ash: use pgetc_eatbnl() in more places, take 2
[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 rootpid;            /* pid of main shell */
388         /* shell level: 0 for the main shell, 1 for its children, and so on */
389         int shlvl;
390 #define rootshell (!shlvl)
391         int errlinno;
392
393         char *minusc;  /* argument to -c option */
394
395         char *curdir; // = nullstr;     /* current working directory */
396         char *physdir; // = nullstr;    /* physical working directory */
397
398         char *arg0; /* value of $0 */
399
400         struct jmploc *exception_handler;
401
402         volatile int suppress_int; /* counter */
403         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
404         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
405         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
406         smallint exception_type; /* kind of exception (0..5) */
407         /* exceptions */
408 #define EXINT 0         /* SIGINT received */
409 #define EXERROR 1       /* a generic error */
410 #define EXEXIT 4        /* exit the shell */
411
412         char nullstr[1];        /* zero length string */
413
414         char optlist[NOPTS];
415 #define eflag optlist[0]
416 #define fflag optlist[1]
417 #define Iflag optlist[2]
418 #define iflag optlist[3]
419 #define mflag optlist[4]
420 #define nflag optlist[5]
421 #define sflag optlist[6]
422 #define cflag optlist[7]
423 #define xflag optlist[8]
424 #define vflag optlist[9]
425 #define Cflag optlist[10]
426 #define aflag optlist[11]
427 #define bflag optlist[12]
428 #define uflag optlist[13]
429 #define viflag optlist[14]
430 #if BASH_PIPEFAIL
431 # define pipefail optlist[15]
432 #else
433 # define pipefail 0
434 #endif
435 #if DEBUG
436 # define nolog optlist[15 + BASH_PIPEFAIL]
437 # define debug optlist[16 + BASH_PIPEFAIL]
438 #endif
439
440         /* trap handler commands */
441         /*
442          * Sigmode records the current value of the signal handlers for the various
443          * modes.  A value of zero means that the current handler is not known.
444          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
445          */
446         char sigmode[NSIG - 1];
447 #define S_DFL      1            /* default signal handling (SIG_DFL) */
448 #define S_CATCH    2            /* signal is caught */
449 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
450 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
451
452         /* indicates specified signal received */
453         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
454         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
455         char *trap[NSIG];
456         char **trap_ptr;        /* used only by "trap hack" */
457
458         /* Rarely referenced stuff */
459 #if ENABLE_ASH_RANDOM_SUPPORT
460         random_t random_gen;
461 #endif
462         pid_t backgndpid;        /* pid of last background process */
463 };
464 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
465 #define G_misc (*ash_ptr_to_globals_misc)
466 #define exitstatus        (G_misc.exitstatus )
467 #define back_exitstatus   (G_misc.back_exitstatus )
468 #define job_warning       (G_misc.job_warning)
469 #define rootpid     (G_misc.rootpid    )
470 #define shlvl       (G_misc.shlvl      )
471 #define errlinno    (G_misc.errlinno   )
472 #define minusc      (G_misc.minusc     )
473 #define curdir      (G_misc.curdir     )
474 #define physdir     (G_misc.physdir    )
475 #define arg0        (G_misc.arg0       )
476 #define exception_handler (G_misc.exception_handler)
477 #define exception_type    (G_misc.exception_type   )
478 #define suppress_int      (G_misc.suppress_int     )
479 #define pending_int       (G_misc.pending_int      )
480 #define got_sigchld       (G_misc.got_sigchld      )
481 #define pending_sig       (G_misc.pending_sig      )
482 #define nullstr     (G_misc.nullstr    )
483 #define optlist     (G_misc.optlist    )
484 #define sigmode     (G_misc.sigmode    )
485 #define gotsig      (G_misc.gotsig     )
486 #define may_have_traps    (G_misc.may_have_traps   )
487 #define trap        (G_misc.trap       )
488 #define trap_ptr    (G_misc.trap_ptr   )
489 #define random_gen  (G_misc.random_gen )
490 #define backgndpid  (G_misc.backgndpid )
491 #define INIT_G_misc() do { \
492         (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \
493         barrier(); \
494         curdir = nullstr; \
495         physdir = nullstr; \
496         trap_ptr = trap; \
497 } while (0)
498
499
500 /* ============ DEBUG */
501 #if DEBUG
502 static void trace_printf(const char *fmt, ...);
503 static void trace_vprintf(const char *fmt, va_list va);
504 # define TRACE(param)    trace_printf param
505 # define TRACEV(param)   trace_vprintf param
506 # define close(fd) do { \
507         int dfd = (fd); \
508         if (close(dfd) < 0) \
509                 bb_error_msg("bug on %d: closing %d(0x%x)", \
510                         __LINE__, dfd, dfd); \
511 } while (0)
512 #else
513 # define TRACE(param)
514 # define TRACEV(param)
515 #endif
516
517
518 /* ============ Utility functions */
519 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
520 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
521
522 static int
523 isdigit_str9(const char *str)
524 {
525         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
526         while (--maxlen && isdigit(*str))
527                 str++;
528         return (*str == '\0');
529 }
530
531 static const char *
532 var_end(const char *var)
533 {
534         while (*var)
535                 if (*var++ == '=')
536                         break;
537         return var;
538 }
539
540
541 /* ============ Interrupts / exceptions */
542
543 static void exitshell(void) NORETURN;
544
545 /*
546  * These macros allow the user to suspend the handling of interrupt signals
547  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
548  * much more efficient and portable.  (But hacking the kernel is so much
549  * more fun than worrying about efficiency and portability. :-))
550  */
551 #if DEBUG_INTONOFF
552 # define INT_OFF do { \
553         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
554         suppress_int++; \
555         barrier(); \
556 } while (0)
557 #else
558 # define INT_OFF do { \
559         suppress_int++; \
560         barrier(); \
561 } while (0)
562 #endif
563
564 /*
565  * Called to raise an exception.  Since C doesn't include exceptions, we
566  * just do a longjmp to the exception handler.  The type of exception is
567  * stored in the global variable "exception_type".
568  */
569 static void raise_exception(int) NORETURN;
570 static void
571 raise_exception(int e)
572 {
573 #if DEBUG
574         if (exception_handler == NULL)
575                 abort();
576 #endif
577         INT_OFF;
578         exception_type = e;
579         longjmp(exception_handler->loc, 1);
580 }
581 #if DEBUG
582 #define raise_exception(e) do { \
583         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
584         raise_exception(e); \
585 } while (0)
586 #endif
587
588 /*
589  * Called when a SIGINT is received.  (If the user specifies
590  * that SIGINT is to be trapped or ignored using the trap builtin, then
591  * this routine is not called.)  Suppressint is nonzero when interrupts
592  * are held using the INT_OFF macro.  (The test for iflag is just
593  * defensive programming.)
594  */
595 static void raise_interrupt(void) NORETURN;
596 static void
597 raise_interrupt(void)
598 {
599         pending_int = 0;
600         /* Signal is not automatically unmasked after it is raised,
601          * do it ourself - unmask all signals */
602         sigprocmask_allsigs(SIG_UNBLOCK);
603         /* pending_sig = 0; - now done in signal_handler() */
604
605         if (!(rootshell && iflag)) {
606                 /* Kill ourself with SIGINT */
607                 signal(SIGINT, SIG_DFL);
608                 raise(SIGINT);
609         }
610         /* bash: ^C even on empty command line sets $? */
611         exitstatus = SIGINT + 128;
612         raise_exception(EXINT);
613         /* NOTREACHED */
614 }
615 #if DEBUG
616 #define raise_interrupt() do { \
617         TRACE(("raising interrupt on line %d\n", __LINE__)); \
618         raise_interrupt(); \
619 } while (0)
620 #endif
621
622 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
623 int_on(void)
624 {
625         barrier();
626         if (--suppress_int == 0 && pending_int) {
627                 raise_interrupt();
628         }
629 }
630 #if DEBUG_INTONOFF
631 # define INT_ON do { \
632         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
633         int_on(); \
634 } while (0)
635 #else
636 # define INT_ON int_on()
637 #endif
638 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
639 force_int_on(void)
640 {
641         barrier();
642         suppress_int = 0;
643         if (pending_int)
644                 raise_interrupt();
645 }
646 #define FORCE_INT_ON force_int_on()
647
648 #define SAVE_INT(v) ((v) = suppress_int)
649
650 #define RESTORE_INT(v) do { \
651         barrier(); \
652         suppress_int = (v); \
653         if (suppress_int == 0 && pending_int) \
654                 raise_interrupt(); \
655 } while (0)
656
657
658 /* ============ Stdout/stderr output */
659
660 static void
661 outstr(const char *p, FILE *file)
662 {
663         INT_OFF;
664         fputs(p, file);
665         INT_ON;
666 }
667
668 static void
669 flush_stdout_stderr(void)
670 {
671         INT_OFF;
672         fflush_all();
673         INT_ON;
674 }
675
676 /* Was called outcslow(c,FILE*), but c was always '\n' */
677 static void
678 newline_and_flush(FILE *dest)
679 {
680         INT_OFF;
681         putc('\n', dest);
682         fflush(dest);
683         INT_ON;
684 }
685
686 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
687 static int
688 out1fmt(const char *fmt, ...)
689 {
690         va_list ap;
691         int r;
692
693         INT_OFF;
694         va_start(ap, fmt);
695         r = vprintf(fmt, ap);
696         va_end(ap);
697         INT_ON;
698         return r;
699 }
700
701 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
702 static int
703 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
704 {
705         va_list ap;
706         int ret;
707
708         INT_OFF;
709         va_start(ap, fmt);
710         ret = vsnprintf(outbuf, length, fmt, ap);
711         va_end(ap);
712         INT_ON;
713         return ret;
714 }
715
716 static void
717 out1str(const char *p)
718 {
719         outstr(p, stdout);
720 }
721
722 static void
723 out2str(const char *p)
724 {
725         outstr(p, stderr);
726         flush_stdout_stderr();
727 }
728
729
730 /* ============ Parser structures */
731
732 /* control characters in argument strings */
733 #define CTL_FIRST CTLESC
734 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
735 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
736 #define CTLENDVAR    ((unsigned char)'\203')
737 #define CTLBACKQ     ((unsigned char)'\204')
738 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
739 #define CTLENDARI    ((unsigned char)'\207')
740 #define CTLQUOTEMARK ((unsigned char)'\210')
741 #define CTL_LAST CTLQUOTEMARK
742
743 /* variable substitution byte (follows CTLVAR) */
744 #define VSTYPE  0x0f            /* type of variable substitution */
745 #define VSNUL   0x10            /* colon--treat the empty string as unset */
746
747 /* values of VSTYPE field */
748 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
749 #define VSMINUS         0x2     /* ${var-text} */
750 #define VSPLUS          0x3     /* ${var+text} */
751 #define VSQUESTION      0x4     /* ${var?message} */
752 #define VSASSIGN        0x5     /* ${var=text} */
753 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
754 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
755 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
756 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
757 #define VSLENGTH        0xa     /* ${#var} */
758 #if BASH_SUBSTR
759 #define VSSUBSTR        0xc     /* ${var:position:length} */
760 #endif
761 #if BASH_PATTERN_SUBST
762 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
763 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
764 #endif
765
766 static const char dolatstr[] ALIGN1 = {
767         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
768 };
769 #define DOLATSTRLEN 6
770
771 #define NCMD      0
772 #define NPIPE     1
773 #define NREDIR    2
774 #define NBACKGND  3
775 #define NSUBSHELL 4
776 #define NAND      5
777 #define NOR       6
778 #define NSEMI     7
779 #define NIF       8
780 #define NWHILE    9
781 #define NUNTIL   10
782 #define NFOR     11
783 #define NCASE    12
784 #define NCLIST   13
785 #define NDEFUN   14
786 #define NARG     15
787 #define NTO      16
788 #if BASH_REDIR_OUTPUT
789 #define NTO2     17
790 #endif
791 #define NCLOBBER 18
792 #define NFROM    19
793 #define NFROMTO  20
794 #define NAPPEND  21
795 #define NTOFD    22
796 #define NFROMFD  23
797 #define NHERE    24
798 #define NXHERE   25
799 #define NNOT     26
800 #define N_NUMBER 27
801
802 union node;
803
804 struct ncmd {
805         smallint type; /* Nxxxx */
806         int linno;
807         union node *assign;
808         union node *args;
809         union node *redirect;
810 };
811
812 struct npipe {
813         smallint type;
814         smallint pipe_backgnd;
815         struct nodelist *cmdlist;
816 };
817
818 struct nredir {
819         smallint type;
820         int linno;
821         union node *n;
822         union node *redirect;
823 };
824
825 struct nbinary {
826         smallint type;
827         union node *ch1;
828         union node *ch2;
829 };
830
831 struct nif {
832         smallint type;
833         union node *test;
834         union node *ifpart;
835         union node *elsepart;
836 };
837
838 struct nfor {
839         smallint type;
840         int linno;
841         union node *args;
842         union node *body;
843         char *var;
844 };
845
846 struct ncase {
847         smallint type;
848         int linno;
849         union node *expr;
850         union node *cases;
851 };
852
853 struct nclist {
854         smallint type;
855         union node *next;
856         union node *pattern;
857         union node *body;
858 };
859
860 struct ndefun {
861         smallint type;
862         int linno;
863         char *text;
864         union node *body;
865 };
866
867 struct narg {
868         smallint type;
869         union node *next;
870         char *text;
871         struct nodelist *backquote;
872 };
873
874 /* nfile and ndup layout must match!
875  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
876  * that it is actually NTO2 (>&file), and change its type.
877  */
878 struct nfile {
879         smallint type;
880         union node *next;
881         int fd;
882         int _unused_dupfd;
883         union node *fname;
884         char *expfname;
885 };
886
887 struct ndup {
888         smallint type;
889         union node *next;
890         int fd;
891         int dupfd;
892         union node *vname;
893         char *_unused_expfname;
894 };
895
896 struct nhere {
897         smallint type;
898         union node *next;
899         int fd;
900         union node *doc;
901 };
902
903 struct nnot {
904         smallint type;
905         union node *com;
906 };
907
908 union node {
909         smallint type;
910         struct ncmd ncmd;
911         struct npipe npipe;
912         struct nredir nredir;
913         struct nbinary nbinary;
914         struct nif nif;
915         struct nfor nfor;
916         struct ncase ncase;
917         struct nclist nclist;
918         struct ndefun ndefun;
919         struct narg narg;
920         struct nfile nfile;
921         struct ndup ndup;
922         struct nhere nhere;
923         struct nnot nnot;
924 };
925
926 /*
927  * NODE_EOF is returned by parsecmd when it encounters an end of file.
928  * It must be distinct from NULL.
929  */
930 #define NODE_EOF ((union node *) -1L)
931
932 struct nodelist {
933         struct nodelist *next;
934         union node *n;
935 };
936
937 struct funcnode {
938         int count;
939         union node n;
940 };
941
942 /*
943  * Free a parse tree.
944  */
945 static void
946 freefunc(struct funcnode *f)
947 {
948         if (f && --f->count < 0)
949                 free(f);
950 }
951
952
953 /* ============ Debugging output */
954
955 #if DEBUG
956
957 static FILE *tracefile;
958
959 static void
960 trace_printf(const char *fmt, ...)
961 {
962         va_list va;
963
964         if (debug != 1)
965                 return;
966         if (DEBUG_TIME)
967                 fprintf(tracefile, "%u ", (int) time(NULL));
968         if (DEBUG_PID)
969                 fprintf(tracefile, "[%u] ", (int) getpid());
970         if (DEBUG_SIG)
971                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
972         va_start(va, fmt);
973         vfprintf(tracefile, fmt, va);
974         va_end(va);
975 }
976
977 static void
978 trace_vprintf(const char *fmt, va_list va)
979 {
980         if (debug != 1)
981                 return;
982         vfprintf(tracefile, fmt, va);
983         fprintf(tracefile, "\n");
984 }
985
986 static void
987 trace_puts(const char *s)
988 {
989         if (debug != 1)
990                 return;
991         fputs(s, tracefile);
992 }
993
994 static void
995 trace_puts_quoted(char *s)
996 {
997         char *p;
998         char c;
999
1000         if (debug != 1)
1001                 return;
1002         putc('"', tracefile);
1003         for (p = s; *p; p++) {
1004                 switch ((unsigned char)*p) {
1005                 case '\n': c = 'n'; goto backslash;
1006                 case '\t': c = 't'; goto backslash;
1007                 case '\r': c = 'r'; goto backslash;
1008                 case '\"': c = '\"'; goto backslash;
1009                 case '\\': c = '\\'; goto backslash;
1010                 case CTLESC: c = 'e'; goto backslash;
1011                 case CTLVAR: c = 'v'; goto backslash;
1012                 case CTLBACKQ: c = 'q'; goto backslash;
1013  backslash:
1014                         putc('\\', tracefile);
1015                         putc(c, tracefile);
1016                         break;
1017                 default:
1018                         if (*p >= ' ' && *p <= '~')
1019                                 putc(*p, tracefile);
1020                         else {
1021                                 putc('\\', tracefile);
1022                                 putc((*p >> 6) & 03, tracefile);
1023                                 putc((*p >> 3) & 07, tracefile);
1024                                 putc(*p & 07, tracefile);
1025                         }
1026                         break;
1027                 }
1028         }
1029         putc('"', tracefile);
1030 }
1031
1032 static void
1033 trace_puts_args(char **ap)
1034 {
1035         if (debug != 1)
1036                 return;
1037         if (!*ap)
1038                 return;
1039         while (1) {
1040                 trace_puts_quoted(*ap);
1041                 if (!*++ap) {
1042                         putc('\n', tracefile);
1043                         break;
1044                 }
1045                 putc(' ', tracefile);
1046         }
1047 }
1048
1049 static void
1050 opentrace(void)
1051 {
1052         char s[100];
1053 #ifdef O_APPEND
1054         int flags;
1055 #endif
1056
1057         if (debug != 1) {
1058                 if (tracefile)
1059                         fflush(tracefile);
1060                 /* leave open because libedit might be using it */
1061                 return;
1062         }
1063         strcpy(s, "./trace");
1064         if (tracefile) {
1065                 if (!freopen(s, "a", tracefile)) {
1066                         fprintf(stderr, "Can't re-open %s\n", s);
1067                         debug = 0;
1068                         return;
1069                 }
1070         } else {
1071                 tracefile = fopen(s, "a");
1072                 if (tracefile == NULL) {
1073                         fprintf(stderr, "Can't open %s\n", s);
1074                         debug = 0;
1075                         return;
1076                 }
1077         }
1078 #ifdef O_APPEND
1079         flags = fcntl(fileno(tracefile), F_GETFL);
1080         if (flags >= 0)
1081                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1082 #endif
1083         setlinebuf(tracefile);
1084         fputs("\nTracing started.\n", tracefile);
1085 }
1086
1087 static void
1088 indent(int amount, char *pfx, FILE *fp)
1089 {
1090         int i;
1091
1092         for (i = 0; i < amount; i++) {
1093                 if (pfx && i == amount - 1)
1094                         fputs(pfx, fp);
1095                 putc('\t', fp);
1096         }
1097 }
1098
1099 /* little circular references here... */
1100 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1101
1102 static void
1103 sharg(union node *arg, FILE *fp)
1104 {
1105         char *p;
1106         struct nodelist *bqlist;
1107         unsigned char subtype;
1108
1109         if (arg->type != NARG) {
1110                 out1fmt("<node type %d>\n", arg->type);
1111                 abort();
1112         }
1113         bqlist = arg->narg.backquote;
1114         for (p = arg->narg.text; *p; p++) {
1115                 switch ((unsigned char)*p) {
1116                 case CTLESC:
1117                         p++;
1118                         putc(*p, fp);
1119                         break;
1120                 case CTLVAR:
1121                         putc('$', fp);
1122                         putc('{', fp);
1123                         subtype = *++p;
1124                         if (subtype == VSLENGTH)
1125                                 putc('#', fp);
1126
1127                         while (*p != '=') {
1128                                 putc(*p, fp);
1129                                 p++;
1130                         }
1131
1132                         if (subtype & VSNUL)
1133                                 putc(':', fp);
1134
1135                         switch (subtype & VSTYPE) {
1136                         case VSNORMAL:
1137                                 putc('}', fp);
1138                                 break;
1139                         case VSMINUS:
1140                                 putc('-', fp);
1141                                 break;
1142                         case VSPLUS:
1143                                 putc('+', fp);
1144                                 break;
1145                         case VSQUESTION:
1146                                 putc('?', fp);
1147                                 break;
1148                         case VSASSIGN:
1149                                 putc('=', fp);
1150                                 break;
1151                         case VSTRIMLEFT:
1152                                 putc('#', fp);
1153                                 break;
1154                         case VSTRIMLEFTMAX:
1155                                 putc('#', fp);
1156                                 putc('#', fp);
1157                                 break;
1158                         case VSTRIMRIGHT:
1159                                 putc('%', fp);
1160                                 break;
1161                         case VSTRIMRIGHTMAX:
1162                                 putc('%', fp);
1163                                 putc('%', fp);
1164                                 break;
1165                         case VSLENGTH:
1166                                 break;
1167                         default:
1168                                 out1fmt("<subtype %d>", subtype);
1169                         }
1170                         break;
1171                 case CTLENDVAR:
1172                         putc('}', fp);
1173                         break;
1174                 case CTLBACKQ:
1175                         putc('$', fp);
1176                         putc('(', fp);
1177                         shtree(bqlist->n, -1, NULL, fp);
1178                         putc(')', fp);
1179                         break;
1180                 default:
1181                         putc(*p, fp);
1182                         break;
1183                 }
1184         }
1185 }
1186
1187 static void
1188 shcmd(union node *cmd, FILE *fp)
1189 {
1190         union node *np;
1191         int first;
1192         const char *s;
1193         int dftfd;
1194
1195         first = 1;
1196         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1197                 if (!first)
1198                         putc(' ', fp);
1199                 sharg(np, fp);
1200                 first = 0;
1201         }
1202         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1203                 if (!first)
1204                         putc(' ', fp);
1205                 dftfd = 0;
1206                 switch (np->nfile.type) {
1207                 case NTO:      s = ">>"+1; dftfd = 1; break;
1208                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1209                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1210 #if BASH_REDIR_OUTPUT
1211                 case NTO2:
1212 #endif
1213                 case NTOFD:    s = ">&"; dftfd = 1; break;
1214                 case NFROM:    s = "<"; break;
1215                 case NFROMFD:  s = "<&"; break;
1216                 case NFROMTO:  s = "<>"; break;
1217                 default:       s = "*error*"; break;
1218                 }
1219                 if (np->nfile.fd != dftfd)
1220                         fprintf(fp, "%d", np->nfile.fd);
1221                 fputs(s, fp);
1222                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1223                         fprintf(fp, "%d", np->ndup.dupfd);
1224                 } else {
1225                         sharg(np->nfile.fname, fp);
1226                 }
1227                 first = 0;
1228         }
1229 }
1230
1231 static void
1232 shtree(union node *n, int ind, char *pfx, FILE *fp)
1233 {
1234         struct nodelist *lp;
1235         const char *s;
1236
1237         if (n == NULL)
1238                 return;
1239
1240         indent(ind, pfx, fp);
1241
1242         if (n == NODE_EOF) {
1243                 fputs("<EOF>", fp);
1244                 return;
1245         }
1246
1247         switch (n->type) {
1248         case NSEMI:
1249                 s = "; ";
1250                 goto binop;
1251         case NAND:
1252                 s = " && ";
1253                 goto binop;
1254         case NOR:
1255                 s = " || ";
1256  binop:
1257                 shtree(n->nbinary.ch1, ind, NULL, fp);
1258                 /* if (ind < 0) */
1259                         fputs(s, fp);
1260                 shtree(n->nbinary.ch2, ind, NULL, fp);
1261                 break;
1262         case NCMD:
1263                 shcmd(n, fp);
1264                 if (ind >= 0)
1265                         putc('\n', fp);
1266                 break;
1267         case NPIPE:
1268                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1269                         shtree(lp->n, 0, NULL, fp);
1270                         if (lp->next)
1271                                 fputs(" | ", fp);
1272                 }
1273                 if (n->npipe.pipe_backgnd)
1274                         fputs(" &", fp);
1275                 if (ind >= 0)
1276                         putc('\n', fp);
1277                 break;
1278         default:
1279                 fprintf(fp, "<node type %d>", n->type);
1280                 if (ind >= 0)
1281                         putc('\n', fp);
1282                 break;
1283         }
1284 }
1285
1286 static void
1287 showtree(union node *n)
1288 {
1289         trace_puts("showtree called\n");
1290         shtree(n, 1, NULL, stderr);
1291 }
1292
1293 #endif /* DEBUG */
1294
1295
1296 /* ============ Parser data */
1297
1298 /*
1299  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1300  */
1301 struct strlist {
1302         struct strlist *next;
1303         char *text;
1304 };
1305
1306 struct alias;
1307
1308 struct strpush {
1309         struct strpush *prev;   /* preceding string on stack */
1310         char *prev_string;
1311         int prev_left_in_line;
1312 #if ENABLE_ASH_ALIAS
1313         struct alias *ap;       /* if push was associated with an alias */
1314 #endif
1315         char *string;           /* remember the string since it may change */
1316
1317         /* Remember last two characters for pungetc. */
1318         int lastc[2];
1319
1320         /* Number of outstanding calls to pungetc. */
1321         int unget;
1322 };
1323
1324 /*
1325  * The parsefile structure pointed to by the global variable parsefile
1326  * contains information about the current file being read.
1327  */
1328 struct parsefile {
1329         struct parsefile *prev; /* preceding file on stack */
1330         int linno;              /* current line */
1331         int pf_fd;              /* file descriptor (or -1 if string) */
1332         int left_in_line;       /* number of chars left in this line */
1333         int left_in_buffer;     /* number of chars left in this buffer past the line */
1334         char *next_to_pgetc;    /* next char in buffer */
1335         char *buf;              /* input buffer */
1336         struct strpush *strpush; /* for pushing strings at this level */
1337         struct strpush basestrpush; /* so pushing one is fast */
1338
1339         /* Remember last two characters for pungetc. */
1340         int lastc[2];
1341
1342         /* Number of outstanding calls to pungetc. */
1343         int unget;
1344 };
1345
1346 static struct parsefile basepf;        /* top level input file */
1347 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1348 static char *commandname;              /* currently executing command */
1349
1350
1351 /* ============ Message printing */
1352
1353 static void
1354 ash_vmsg(const char *msg, va_list ap)
1355 {
1356         fprintf(stderr, "%s: ", arg0);
1357         if (commandname) {
1358                 if (strcmp(arg0, commandname))
1359                         fprintf(stderr, "%s: ", commandname);
1360                 if (!iflag || g_parsefile->pf_fd > 0)
1361                         fprintf(stderr, "line %d: ", errlinno);
1362         }
1363         vfprintf(stderr, msg, ap);
1364         newline_and_flush(stderr);
1365 }
1366
1367 /*
1368  * Exverror is called to raise the error exception.  If the second argument
1369  * is not NULL then error prints an error message using printf style
1370  * formatting.  It then raises the error exception.
1371  */
1372 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1373 static void
1374 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1375 {
1376 #if DEBUG
1377         if (msg) {
1378                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1379                 TRACEV((msg, ap));
1380         } else
1381                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1382         if (msg)
1383 #endif
1384                 ash_vmsg(msg, ap);
1385
1386         flush_stdout_stderr();
1387         raise_exception(cond);
1388         /* NOTREACHED */
1389 }
1390
1391 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1392 static void
1393 ash_msg_and_raise_error(const char *msg, ...)
1394 {
1395         va_list ap;
1396
1397         exitstatus = 2;
1398
1399         va_start(ap, msg);
1400         ash_vmsg_and_raise(EXERROR, msg, ap);
1401         /* NOTREACHED */
1402         va_end(ap);
1403 }
1404
1405 /*
1406  * 'fmt' must be a string literal.
1407  */
1408 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1409
1410 static void raise_error_syntax(const char *) NORETURN;
1411 static void
1412 raise_error_syntax(const char *msg)
1413 {
1414         errlinno = g_parsefile->linno;
1415         ash_msg_and_raise_error("syntax error: %s", msg);
1416         /* NOTREACHED */
1417 }
1418
1419 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1420 static void
1421 ash_msg_and_raise(int cond, const char *msg, ...)
1422 {
1423         va_list ap;
1424
1425         va_start(ap, msg);
1426         ash_vmsg_and_raise(cond, msg, ap);
1427         /* NOTREACHED */
1428         va_end(ap);
1429 }
1430
1431 /*
1432  * error/warning routines for external builtins
1433  */
1434 static void
1435 ash_msg(const char *fmt, ...)
1436 {
1437         va_list ap;
1438
1439         va_start(ap, fmt);
1440         ash_vmsg(fmt, ap);
1441         va_end(ap);
1442 }
1443
1444 /*
1445  * Return a string describing an error.  The returned string may be a
1446  * pointer to a static buffer that will be overwritten on the next call.
1447  * Action describes the operation that got the error.
1448  */
1449 static const char *
1450 errmsg(int e, const char *em)
1451 {
1452         if (e == ENOENT || e == ENOTDIR) {
1453                 return em;
1454         }
1455         return strerror(e);
1456 }
1457
1458
1459 /* ============ Memory allocation */
1460
1461 #if 0
1462 /* I consider these wrappers nearly useless:
1463  * ok, they return you to nearest exception handler, but
1464  * how much memory do you leak in the process, making
1465  * memory starvation worse?
1466  */
1467 static void *
1468 ckrealloc(void * p, size_t nbytes)
1469 {
1470         p = realloc(p, nbytes);
1471         if (!p)
1472                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1473         return p;
1474 }
1475
1476 static void *
1477 ckmalloc(size_t nbytes)
1478 {
1479         return ckrealloc(NULL, nbytes);
1480 }
1481
1482 static void *
1483 ckzalloc(size_t nbytes)
1484 {
1485         return memset(ckmalloc(nbytes), 0, nbytes);
1486 }
1487
1488 static char *
1489 ckstrdup(const char *s)
1490 {
1491         char *p = strdup(s);
1492         if (!p)
1493                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1494         return p;
1495 }
1496 #else
1497 /* Using bbox equivalents. They exit if out of memory */
1498 # define ckrealloc xrealloc
1499 # define ckmalloc  xmalloc
1500 # define ckzalloc  xzalloc
1501 # define ckstrdup  xstrdup
1502 #endif
1503
1504 /*
1505  * It appears that grabstackstr() will barf with such alignments
1506  * because stalloc() will return a string allocated in a new stackblock.
1507  */
1508 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1509 enum {
1510         /* Most machines require the value returned from malloc to be aligned
1511          * in some way.  The following macro will get this right
1512          * on many machines.  */
1513         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1514         /* Minimum size of a block */
1515         MINSIZE = SHELL_ALIGN(504),
1516 };
1517
1518 struct stack_block {
1519         struct stack_block *prev;
1520         char space[MINSIZE];
1521 };
1522
1523 struct stackmark {
1524         struct stack_block *stackp;
1525         char *stacknxt;
1526         size_t stacknleft;
1527 };
1528
1529
1530 struct globals_memstack {
1531         struct stack_block *g_stackp; // = &stackbase;
1532         char *g_stacknxt; // = stackbase.space;
1533         char *sstrend; // = stackbase.space + MINSIZE;
1534         size_t g_stacknleft; // = MINSIZE;
1535         struct stack_block stackbase;
1536 };
1537 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1538 #define G_memstack (*ash_ptr_to_globals_memstack)
1539 #define g_stackp     (G_memstack.g_stackp    )
1540 #define g_stacknxt   (G_memstack.g_stacknxt  )
1541 #define sstrend      (G_memstack.sstrend     )
1542 #define g_stacknleft (G_memstack.g_stacknleft)
1543 #define stackbase    (G_memstack.stackbase   )
1544 #define INIT_G_memstack() do { \
1545         (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \
1546         barrier(); \
1547         g_stackp = &stackbase; \
1548         g_stacknxt = stackbase.space; \
1549         g_stacknleft = MINSIZE; \
1550         sstrend = stackbase.space + MINSIZE; \
1551 } while (0)
1552
1553
1554 #define stackblock()     ((void *)g_stacknxt)
1555 #define stackblocksize() g_stacknleft
1556
1557 /*
1558  * Parse trees for commands are allocated in lifo order, so we use a stack
1559  * to make this more efficient, and also to avoid all sorts of exception
1560  * handling code to handle interrupts in the middle of a parse.
1561  *
1562  * The size 504 was chosen because the Ultrix malloc handles that size
1563  * well.
1564  */
1565 static void *
1566 stalloc(size_t nbytes)
1567 {
1568         char *p;
1569         size_t aligned;
1570
1571         aligned = SHELL_ALIGN(nbytes);
1572         if (aligned > g_stacknleft) {
1573                 size_t len;
1574                 size_t blocksize;
1575                 struct stack_block *sp;
1576
1577                 blocksize = aligned;
1578                 if (blocksize < MINSIZE)
1579                         blocksize = MINSIZE;
1580                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1581                 if (len < blocksize)
1582                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1583                 INT_OFF;
1584                 sp = ckmalloc(len);
1585                 sp->prev = g_stackp;
1586                 g_stacknxt = sp->space;
1587                 g_stacknleft = blocksize;
1588                 sstrend = g_stacknxt + blocksize;
1589                 g_stackp = sp;
1590                 INT_ON;
1591         }
1592         p = g_stacknxt;
1593         g_stacknxt += aligned;
1594         g_stacknleft -= aligned;
1595         return p;
1596 }
1597
1598 static void *
1599 stzalloc(size_t nbytes)
1600 {
1601         return memset(stalloc(nbytes), 0, nbytes);
1602 }
1603
1604 static void
1605 stunalloc(void *p)
1606 {
1607 #if DEBUG
1608         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1609                 write(STDERR_FILENO, "stunalloc\n", 10);
1610                 abort();
1611         }
1612 #endif
1613         g_stacknleft += g_stacknxt - (char *)p;
1614         g_stacknxt = p;
1615 }
1616
1617 /*
1618  * Like strdup but works with the ash stack.
1619  */
1620 static char *
1621 sstrdup(const char *p)
1622 {
1623         size_t len = strlen(p) + 1;
1624         return memcpy(stalloc(len), p, len);
1625 }
1626
1627 static ALWAYS_INLINE void
1628 grabstackblock(size_t len)
1629 {
1630         stalloc(len);
1631 }
1632
1633 static void
1634 pushstackmark(struct stackmark *mark, size_t len)
1635 {
1636         mark->stackp = g_stackp;
1637         mark->stacknxt = g_stacknxt;
1638         mark->stacknleft = g_stacknleft;
1639         grabstackblock(len);
1640 }
1641
1642 static void
1643 setstackmark(struct stackmark *mark)
1644 {
1645         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1646 }
1647
1648 static void
1649 popstackmark(struct stackmark *mark)
1650 {
1651         struct stack_block *sp;
1652
1653         if (!mark->stackp)
1654                 return;
1655
1656         INT_OFF;
1657         while (g_stackp != mark->stackp) {
1658                 sp = g_stackp;
1659                 g_stackp = sp->prev;
1660                 free(sp);
1661         }
1662         g_stacknxt = mark->stacknxt;
1663         g_stacknleft = mark->stacknleft;
1664         sstrend = mark->stacknxt + mark->stacknleft;
1665         INT_ON;
1666 }
1667
1668 /*
1669  * When the parser reads in a string, it wants to stick the string on the
1670  * stack and only adjust the stack pointer when it knows how big the
1671  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1672  * of space on top of the stack and stackblocklen returns the length of
1673  * this block.  Growstackblock will grow this space by at least one byte,
1674  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1675  * part of the block that has been used.
1676  */
1677 static void
1678 growstackblock(void)
1679 {
1680         size_t newlen;
1681
1682         newlen = g_stacknleft * 2;
1683         if (newlen < g_stacknleft)
1684                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1685         if (newlen < 128)
1686                 newlen += 128;
1687
1688         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1689                 struct stack_block *sp;
1690                 struct stack_block *prevstackp;
1691                 size_t grosslen;
1692
1693                 INT_OFF;
1694                 sp = g_stackp;
1695                 prevstackp = sp->prev;
1696                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1697                 sp = ckrealloc(sp, grosslen);
1698                 sp->prev = prevstackp;
1699                 g_stackp = sp;
1700                 g_stacknxt = sp->space;
1701                 g_stacknleft = newlen;
1702                 sstrend = sp->space + newlen;
1703                 INT_ON;
1704         } else {
1705                 char *oldspace = g_stacknxt;
1706                 size_t oldlen = g_stacknleft;
1707                 char *p = stalloc(newlen);
1708
1709                 /* free the space we just allocated */
1710                 g_stacknxt = memcpy(p, oldspace, oldlen);
1711                 g_stacknleft += newlen;
1712         }
1713 }
1714
1715 /*
1716  * The following routines are somewhat easier to use than the above.
1717  * The user declares a variable of type STACKSTR, which may be declared
1718  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1719  * the user uses the macro STPUTC to add characters to the string.  In
1720  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1721  * grown as necessary.  When the user is done, she can just leave the
1722  * string there and refer to it using stackblock().  Or she can allocate
1723  * the space for it using grabstackstr().  If it is necessary to allow
1724  * someone else to use the stack temporarily and then continue to grow
1725  * the string, the user should use grabstack to allocate the space, and
1726  * then call ungrabstr(p) to return to the previous mode of operation.
1727  *
1728  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1729  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1730  * is space for at least one character.
1731  */
1732 static void *
1733 growstackstr(void)
1734 {
1735         size_t len = stackblocksize();
1736         growstackblock();
1737         return (char *)stackblock() + len;
1738 }
1739
1740 /*
1741  * Called from CHECKSTRSPACE.
1742  */
1743 static char *
1744 makestrspace(size_t newlen, char *p)
1745 {
1746         size_t len = p - g_stacknxt;
1747         size_t size;
1748
1749         for (;;) {
1750                 size_t nleft;
1751
1752                 size = stackblocksize();
1753                 nleft = size - len;
1754                 if (nleft >= newlen)
1755                         break;
1756                 growstackblock();
1757         }
1758         return (char *)stackblock() + len;
1759 }
1760
1761 static char *
1762 stack_nputstr(const char *s, size_t n, char *p)
1763 {
1764         p = makestrspace(n, p);
1765         p = (char *)mempcpy(p, s, n);
1766         return p;
1767 }
1768
1769 static char *
1770 stack_putstr(const char *s, char *p)
1771 {
1772         return stack_nputstr(s, strlen(s), p);
1773 }
1774
1775 static char *
1776 _STPUTC(int c, char *p)
1777 {
1778         if (p == sstrend)
1779                 p = growstackstr();
1780         *p++ = c;
1781         return p;
1782 }
1783
1784 #define STARTSTACKSTR(p)        ((p) = stackblock())
1785 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1786 #define CHECKSTRSPACE(n, p) do { \
1787         char *q = (p); \
1788         size_t l = (n); \
1789         size_t m = sstrend - q; \
1790         if (l > m) \
1791                 (p) = makestrspace(l, q); \
1792 } while (0)
1793 #define USTPUTC(c, p)           (*(p)++ = (c))
1794 #define STACKSTRNUL(p) do { \
1795         if ((p) == sstrend) \
1796                 (p) = growstackstr(); \
1797         *(p) = '\0'; \
1798 } while (0)
1799 #define STUNPUTC(p)             (--(p))
1800 #define STTOPC(p)               ((p)[-1])
1801 #define STADJUST(amount, p)     ((p) += (amount))
1802
1803 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1804 #define ungrabstackstr(s, p)    stunalloc(s)
1805 #define stackstrend()           ((void *)sstrend)
1806
1807
1808 /* ============ String helpers */
1809
1810 /*
1811  * prefix -- see if pfx is a prefix of string.
1812  */
1813 static char *
1814 prefix(const char *string, const char *pfx)
1815 {
1816         while (*pfx) {
1817                 if (*pfx++ != *string++)
1818                         return NULL;
1819         }
1820         return (char *) string;
1821 }
1822
1823 /*
1824  * Check for a valid number.  This should be elsewhere.
1825  */
1826 static int
1827 is_number(const char *p)
1828 {
1829         do {
1830                 if (!isdigit(*p))
1831                         return 0;
1832         } while (*++p != '\0');
1833         return 1;
1834 }
1835
1836 /*
1837  * Convert a string of digits to an integer, printing an error message on
1838  * failure.
1839  */
1840 static int
1841 number(const char *s)
1842 {
1843         if (!is_number(s))
1844                 ash_msg_and_raise_error(msg_illnum, s);
1845         return atoi(s);
1846 }
1847
1848 /*
1849  * Produce a single quoted string suitable as input to the shell.
1850  * The return string is allocated on the stack.
1851  */
1852 static char *
1853 single_quote(const char *s)
1854 {
1855         char *p;
1856
1857         STARTSTACKSTR(p);
1858
1859         do {
1860                 char *q;
1861                 size_t len;
1862
1863                 len = strchrnul(s, '\'') - s;
1864
1865                 q = p = makestrspace(len + 3, p);
1866
1867                 *q++ = '\'';
1868                 q = (char *)mempcpy(q, s, len);
1869                 *q++ = '\'';
1870                 s += len;
1871
1872                 STADJUST(q - p, p);
1873
1874                 if (*s != '\'')
1875                         break;
1876                 len = 0;
1877                 do len++; while (*++s == '\'');
1878
1879                 q = p = makestrspace(len + 3, p);
1880
1881                 *q++ = '"';
1882                 q = (char *)mempcpy(q, s - len, len);
1883                 *q++ = '"';
1884
1885                 STADJUST(q - p, p);
1886         } while (*s);
1887
1888         USTPUTC('\0', p);
1889
1890         return stackblock();
1891 }
1892
1893 /*
1894  * Produce a possibly single quoted string suitable as input to the shell.
1895  * If quoting was done, the return string is allocated on the stack,
1896  * otherwise a pointer to the original string is returned.
1897  */
1898 static const char *
1899 maybe_single_quote(const char *s)
1900 {
1901         const char *p = s;
1902
1903         while (*p) {
1904                 /* Assuming ACSII */
1905                 /* quote ctrl_chars space !"#$%&'()* */
1906                 if (*p < '+')
1907                         goto need_quoting;
1908                 /* quote ;<=>? */
1909                 if (*p >= ';' && *p <= '?')
1910                         goto need_quoting;
1911                 /* quote `[\ */
1912                 if (*p == '`')
1913                         goto need_quoting;
1914                 if (*p == '[')
1915                         goto need_quoting;
1916                 if (*p == '\\')
1917                         goto need_quoting;
1918                 /* quote {|}~ DEL and high bytes */
1919                 if (*p > 'z')
1920                         goto need_quoting;
1921                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1922                 /* TODO: maybe avoid quoting % */
1923                 p++;
1924         }
1925         return s;
1926
1927  need_quoting:
1928         return single_quote(s);
1929 }
1930
1931
1932 /* ============ nextopt */
1933
1934 static char **argptr;                  /* argument list for builtin commands */
1935 static char *optionarg;                /* set by nextopt (like getopt) */
1936 static char *optptr;                   /* used by nextopt */
1937
1938 /*
1939  * XXX - should get rid of. Have all builtins use getopt(3).
1940  * The library getopt must have the BSD extension static variable
1941  * "optreset", otherwise it can't be used within the shell safely.
1942  *
1943  * Standard option processing (a la getopt) for builtin routines.
1944  * The only argument that is passed to nextopt is the option string;
1945  * the other arguments are unnecessary. It returns the character,
1946  * or '\0' on end of input.
1947  */
1948 static int
1949 nextopt(const char *optstring)
1950 {
1951         char *p;
1952         const char *q;
1953         char c;
1954
1955         p = optptr;
1956         if (p == NULL || *p == '\0') {
1957                 /* We ate entire "-param", take next one */
1958                 p = *argptr;
1959                 if (p == NULL)
1960                         return '\0';
1961                 if (*p != '-')
1962                         return '\0';
1963                 if (*++p == '\0') /* just "-" ? */
1964                         return '\0';
1965                 argptr++;
1966                 if (LONE_DASH(p)) /* "--" ? */
1967                         return '\0';
1968                 /* p => next "-param" */
1969         }
1970         /* p => some option char in the middle of a "-param" */
1971         c = *p++;
1972         for (q = optstring; *q != c;) {
1973                 if (*q == '\0')
1974                         ash_msg_and_raise_error("illegal option -%c", c);
1975                 if (*++q == ':')
1976                         q++;
1977         }
1978         if (*++q == ':') {
1979                 if (*p == '\0') {
1980                         p = *argptr++;
1981                         if (p == NULL)
1982                                 ash_msg_and_raise_error("no arg for -%c option", c);
1983                 }
1984                 optionarg = p;
1985                 p = NULL;
1986         }
1987         optptr = p;
1988         return c;
1989 }
1990
1991
1992 /* ============ Shell variables */
1993
1994 struct shparam {
1995         int nparam;             /* # of positional parameters (without $0) */
1996 #if ENABLE_ASH_GETOPTS
1997         int optind;             /* next parameter to be processed by getopts */
1998         int optoff;             /* used by getopts */
1999 #endif
2000         unsigned char malloced; /* if parameter list dynamically allocated */
2001         char **p;               /* parameter list */
2002 };
2003
2004 /*
2005  * Free the list of positional parameters.
2006  */
2007 static void
2008 freeparam(volatile struct shparam *param)
2009 {
2010         if (param->malloced) {
2011                 char **ap, **ap1;
2012                 ap = ap1 = param->p;
2013                 while (*ap)
2014                         free(*ap++);
2015                 free(ap1);
2016         }
2017 }
2018
2019 #if ENABLE_ASH_GETOPTS
2020 static void FAST_FUNC getoptsreset(const char *value);
2021 #endif
2022
2023 struct var {
2024         struct var *next;               /* next entry in hash list */
2025         int flags;                      /* flags are defined above */
2026         const char *var_text;           /* name=value */
2027         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
2028                                         /* the variable gets set/unset */
2029 };
2030
2031 struct localvar {
2032         struct localvar *next;          /* next local variable in list */
2033         struct var *vp;                 /* the variable that was made local */
2034         int flags;                      /* saved flags */
2035         const char *text;               /* saved text */
2036 };
2037
2038 /* flags */
2039 #define VEXPORT         0x01    /* variable is exported */
2040 #define VREADONLY       0x02    /* variable cannot be modified */
2041 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
2042 #define VTEXTFIXED      0x08    /* text is statically allocated */
2043 #define VSTACK          0x10    /* text is allocated on the stack */
2044 #define VUNSET          0x20    /* the variable is not set */
2045 #define VNOFUNC         0x40    /* don't call the callback function */
2046 #define VNOSET          0x80    /* do not set variable - just readonly test */
2047 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2048 #if ENABLE_ASH_RANDOM_SUPPORT
2049 # define VDYNAMIC       0x200   /* dynamic variable */
2050 #else
2051 # define VDYNAMIC       0
2052 #endif
2053
2054
2055 /* Need to be before varinit_data[] */
2056 #if ENABLE_LOCALE_SUPPORT
2057 static void FAST_FUNC
2058 change_lc_all(const char *value)
2059 {
2060         if (value && *value != '\0')
2061                 setlocale(LC_ALL, value);
2062 }
2063 static void FAST_FUNC
2064 change_lc_ctype(const char *value)
2065 {
2066         if (value && *value != '\0')
2067                 setlocale(LC_CTYPE, value);
2068 }
2069 #endif
2070 #if ENABLE_ASH_MAIL
2071 static void chkmail(void);
2072 static void changemail(const char *var_value) FAST_FUNC;
2073 #else
2074 # define chkmail()  ((void)0)
2075 #endif
2076 static void changepath(const char *) FAST_FUNC;
2077 #if ENABLE_ASH_RANDOM_SUPPORT
2078 static void change_random(const char *) FAST_FUNC;
2079 #endif
2080 #if BASH_EPOCH_VARS
2081 static void change_seconds(const char *) FAST_FUNC;
2082 static void change_realtime(const char *) FAST_FUNC;
2083 #endif
2084
2085 static const struct {
2086         int flags;
2087         const char *var_text;
2088         void (*var_func)(const char *) FAST_FUNC;
2089 } varinit_data[] = {
2090         /*
2091          * Note: VEXPORT would not work correctly here for NOFORK applets:
2092          * some environment strings may be constant.
2093          */
2094         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2095 #if ENABLE_ASH_MAIL
2096         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2097         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2098 #endif
2099         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2100         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2101         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2102         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2103 #if ENABLE_ASH_GETOPTS
2104         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2105 #endif
2106         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2107 #if ENABLE_ASH_RANDOM_SUPPORT
2108         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2109 #endif
2110 #if BASH_EPOCH_VARS
2111         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHSECONDS", change_seconds },
2112         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHREALTIME", change_realtime },
2113 #endif
2114 #if ENABLE_LOCALE_SUPPORT
2115         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2116         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2117 #endif
2118 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2119         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2120 #endif
2121 };
2122
2123 struct redirtab;
2124
2125 struct globals_var {
2126         struct shparam shellparam;      /* $@ current positional parameters */
2127         struct redirtab *redirlist;
2128         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2129         struct var *vartab[VTABSIZE];
2130         struct var varinit[ARRAY_SIZE(varinit_data)];
2131         int lineno;
2132         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2133 };
2134 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2135 #define G_var (*ash_ptr_to_globals_var)
2136 #define shellparam    (G_var.shellparam   )
2137 //#define redirlist     (G_var.redirlist    )
2138 #define preverrout_fd (G_var.preverrout_fd)
2139 #define vartab        (G_var.vartab       )
2140 #define varinit       (G_var.varinit      )
2141 #define lineno        (G_var.lineno       )
2142 #define linenovar     (G_var.linenovar    )
2143 #define vifs      varinit[0]
2144 #if ENABLE_ASH_MAIL
2145 # define vmail    varinit[1]
2146 # define vmpath   varinit[2]
2147 #endif
2148 #define VAR_OFFSET1 (ENABLE_ASH_MAIL*2)
2149 #define vpath     varinit[VAR_OFFSET1 + 1]
2150 #define vps1      varinit[VAR_OFFSET1 + 2]
2151 #define vps2      varinit[VAR_OFFSET1 + 3]
2152 #define vps4      varinit[VAR_OFFSET1 + 4]
2153 #if ENABLE_ASH_GETOPTS
2154 # define voptind  varinit[VAR_OFFSET1 + 5]
2155 #endif
2156 #define VAR_OFFSET2 (VAR_OFFSET1 + ENABLE_ASH_GETOPTS)
2157 #define vlineno   varinit[VAR_OFFSET2 + 5]
2158 #if ENABLE_ASH_RANDOM_SUPPORT
2159 # define vrandom  varinit[VAR_OFFSET2 + 6]
2160 #endif
2161 #define VAR_OFFSET3 (VAR_OFFSET2 + ENABLE_ASH_RANDOM_SUPPORT)
2162 #if BASH_EPOCH_VARS
2163 # define vepochs  varinit[VAR_OFFSET3 + 6]
2164 # define vepochr  varinit[VAR_OFFSET3 + 7]
2165 #endif
2166 #define INIT_G_var() do { \
2167         unsigned i; \
2168         (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \
2169         barrier(); \
2170         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2171                 varinit[i].flags    = varinit_data[i].flags; \
2172                 varinit[i].var_text = varinit_data[i].var_text; \
2173                 varinit[i].var_func = varinit_data[i].var_func; \
2174         } \
2175         strcpy(linenovar, "LINENO="); \
2176         vlineno.var_text = linenovar; \
2177 } while (0)
2178
2179 /*
2180  * The following macros access the values of the above variables.
2181  * They have to skip over the name.  They return the null string
2182  * for unset variables.
2183  */
2184 #define ifsval()        (vifs.var_text + 4)
2185 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2186 #if ENABLE_ASH_MAIL
2187 # define mailval()      (vmail.var_text + 5)
2188 # define mpathval()     (vmpath.var_text + 9)
2189 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2190 #endif
2191 #define pathval()       (vpath.var_text + 5)
2192 #define ps1val()        (vps1.var_text + 4)
2193 #define ps2val()        (vps2.var_text + 4)
2194 #define ps4val()        (vps4.var_text + 4)
2195 #if ENABLE_ASH_GETOPTS
2196 # define optindval()    (voptind.var_text + 7)
2197 #endif
2198
2199 #if ENABLE_ASH_GETOPTS
2200 static void FAST_FUNC
2201 getoptsreset(const char *value)
2202 {
2203         shellparam.optind = 1;
2204         if (is_number(value))
2205                 shellparam.optind = number(value) ?: 1;
2206         shellparam.optoff = -1;
2207 }
2208 #endif
2209
2210 /*
2211  * Compares two strings up to the first = or '\0'.  The first
2212  * string must be terminated by '='; the second may be terminated by
2213  * either '=' or '\0'.
2214  */
2215 static int
2216 varcmp(const char *p, const char *q)
2217 {
2218         int c, d;
2219
2220         while ((c = *p) == (d = *q)) {
2221                 if (c == '\0' || c == '=')
2222                         goto out;
2223                 p++;
2224                 q++;
2225         }
2226         if (c == '=')
2227                 c = '\0';
2228         if (d == '=')
2229                 d = '\0';
2230  out:
2231         return c - d;
2232 }
2233
2234 /*
2235  * Find the appropriate entry in the hash table from the name.
2236  */
2237 static struct var **
2238 hashvar(const char *p)
2239 {
2240         unsigned hashval;
2241
2242         hashval = ((unsigned char) *p) << 4;
2243         while (*p && *p != '=')
2244                 hashval += (unsigned char) *p++;
2245         return &vartab[hashval % VTABSIZE];
2246 }
2247
2248 static int
2249 vpcmp(const void *a, const void *b)
2250 {
2251         return varcmp(*(const char **)a, *(const char **)b);
2252 }
2253
2254 /*
2255  * This routine initializes the builtin variables.
2256  */
2257 static void
2258 initvar(void)
2259 {
2260         struct var *vp;
2261         struct var *end;
2262         struct var **vpp;
2263
2264         /*
2265          * PS1 depends on uid
2266          */
2267 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2268         vps1.var_text = "PS1=\\w \\$ ";
2269 #else
2270         if (!geteuid())
2271                 vps1.var_text = "PS1=# ";
2272 #endif
2273         vp = varinit;
2274         end = vp + ARRAY_SIZE(varinit);
2275         do {
2276                 vpp = hashvar(vp->var_text);
2277                 vp->next = *vpp;
2278                 *vpp = vp;
2279         } while (++vp < end);
2280 }
2281
2282 static struct var **
2283 findvar(struct var **vpp, const char *name)
2284 {
2285         for (; *vpp; vpp = &(*vpp)->next) {
2286                 if (varcmp((*vpp)->var_text, name) == 0) {
2287                         break;
2288                 }
2289         }
2290         return vpp;
2291 }
2292
2293 /*
2294  * Find the value of a variable.  Returns NULL if not set.
2295  */
2296 static const char* FAST_FUNC
2297 lookupvar(const char *name)
2298 {
2299         struct var *v;
2300
2301         v = *findvar(hashvar(name), name);
2302         if (v) {
2303 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2304         /*
2305          * Dynamic variables are implemented roughly the same way they are
2306          * in bash. Namely, they're "special" so long as they aren't unset.
2307          * As soon as they're unset, they're no longer dynamic, and dynamic
2308          * lookup will no longer happen at that point. -- PFM.
2309          */
2310                 if (v->flags & VDYNAMIC)
2311                         v->var_func(NULL);
2312 #endif
2313                 if (!(v->flags & VUNSET)) {
2314                         if (v == &vlineno && v->var_text == linenovar) {
2315                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2316                         }
2317                         return var_end(v->var_text);
2318                 }
2319         }
2320         return NULL;
2321 }
2322
2323 #if ENABLE_UNICODE_SUPPORT
2324 static void
2325 reinit_unicode_for_ash(void)
2326 {
2327         /* Unicode support should be activated even if LANG is set
2328          * _during_ shell execution, not only if it was set when
2329          * shell was started. Therefore, re-check LANG every time:
2330          */
2331         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2332          || ENABLE_UNICODE_USING_LOCALE
2333         ) {
2334                 const char *s = lookupvar("LC_ALL");
2335                 if (!s) s = lookupvar("LC_CTYPE");
2336                 if (!s) s = lookupvar("LANG");
2337                 reinit_unicode(s);
2338         }
2339 }
2340 #else
2341 # define reinit_unicode_for_ash() ((void)0)
2342 #endif
2343
2344 /*
2345  * Search the environment of a builtin command.
2346  */
2347 static ALWAYS_INLINE const char *
2348 bltinlookup(const char *name)
2349 {
2350         return lookupvar(name);
2351 }
2352
2353 /*
2354  * Same as setvar except that the variable and value are passed in
2355  * the first argument as name=value.  Since the first argument will
2356  * be actually stored in the table, it should not be a string that
2357  * will go away.
2358  * Called with interrupts off.
2359  */
2360 static struct var *
2361 setvareq(char *s, int flags)
2362 {
2363         struct var *vp, **vpp;
2364
2365         vpp = hashvar(s);
2366         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2367         vpp = findvar(vpp, s);
2368         vp = *vpp;
2369         if (vp) {
2370                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2371                         const char *n;
2372
2373                         if (flags & VNOSAVE)
2374                                 free(s);
2375                         n = vp->var_text;
2376                         exitstatus = 1;
2377                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2378                 }
2379
2380                 if (flags & VNOSET)
2381                         goto out;
2382
2383                 if (vp->var_func && !(flags & VNOFUNC))
2384                         vp->var_func(var_end(s));
2385
2386                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2387                         free((char*)vp->var_text);
2388
2389                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2390                         *vpp = vp->next;
2391                         free(vp);
2392  out_free:
2393                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2394                                 free(s);
2395                         goto out;
2396                 }
2397
2398                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2399 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2400                 if (flags & VUNSET)
2401                         flags &= ~VDYNAMIC;
2402 #endif
2403         } else {
2404                 /* variable s is not found */
2405                 if (flags & VNOSET)
2406                         goto out;
2407                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2408                         goto out_free;
2409                 vp = ckzalloc(sizeof(*vp));
2410                 vp->next = *vpp;
2411                 /*vp->func = NULL; - ckzalloc did it */
2412                 *vpp = vp;
2413         }
2414         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2415                 s = ckstrdup(s);
2416         vp->var_text = s;
2417         vp->flags = flags;
2418
2419  out:
2420         return vp;
2421 }
2422
2423 /*
2424  * Set the value of a variable.  The flags argument is ored with the
2425  * flags of the variable.  If val is NULL, the variable is unset.
2426  */
2427 static struct var *
2428 setvar(const char *name, const char *val, int flags)
2429 {
2430         const char *q;
2431         char *p;
2432         char *nameeq;
2433         size_t namelen;
2434         size_t vallen;
2435         struct var *vp;
2436
2437         q = endofname(name);
2438         p = strchrnul(q, '=');
2439         namelen = p - name;
2440         if (!namelen || p != q)
2441                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2442         vallen = 0;
2443         if (val == NULL) {
2444                 flags |= VUNSET;
2445         } else {
2446                 vallen = strlen(val);
2447         }
2448
2449         INT_OFF;
2450         nameeq = ckzalloc(namelen + vallen + 2);
2451         p = mempcpy(nameeq, name, namelen);
2452         if (val) {
2453                 *p++ = '=';
2454                 memcpy(p, val, vallen);
2455         }
2456         vp = setvareq(nameeq, flags | VNOSAVE);
2457         INT_ON;
2458
2459         return vp;
2460 }
2461
2462 static void FAST_FUNC
2463 setvar0(const char *name, const char *val)
2464 {
2465         setvar(name, val, 0);
2466 }
2467
2468 /*
2469  * Unset the specified variable.
2470  */
2471 static void
2472 unsetvar(const char *s)
2473 {
2474         setvar(s, NULL, 0);
2475 }
2476
2477 /*
2478  * Process a linked list of variable assignments.
2479  */
2480 static void
2481 listsetvar(struct strlist *list_set_var, int flags)
2482 {
2483         struct strlist *lp = list_set_var;
2484
2485         if (!lp)
2486                 return;
2487         INT_OFF;
2488         do {
2489                 setvareq(lp->text, flags);
2490                 lp = lp->next;
2491         } while (lp);
2492         INT_ON;
2493 }
2494
2495 /*
2496  * Generate a list of variables satisfying the given conditions.
2497  */
2498 #if !ENABLE_FEATURE_SH_NOFORK
2499 # define listvars(on, off, lp, end) listvars(on, off, end)
2500 #endif
2501 static char **
2502 listvars(int on, int off, struct strlist *lp, char ***end)
2503 {
2504         struct var **vpp;
2505         struct var *vp;
2506         char **ep;
2507         int mask;
2508
2509         STARTSTACKSTR(ep);
2510         vpp = vartab;
2511         mask = on | off;
2512         do {
2513                 for (vp = *vpp; vp; vp = vp->next) {
2514                         if ((vp->flags & mask) == on) {
2515 #if ENABLE_FEATURE_SH_NOFORK
2516                                 /* If variable with the same name is both
2517                                  * exported and temporarily set for a command:
2518                                  *  export ZVAR=5
2519                                  *  ZVAR=6 printenv
2520                                  * then "ZVAR=6" will be both in vartab and
2521                                  * lp lists. Do not pass it twice to printenv.
2522                                  */
2523                                 struct strlist *lp1 = lp;
2524                                 while (lp1) {
2525                                         if (strcmp(lp1->text, vp->var_text) == 0)
2526                                                 goto skip;
2527                                         lp1 = lp1->next;
2528                                 }
2529 #endif
2530                                 if (ep == stackstrend())
2531                                         ep = growstackstr();
2532                                 *ep++ = (char*)vp->var_text;
2533 #if ENABLE_FEATURE_SH_NOFORK
2534  skip: ;
2535 #endif
2536                         }
2537                 }
2538         } while (++vpp < vartab + VTABSIZE);
2539
2540 #if ENABLE_FEATURE_SH_NOFORK
2541         while (lp) {
2542                 if (ep == stackstrend())
2543                         ep = growstackstr();
2544                 *ep++ = lp->text;
2545                 lp = lp->next;
2546         }
2547 #endif
2548
2549         if (ep == stackstrend())
2550                 ep = growstackstr();
2551         if (end)
2552                 *end = ep;
2553         *ep++ = NULL;
2554         return grabstackstr(ep);
2555 }
2556
2557
2558 /* ============ Path search helper
2559  *
2560  * The variable path (passed by reference) should be set to the start
2561  * of the path before the first call; path_advance will update
2562  * this value as it proceeds.  Successive calls to path_advance will return
2563  * the possible path expansions in sequence.  If an option (indicated by
2564  * a percent sign) appears in the path entry then the global variable
2565  * pathopt will be set to point to it; otherwise pathopt will be set to
2566  * NULL.
2567  */
2568 static const char *pathopt;     /* set by path_advance */
2569
2570 static char *
2571 path_advance(const char **path, const char *name)
2572 {
2573         const char *p;
2574         char *q;
2575         const char *start;
2576         size_t len;
2577
2578         if (*path == NULL)
2579                 return NULL;
2580         start = *path;
2581         for (p = start; *p && *p != ':' && *p != '%'; p++)
2582                 continue;
2583         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2584         while (stackblocksize() < len)
2585                 growstackblock();
2586         q = stackblock();
2587         if (p != start) {
2588                 q = mempcpy(q, start, p - start);
2589                 *q++ = '/';
2590         }
2591         strcpy(q, name);
2592         pathopt = NULL;
2593         if (*p == '%') {
2594                 pathopt = ++p;
2595                 while (*p && *p != ':')
2596                         p++;
2597         }
2598         if (*p == ':')
2599                 *path = p + 1;
2600         else
2601                 *path = NULL;
2602         return stalloc(len);
2603 }
2604
2605
2606 /* ============ Prompt */
2607
2608 static smallint doprompt;                   /* if set, prompt the user */
2609 static smallint needprompt;                 /* true if interactive and at start of line */
2610
2611 #if ENABLE_FEATURE_EDITING
2612 static line_input_t *line_input_state;
2613 static const char *cmdedit_prompt;
2614 static void
2615 putprompt(const char *s)
2616 {
2617         if (ENABLE_ASH_EXPAND_PRMT) {
2618                 free((char*)cmdedit_prompt);
2619                 cmdedit_prompt = ckstrdup(s);
2620                 return;
2621         }
2622         cmdedit_prompt = s;
2623 }
2624 #else
2625 static void
2626 putprompt(const char *s)
2627 {
2628         out2str(s);
2629 }
2630 #endif
2631
2632 /* expandstr() needs parsing machinery, so it is far away ahead... */
2633 static const char *expandstr(const char *ps, int syntax_type);
2634 /* Values for syntax param */
2635 #define BASESYNTAX 0    /* not in quotes */
2636 #define DQSYNTAX   1    /* in double quotes */
2637 #define SQSYNTAX   2    /* in single quotes */
2638 #define ARISYNTAX  3    /* in arithmetic */
2639 #if ENABLE_ASH_EXPAND_PRMT
2640 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2641 #endif
2642 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2643
2644 /*
2645  * called by editline -- any expansions to the prompt should be added here.
2646  */
2647 static void
2648 setprompt_if(smallint do_set, int whichprompt)
2649 {
2650         const char *prompt;
2651         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2652
2653         if (!do_set)
2654                 return;
2655
2656         needprompt = 0;
2657
2658         switch (whichprompt) {
2659         case 1:
2660                 prompt = ps1val();
2661                 break;
2662         case 2:
2663                 prompt = ps2val();
2664                 break;
2665         default:                        /* 0 */
2666                 prompt = nullstr;
2667         }
2668 #if ENABLE_ASH_EXPAND_PRMT
2669         pushstackmark(&smark, stackblocksize());
2670         putprompt(expandstr(prompt, PSSYNTAX));
2671         popstackmark(&smark);
2672 #else
2673         putprompt(prompt);
2674 #endif
2675 }
2676
2677
2678 /* ============ The cd and pwd commands */
2679
2680 #define CD_PHYSICAL 1
2681 #define CD_PRINT 2
2682
2683 static int
2684 cdopt(void)
2685 {
2686         int flags = 0;
2687         int i, j;
2688
2689         j = 'L';
2690         while ((i = nextopt("LP")) != '\0') {
2691                 if (i != j) {
2692                         flags ^= CD_PHYSICAL;
2693                         j = i;
2694                 }
2695         }
2696
2697         return flags;
2698 }
2699
2700 /*
2701  * Update curdir (the name of the current directory) in response to a
2702  * cd command.
2703  */
2704 static const char *
2705 updatepwd(const char *dir)
2706 {
2707         char *new;
2708         char *p;
2709         char *cdcomppath;
2710         const char *lim;
2711
2712         cdcomppath = sstrdup(dir);
2713         STARTSTACKSTR(new);
2714         if (*dir != '/') {
2715                 if (curdir == nullstr)
2716                         return 0;
2717                 new = stack_putstr(curdir, new);
2718         }
2719         new = makestrspace(strlen(dir) + 2, new);
2720         lim = (char *)stackblock() + 1;
2721         if (*dir != '/') {
2722                 if (new[-1] != '/')
2723                         USTPUTC('/', new);
2724                 if (new > lim && *lim == '/')
2725                         lim++;
2726         } else {
2727                 USTPUTC('/', new);
2728                 cdcomppath++;
2729                 if (dir[1] == '/' && dir[2] != '/') {
2730                         USTPUTC('/', new);
2731                         cdcomppath++;
2732                         lim++;
2733                 }
2734         }
2735         p = strtok(cdcomppath, "/");
2736         while (p) {
2737                 switch (*p) {
2738                 case '.':
2739                         if (p[1] == '.' && p[2] == '\0') {
2740                                 while (new > lim) {
2741                                         STUNPUTC(new);
2742                                         if (new[-1] == '/')
2743                                                 break;
2744                                 }
2745                                 break;
2746                         }
2747                         if (p[1] == '\0')
2748                                 break;
2749                         /* fall through */
2750                 default:
2751                         new = stack_putstr(p, new);
2752                         USTPUTC('/', new);
2753                 }
2754                 p = strtok(NULL, "/");
2755         }
2756         if (new > lim)
2757                 STUNPUTC(new);
2758         *new = 0;
2759         return stackblock();
2760 }
2761
2762 /*
2763  * Find out what the current directory is. If we already know the current
2764  * directory, this routine returns immediately.
2765  */
2766 static char *
2767 getpwd(void)
2768 {
2769         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2770         return dir ? dir : nullstr;
2771 }
2772
2773 static void
2774 setpwd(const char *val, int setold)
2775 {
2776         char *oldcur, *dir;
2777
2778         oldcur = dir = curdir;
2779
2780         if (setold) {
2781                 setvar("OLDPWD", oldcur, VEXPORT);
2782         }
2783         INT_OFF;
2784         if (physdir != nullstr) {
2785                 if (physdir != oldcur)
2786                         free(physdir);
2787                 physdir = nullstr;
2788         }
2789         if (oldcur == val || !val) {
2790                 char *s = getpwd();
2791                 physdir = s;
2792                 if (!val)
2793                         dir = s;
2794         } else
2795                 dir = ckstrdup(val);
2796         if (oldcur != dir && oldcur != nullstr) {
2797                 free(oldcur);
2798         }
2799         curdir = dir;
2800         INT_ON;
2801         setvar("PWD", dir, VEXPORT);
2802 }
2803
2804 static void hashcd(void);
2805
2806 /*
2807  * Actually do the chdir.  We also call hashcd to let other routines
2808  * know that the current directory has changed.
2809  */
2810 static int
2811 docd(const char *dest, int flags)
2812 {
2813         const char *dir = NULL;
2814         int err;
2815
2816         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2817
2818         INT_OFF;
2819         if (!(flags & CD_PHYSICAL)) {
2820                 dir = updatepwd(dest);
2821                 if (dir)
2822                         dest = dir;
2823         }
2824         err = chdir(dest);
2825         if (err)
2826                 goto out;
2827         setpwd(dir, 1);
2828         hashcd();
2829  out:
2830         INT_ON;
2831         return err;
2832 }
2833
2834 static int FAST_FUNC
2835 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2836 {
2837         const char *dest;
2838         const char *path;
2839         const char *p;
2840         char c;
2841         struct stat statb;
2842         int flags;
2843
2844         flags = cdopt();
2845         dest = *argptr;
2846         if (!dest)
2847                 dest = bltinlookup("HOME");
2848         else if (LONE_DASH(dest)) {
2849                 dest = bltinlookup("OLDPWD");
2850                 flags |= CD_PRINT;
2851         }
2852         if (!dest)
2853                 dest = nullstr;
2854         if (*dest == '/')
2855                 goto step6;
2856         if (*dest == '.') {
2857                 c = dest[1];
2858  dotdot:
2859                 switch (c) {
2860                 case '\0':
2861                 case '/':
2862                         goto step6;
2863                 case '.':
2864                         c = dest[2];
2865                         if (c != '.')
2866                                 goto dotdot;
2867                 }
2868         }
2869         if (!*dest)
2870                 dest = ".";
2871         path = bltinlookup("CDPATH");
2872         while (path) {
2873                 c = *path;
2874                 p = path_advance(&path, dest);
2875                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2876                         if (c && c != ':')
2877                                 flags |= CD_PRINT;
2878  docd:
2879                         if (!docd(p, flags))
2880                                 goto out;
2881                         goto err;
2882                 }
2883         }
2884
2885  step6:
2886         p = dest;
2887         goto docd;
2888
2889  err:
2890         ash_msg_and_raise_perror("can't cd to %s", dest);
2891         /* NOTREACHED */
2892  out:
2893         if (flags & CD_PRINT)
2894                 out1fmt("%s\n", curdir);
2895         return 0;
2896 }
2897
2898 static int FAST_FUNC
2899 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2900 {
2901         int flags;
2902         const char *dir = curdir;
2903
2904         flags = cdopt();
2905         if (flags) {
2906                 if (physdir == nullstr)
2907                         setpwd(dir, 0);
2908                 dir = physdir;
2909         }
2910         out1fmt("%s\n", dir);
2911         return 0;
2912 }
2913
2914
2915 /* ============ ... */
2916
2917
2918 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2919
2920 /* Syntax classes */
2921 #define CWORD     0             /* character is nothing special */
2922 #define CNL       1             /* newline character */
2923 #define CBACK     2             /* a backslash character */
2924 #define CSQUOTE   3             /* single quote */
2925 #define CDQUOTE   4             /* double quote */
2926 #define CENDQUOTE 5             /* a terminating quote */
2927 #define CBQUOTE   6             /* backwards single quote */
2928 #define CVAR      7             /* a dollar sign */
2929 #define CENDVAR   8             /* a '}' character */
2930 #define CLP       9             /* a left paren in arithmetic */
2931 #define CRP      10             /* a right paren in arithmetic */
2932 #define CENDFILE 11             /* end of file */
2933 #define CCTL     12             /* like CWORD, except it must be escaped */
2934 #define CSPCL    13             /* these terminate a word */
2935 #define CIGN     14             /* character should be ignored */
2936
2937 #define PEOF     256
2938 #if ENABLE_ASH_ALIAS
2939 # define PEOA    257
2940 #endif
2941
2942 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2943
2944 #if ENABLE_FEATURE_SH_MATH
2945 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2946 #else
2947 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2948 #endif
2949 static const uint16_t S_I_T[] ALIGN2 = {
2950 #if ENABLE_ASH_ALIAS
2951         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2952 #endif
2953         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2954         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2955         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2956         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2957         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2958         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2959         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2960         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2961         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2962         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2963         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2964 #if !USE_SIT_FUNCTION
2965         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2966         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2967         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2968 #endif
2969 #undef SIT_ITEM
2970 };
2971 /* Constants below must match table above */
2972 enum {
2973 #if ENABLE_ASH_ALIAS
2974         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2975 #endif
2976         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2977         CNL_CNL_CNL_CNL                    , /*  2 */
2978         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2979         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2980         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2981         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2982         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2983         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2984         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2985         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2986         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2987         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2988         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2989         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2990 };
2991
2992 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2993  * caller must ensure proper cast on it if c is *char_ptr!
2994  */
2995 #if USE_SIT_FUNCTION
2996
2997 static int
2998 SIT(int c, int syntax)
2999 {
3000         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
3001         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
3002         /*
3003          * This causes '/' to be prepended with CTLESC in dquoted string,
3004          * making "./file"* treated incorrectly because we feed
3005          * ".\/file*" string to glob(), confusing it (see expandmeta func).
3006          * The "homegrown" glob implementation is okay with that,
3007          * but glibc one isn't. With '/' always treated as CWORD,
3008          * both work fine.
3009          */
3010 # if ENABLE_ASH_ALIAS
3011         static const uint8_t syntax_index_table[] ALIGN1 = {
3012                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
3013                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
3014                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
3015                 11, 3                           /* "}~" */
3016         };
3017 # else
3018         static const uint8_t syntax_index_table[] ALIGN1 = {
3019                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
3020                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
3021                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
3022                 10, 2                           /* "}~" */
3023         };
3024 # endif
3025         const char *s;
3026         int indx;
3027
3028         if (c == PEOF)
3029                 return CENDFILE;
3030 # if ENABLE_ASH_ALIAS
3031         if (c == PEOA)
3032                 indx = 0;
3033         else
3034 # endif
3035         {
3036                 /* Cast is purely for paranoia here,
3037                  * just in case someone passed signed char to us */
3038                 if ((unsigned char)c >= CTL_FIRST
3039                  && (unsigned char)c <= CTL_LAST
3040                 ) {
3041                         return CCTL;
3042                 }
3043                 s = strchrnul(spec_symbls, c);
3044                 if (*s == '\0')
3045                         return CWORD;
3046                 indx = syntax_index_table[s - spec_symbls];
3047         }
3048         return (S_I_T[indx] >> (syntax*4)) & 0xf;
3049 }
3050
3051 #else   /* !USE_SIT_FUNCTION */
3052
3053 static const uint8_t syntax_index_table[] ALIGN1 = {
3054         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3055         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3056         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3057         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3058         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3059         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3060         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3061         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3062         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3063         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3064         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3065         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3066         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3067         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3068         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3069         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3070         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3071         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3072         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3073         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3074         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3075         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3076         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3077         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3078         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3079         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3080         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3081         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3082         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3083         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3084         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3085         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3086         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3087         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3088         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3089         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3090         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3091         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3092         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3093         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3094         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3095         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3096         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3097         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3098         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3099         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3100         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3101         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3102 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3103         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3104         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3105         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3106         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3107         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3108         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3109         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3110         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3111         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3112         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3113         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3114         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3115         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3116         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3117         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3118         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3119         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3120         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3121         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3122         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3123         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3124         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3125         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3126         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3127         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3128         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3129         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3130         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3131         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3132         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3133         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3134         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3135         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3136         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3137         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3138         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3139         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3140         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3141         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3142         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3143         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3144         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3145         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3146         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3147         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3148         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3149         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3150         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3151         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3152         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3153         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3154         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3155         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3156         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3157         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3158         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3159         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3160         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3161         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3162         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3163         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3164         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3165         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3166         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3167         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3168         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3169         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3170         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3171         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3172         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3173         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3174         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3175         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3176         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3177         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3178         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3179         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3180         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3181         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3182         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3183         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3184         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3185         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3186         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3187         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3188         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3189         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3190         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3191         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3192         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3193         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3258         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3259         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3260         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3261         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3262         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3263         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3264         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3265         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3266         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3267         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3268         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3269         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3270         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3271         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3272         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3273         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3274         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3275         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3276         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3277         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3278         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3279         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3280         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3281         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3282         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3283         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3284         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3285         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3286         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3287         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3288         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3289         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3290         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3291         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3292         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3293         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3294         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3295         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3296         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3297         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3298         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3299         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3300         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3301         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3302         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3303         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3304         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3305         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3306         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3307         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3308         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3309         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3310         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3311         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3312         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3313 # if ENABLE_ASH_ALIAS
3314         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3315 # endif
3316 };
3317
3318 #if 1
3319 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3320 #else /* debug version, caught one signed char bug */
3321 # define SIT(c, syntax) \
3322         ({ \
3323                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3324                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3325                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3326                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3327                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3328         })
3329 #endif
3330
3331 #endif  /* !USE_SIT_FUNCTION */
3332
3333
3334 /* ============ Alias handling */
3335
3336 #if ENABLE_ASH_ALIAS
3337
3338 #define ALIASINUSE 1
3339 #define ALIASDEAD  2
3340
3341 struct alias {
3342         struct alias *next;
3343         char *name;
3344         char *val;
3345         int flag;
3346 };
3347
3348
3349 static struct alias **atab; // [ATABSIZE];
3350 #define INIT_G_alias() do { \
3351         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3352 } while (0)
3353
3354
3355 static struct alias **
3356 __lookupalias(const char *name)
3357 {
3358         unsigned int hashval;
3359         struct alias **app;
3360         const char *p;
3361         unsigned int ch;
3362
3363         p = name;
3364
3365         ch = (unsigned char)*p;
3366         hashval = ch << 4;
3367         while (ch) {
3368                 hashval += ch;
3369                 ch = (unsigned char)*++p;
3370         }
3371         app = &atab[hashval % ATABSIZE];
3372
3373         for (; *app; app = &(*app)->next) {
3374                 if (strcmp(name, (*app)->name) == 0) {
3375                         break;
3376                 }
3377         }
3378
3379         return app;
3380 }
3381
3382 static struct alias *
3383 lookupalias(const char *name, int check)
3384 {
3385         struct alias *ap = *__lookupalias(name);
3386
3387         if (check && ap && (ap->flag & ALIASINUSE))
3388                 return NULL;
3389         return ap;
3390 }
3391
3392 static struct alias *
3393 freealias(struct alias *ap)
3394 {
3395         struct alias *next;
3396
3397         if (ap->flag & ALIASINUSE) {
3398                 ap->flag |= ALIASDEAD;
3399                 return ap;
3400         }
3401
3402         next = ap->next;
3403         free(ap->name);
3404         free(ap->val);
3405         free(ap);
3406         return next;
3407 }
3408
3409 static void
3410 setalias(const char *name, const char *val)
3411 {
3412         struct alias *ap, **app;
3413
3414         app = __lookupalias(name);
3415         ap = *app;
3416         INT_OFF;
3417         if (ap) {
3418                 if (!(ap->flag & ALIASINUSE)) {
3419                         free(ap->val);
3420                 }
3421                 ap->val = ckstrdup(val);
3422                 ap->flag &= ~ALIASDEAD;
3423         } else {
3424                 /* not found */
3425                 ap = ckzalloc(sizeof(struct alias));
3426                 ap->name = ckstrdup(name);
3427                 ap->val = ckstrdup(val);
3428                 /*ap->flag = 0; - ckzalloc did it */
3429                 /*ap->next = NULL;*/
3430                 *app = ap;
3431         }
3432         INT_ON;
3433 }
3434
3435 static int
3436 unalias(const char *name)
3437 {
3438         struct alias **app;
3439
3440         app = __lookupalias(name);
3441
3442         if (*app) {
3443                 INT_OFF;
3444                 *app = freealias(*app);
3445                 INT_ON;
3446                 return 0;
3447         }
3448
3449         return 1;
3450 }
3451
3452 static void
3453 rmaliases(void)
3454 {
3455         struct alias *ap, **app;
3456         int i;
3457
3458         INT_OFF;
3459         for (i = 0; i < ATABSIZE; i++) {
3460                 app = &atab[i];
3461                 for (ap = *app; ap; ap = *app) {
3462                         *app = freealias(*app);
3463                         if (ap == *app) {
3464                                 app = &ap->next;
3465                         }
3466                 }
3467         }
3468         INT_ON;
3469 }
3470
3471 static void
3472 printalias(const struct alias *ap)
3473 {
3474         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3475 }
3476
3477 /*
3478  * TODO - sort output
3479  */
3480 static int FAST_FUNC
3481 aliascmd(int argc UNUSED_PARAM, char **argv)
3482 {
3483         char *n, *v;
3484         int ret = 0;
3485         struct alias *ap;
3486
3487         if (!argv[1]) {
3488                 int i;
3489
3490                 for (i = 0; i < ATABSIZE; i++) {
3491                         for (ap = atab[i]; ap; ap = ap->next) {
3492                                 printalias(ap);
3493                         }
3494                 }
3495                 return 0;
3496         }
3497         while ((n = *++argv) != NULL) {
3498                 v = strchr(n+1, '=');
3499                 if (v == NULL) { /* n+1: funny ksh stuff */
3500                         ap = *__lookupalias(n);
3501                         if (ap == NULL) {
3502                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3503                                 ret = 1;
3504                         } else
3505                                 printalias(ap);
3506                 } else {
3507                         *v++ = '\0';
3508                         setalias(n, v);
3509                 }
3510         }
3511
3512         return ret;
3513 }
3514
3515 static int FAST_FUNC
3516 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3517 {
3518         int i;
3519
3520         while (nextopt("a") != '\0') {
3521                 rmaliases();
3522                 return 0;
3523         }
3524         for (i = 0; *argptr; argptr++) {
3525                 if (unalias(*argptr)) {
3526                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3527                         i = 1;
3528                 }
3529         }
3530
3531         return i;
3532 }
3533
3534 #endif /* ASH_ALIAS */
3535
3536
3537 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3538 #define FORK_FG    0
3539 #define FORK_BG    1
3540 #define FORK_NOJOB 2
3541
3542 /* mode flags for showjob(s) */
3543 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3544 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3545 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3546 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3547
3548 /*
3549  * A job structure contains information about a job.  A job is either a
3550  * single process or a set of processes contained in a pipeline.  In the
3551  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3552  * array of pids.
3553  */
3554 struct procstat {
3555         pid_t   ps_pid;         /* process id */
3556         int     ps_status;      /* last process status from wait() */
3557         char    *ps_cmd;        /* text of command being run */
3558 };
3559
3560 struct job {
3561         struct procstat ps0;    /* status of process */
3562         struct procstat *ps;    /* status of processes when more than one */
3563 #if JOBS
3564         int stopstatus;         /* status of a stopped job */
3565 #endif
3566         unsigned nprocs;        /* number of processes */
3567
3568 #define JOBRUNNING      0       /* at least one proc running */
3569 #define JOBSTOPPED      1       /* all procs are stopped */
3570 #define JOBDONE         2       /* all procs are completed */
3571         unsigned
3572                 state: 8,
3573 #if JOBS
3574                 sigint: 1,      /* job was killed by SIGINT */
3575                 jobctl: 1,      /* job running under job control */
3576 #endif
3577                 waited: 1,      /* true if this entry has been waited for */
3578                 used: 1,        /* true if this entry is in used */
3579                 changed: 1;     /* true if status has changed */
3580         struct job *prev_job;   /* previous job */
3581 };
3582
3583 static struct job *makejob(/*union node *,*/ int);
3584 static int forkshell(struct job *, union node *, int);
3585 static int waitforjob(struct job *);
3586
3587 #if !JOBS
3588 enum { doing_jobctl = 0 };
3589 #define setjobctl(on) do {} while (0)
3590 #else
3591 static smallint doing_jobctl; //references:8
3592 static void setjobctl(int);
3593 #endif
3594
3595 /*
3596  * Ignore a signal.
3597  */
3598 static void
3599 ignoresig(int signo)
3600 {
3601         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3602         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3603                 /* No, need to do it */
3604                 signal(signo, SIG_IGN);
3605         }
3606         sigmode[signo - 1] = S_HARD_IGN;
3607 }
3608
3609 /*
3610  * Only one usage site - in setsignal()
3611  */
3612 static void
3613 signal_handler(int signo)
3614 {
3615         if (signo == SIGCHLD) {
3616                 got_sigchld = 1;
3617                 if (!trap[SIGCHLD])
3618                         return;
3619         }
3620
3621         gotsig[signo - 1] = 1;
3622         pending_sig = signo;
3623
3624         if (signo == SIGINT && !trap[SIGINT]) {
3625                 if (!suppress_int) {
3626                         pending_sig = 0;
3627                         raise_interrupt(); /* does not return */
3628                 }
3629                 pending_int = 1;
3630         }
3631 }
3632
3633 /*
3634  * Set the signal handler for the specified signal.  The routine figures
3635  * out what it should be set to.
3636  */
3637 static void
3638 setsignal(int signo)
3639 {
3640         char *t;
3641         char cur_act, new_act;
3642         struct sigaction act;
3643
3644         t = trap[signo];
3645         new_act = S_DFL;
3646         if (t != NULL) { /* trap for this sig is set */
3647                 new_act = S_CATCH;
3648                 if (t[0] == '\0') /* trap is "": ignore this sig */
3649                         new_act = S_IGN;
3650         }
3651
3652         if (rootshell && new_act == S_DFL) {
3653                 switch (signo) {
3654                 case SIGINT:
3655                         if (iflag || minusc || sflag == 0)
3656                                 new_act = S_CATCH;
3657                         break;
3658                 case SIGQUIT:
3659 #if DEBUG
3660                         if (debug)
3661                                 break;
3662 #endif
3663                         /* man bash:
3664                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3665                          * commands run by bash have signal handlers
3666                          * set to the values inherited by the shell
3667                          * from its parent". */
3668                         new_act = S_IGN;
3669                         break;
3670                 case SIGTERM:
3671                         if (iflag)
3672                                 new_act = S_IGN;
3673                         break;
3674 #if JOBS
3675                 case SIGTSTP:
3676                 case SIGTTOU:
3677                         if (mflag)
3678                                 new_act = S_IGN;
3679                         break;
3680 #endif
3681                 }
3682         }
3683         /* if !rootshell, we reset SIGQUIT to DFL,
3684          * whereas we have to restore it to what shell got on entry.
3685          * This is handled by the fact that if signal was IGNored on entry,
3686          * then cur_act is S_HARD_IGN and we never change its sigaction
3687          * (see code below).
3688          */
3689
3690         if (signo == SIGCHLD)
3691                 new_act = S_CATCH;
3692
3693         t = &sigmode[signo - 1];
3694         cur_act = *t;
3695         if (cur_act == 0) {
3696                 /* current setting is not yet known */
3697                 if (sigaction(signo, NULL, &act)) {
3698                         /* pretend it worked; maybe we should give a warning,
3699                          * but other shells don't. We don't alter sigmode,
3700                          * so we retry every time.
3701                          * btw, in Linux it never fails. --vda */
3702                         return;
3703                 }
3704                 if (act.sa_handler == SIG_IGN) {
3705                         cur_act = S_HARD_IGN;
3706                         if (mflag
3707                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3708                         ) {
3709                                 cur_act = S_IGN;   /* don't hard ignore these */
3710                         }
3711                 }
3712                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3713                         /* installing SIG_DFL over SIG_DFL is a no-op */
3714                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3715                         *t = S_DFL;
3716                         return;
3717                 }
3718         }
3719         if (cur_act == S_HARD_IGN || cur_act == new_act)
3720                 return;
3721
3722         *t = new_act;
3723
3724         act.sa_handler = SIG_DFL;
3725         switch (new_act) {
3726         case S_CATCH:
3727                 act.sa_handler = signal_handler;
3728                 break;
3729         case S_IGN:
3730                 act.sa_handler = SIG_IGN;
3731                 break;
3732         }
3733         /* flags and mask matter only if !DFL and !IGN, but we do it
3734          * for all cases for more deterministic behavior:
3735          */
3736         act.sa_flags = 0; //TODO: why not SA_RESTART?
3737         sigfillset(&act.sa_mask);
3738
3739         sigaction_set(signo, &act);
3740 }
3741
3742 /* mode flags for set_curjob */
3743 #define CUR_DELETE 2
3744 #define CUR_RUNNING 1
3745 #define CUR_STOPPED 0
3746
3747 #if JOBS
3748 /* pgrp of shell on invocation */
3749 static int initialpgrp; //references:2
3750 static int ttyfd = -1; //5
3751 #endif
3752 /* array of jobs */
3753 static struct job *jobtab; //5
3754 /* size of array */
3755 static unsigned njobs; //4
3756 /* current job */
3757 static struct job *curjob; //lots
3758 /* number of presumed living untracked jobs */
3759 static int jobless; //4
3760
3761 #if 0
3762 /* Bash has a feature: it restores termios after a successful wait for
3763  * a foreground job which had at least one stopped or sigkilled member.
3764  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3765  * properly restoring tty state. Should we do this too?
3766  * A reproducer: ^Z an interactive python:
3767  *
3768  * # python
3769  * Python 2.7.12 (...)
3770  * >>> ^Z
3771  *      { python leaves tty in -icanon -echo state. We do survive that... }
3772  *  [1]+  Stopped                    python
3773  *      { ...however, next program (python #2) does not survive it well: }
3774  * # python
3775  * Python 2.7.12 (...)
3776  * >>> Traceback (most recent call last):
3777  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3778  *   File "<stdin>", line 1, in <module>
3779  * NameError: name 'qwerty' is not defined
3780  *
3781  * The implementation below is modeled on bash code and seems to work.
3782  * However, I'm not sure we should do this. For one: what if I'd fg
3783  * the stopped python instead? It'll be confused by "restored" tty state.
3784  */
3785 static struct termios shell_tty_info;
3786 static void
3787 get_tty_state(void)
3788 {
3789         if (rootshell && ttyfd >= 0)
3790                 tcgetattr(ttyfd, &shell_tty_info);
3791 }
3792 static void
3793 set_tty_state(void)
3794 {
3795         /* if (rootshell) - caller ensures this */
3796         if (ttyfd >= 0)
3797                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3798 }
3799 static int
3800 job_signal_status(struct job *jp)
3801 {
3802         int status;
3803         unsigned i;
3804         struct procstat *ps = jp->ps;
3805         for (i = 0; i < jp->nprocs; i++) {
3806                 status = ps[i].ps_status;
3807                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3808                         return status;
3809         }
3810         return 0;
3811 }
3812 static void
3813 restore_tty_if_stopped_or_signaled(struct job *jp)
3814 {
3815 //TODO: check what happens if we come from waitforjob() in expbackq()
3816         if (rootshell) {
3817                 int s = job_signal_status(jp);
3818                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3819                         set_tty_state();
3820         }
3821 }
3822 #else
3823 # define get_tty_state() ((void)0)
3824 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3825 #endif
3826
3827 static void
3828 set_curjob(struct job *jp, unsigned mode)
3829 {
3830         struct job *jp1;
3831         struct job **jpp, **curp;
3832
3833         /* first remove from list */
3834         jpp = curp = &curjob;
3835         while (1) {
3836                 jp1 = *jpp;
3837                 if (jp1 == jp)
3838                         break;
3839                 jpp = &jp1->prev_job;
3840         }
3841         *jpp = jp1->prev_job;
3842
3843         /* Then re-insert in correct position */
3844         jpp = curp;
3845         switch (mode) {
3846         default:
3847 #if DEBUG
3848                 abort();
3849 #endif
3850         case CUR_DELETE:
3851                 /* job being deleted */
3852                 break;
3853         case CUR_RUNNING:
3854                 /* newly created job or backgrounded job,
3855                  * put after all stopped jobs.
3856                  */
3857                 while (1) {
3858                         jp1 = *jpp;
3859 #if JOBS
3860                         if (!jp1 || jp1->state != JOBSTOPPED)
3861 #endif
3862                                 break;
3863                         jpp = &jp1->prev_job;
3864                 }
3865                 /* FALLTHROUGH */
3866 #if JOBS
3867         case CUR_STOPPED:
3868 #endif
3869                 /* newly stopped job - becomes curjob */
3870                 jp->prev_job = *jpp;
3871                 *jpp = jp;
3872                 break;
3873         }
3874 }
3875
3876 #if JOBS || DEBUG
3877 static int
3878 jobno(const struct job *jp)
3879 {
3880         return jp - jobtab + 1;
3881 }
3882 #endif
3883
3884 /*
3885  * Convert a job name to a job structure.
3886  */
3887 #if !JOBS
3888 #define getjob(name, getctl) getjob(name)
3889 #endif
3890 static struct job *
3891 getjob(const char *name, int getctl)
3892 {
3893         struct job *jp;
3894         struct job *found;
3895         const char *err_msg = "%s: no such job";
3896         unsigned num;
3897         int c;
3898         const char *p;
3899         char *(*match)(const char *, const char *);
3900
3901         jp = curjob;
3902         p = name;
3903         if (!p)
3904                 goto currentjob;
3905
3906         if (*p != '%')
3907                 goto err;
3908
3909         c = *++p;
3910         if (!c)
3911                 goto currentjob;
3912
3913         if (!p[1]) {
3914                 if (c == '+' || c == '%') {
3915  currentjob:
3916                         err_msg = "No current job";
3917                         goto check;
3918                 }
3919                 if (c == '-') {
3920                         if (jp)
3921                                 jp = jp->prev_job;
3922                         err_msg = "No previous job";
3923  check:
3924                         if (!jp)
3925                                 goto err;
3926                         goto gotit;
3927                 }
3928         }
3929
3930         if (is_number(p)) {
3931                 num = atoi(p);
3932                 if (num > 0 && num <= njobs) {
3933                         jp = jobtab + num - 1;
3934                         if (jp->used)
3935                                 goto gotit;
3936                         goto err;
3937                 }
3938         }
3939
3940         match = prefix;
3941         if (*p == '?') {
3942                 match = strstr;
3943                 p++;
3944         }
3945
3946         found = NULL;
3947         while (jp) {
3948                 if (match(jp->ps[0].ps_cmd, p)) {
3949                         if (found)
3950                                 goto err;
3951                         found = jp;
3952                         err_msg = "%s: ambiguous";
3953                 }
3954                 jp = jp->prev_job;
3955         }
3956         if (!found)
3957                 goto err;
3958         jp = found;
3959
3960  gotit:
3961 #if JOBS
3962         err_msg = "job %s not created under job control";
3963         if (getctl && jp->jobctl == 0)
3964                 goto err;
3965 #endif
3966         return jp;
3967  err:
3968         ash_msg_and_raise_error(err_msg, name);
3969 }
3970
3971 /*
3972  * Mark a job structure as unused.
3973  */
3974 static void
3975 freejob(struct job *jp)
3976 {
3977         struct procstat *ps;
3978         int i;
3979
3980         INT_OFF;
3981         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3982                 if (ps->ps_cmd != nullstr)
3983                         free(ps->ps_cmd);
3984         }
3985         if (jp->ps != &jp->ps0)
3986                 free(jp->ps);
3987         jp->used = 0;
3988         set_curjob(jp, CUR_DELETE);
3989         INT_ON;
3990 }
3991
3992 #if JOBS
3993 static void
3994 xtcsetpgrp(int fd, pid_t pgrp)
3995 {
3996         if (tcsetpgrp(fd, pgrp))
3997                 ash_msg_and_raise_perror("can't set tty process group");
3998 }
3999
4000 /*
4001  * Turn job control on and off.
4002  *
4003  * Note:  This code assumes that the third arg to ioctl is a character
4004  * pointer, which is true on Berkeley systems but not System V.  Since
4005  * System V doesn't have job control yet, this isn't a problem now.
4006  *
4007  * Called with interrupts off.
4008  */
4009 static void
4010 setjobctl(int on)
4011 {
4012         int fd;
4013         int pgrp;
4014
4015         if (on == doing_jobctl || rootshell == 0)
4016                 return;
4017         if (on) {
4018                 int ofd;
4019                 ofd = fd = open(_PATH_TTY, O_RDWR);
4020                 if (fd < 0) {
4021         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
4022          * That sometimes helps to acquire controlling tty.
4023          * Obviously, a workaround for bugs when someone
4024          * failed to provide a controlling tty to bash! :) */
4025                         fd = 2;
4026                         while (!isatty(fd))
4027                                 if (--fd < 0)
4028                                         goto out;
4029                 }
4030                 /* fd is a tty at this point */
4031                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
4032                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
4033                         close(ofd);
4034                 if (fd < 0)
4035                         goto out; /* F_DUPFD failed */
4036                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
4037                         close_on_exec_on(fd);
4038                 while (1) { /* while we are in the background */
4039                         pgrp = tcgetpgrp(fd);
4040                         if (pgrp < 0) {
4041  out:
4042                                 ash_msg("can't access tty; job control turned off");
4043                                 mflag = on = 0;
4044                                 goto close;
4045                         }
4046                         if (pgrp == getpgrp())
4047                                 break;
4048                         killpg(0, SIGTTIN);
4049                 }
4050                 initialpgrp = pgrp;
4051
4052                 setsignal(SIGTSTP);
4053                 setsignal(SIGTTOU);
4054                 setsignal(SIGTTIN);
4055                 pgrp = rootpid;
4056                 setpgid(0, pgrp);
4057                 xtcsetpgrp(fd, pgrp);
4058         } else {
4059                 /* turning job control off */
4060                 fd = ttyfd;
4061                 pgrp = initialpgrp;
4062                 /* was xtcsetpgrp, but this can make exiting ash
4063                  * loop forever if pty is already deleted */
4064                 tcsetpgrp(fd, pgrp);
4065                 setpgid(0, pgrp);
4066                 setsignal(SIGTSTP);
4067                 setsignal(SIGTTOU);
4068                 setsignal(SIGTTIN);
4069  close:
4070                 if (fd >= 0)
4071                         close(fd);
4072                 fd = -1;
4073         }
4074         ttyfd = fd;
4075         doing_jobctl = on;
4076 }
4077
4078 static int FAST_FUNC
4079 killcmd(int argc, char **argv)
4080 {
4081         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4082                 int i = 1;
4083                 do {
4084                         if (argv[i][0] == '%') {
4085                                 /*
4086                                  * "kill %N" - job kill
4087                                  * Converting to pgrp / pid kill
4088                                  */
4089                                 struct job *jp;
4090                                 char *dst;
4091                                 int j, n;
4092
4093                                 jp = getjob(argv[i], 0);
4094                                 /*
4095                                  * In jobs started under job control, we signal
4096                                  * entire process group by kill -PGRP_ID.
4097                                  * This happens, f.e., in interactive shell.
4098                                  *
4099                                  * Otherwise, we signal each child via
4100                                  * kill PID1 PID2 PID3.
4101                                  * Testcases:
4102                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4103                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4104                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4105                                  */
4106                                 n = jp->nprocs; /* can't be 0 (I hope) */
4107                                 if (jp->jobctl)
4108                                         n = 1;
4109                                 dst = alloca(n * sizeof(int)*4);
4110                                 argv[i] = dst;
4111                                 for (j = 0; j < n; j++) {
4112                                         struct procstat *ps = &jp->ps[j];
4113                                         /* Skip non-running and not-stopped members
4114                                          * (i.e. dead members) of the job
4115                                          */
4116                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4117                                                 continue;
4118                                         /*
4119                                          * kill_main has matching code to expect
4120                                          * leading space. Needed to not confuse
4121                                          * negative pids with "kill -SIGNAL_NO" syntax
4122                                          */
4123                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4124                                 }
4125                                 *dst = '\0';
4126                         }
4127                 } while (argv[++i]);
4128         }
4129         return kill_main(argc, argv);
4130 }
4131
4132 static void
4133 showpipe(struct job *jp /*, FILE *out*/)
4134 {
4135         struct procstat *ps;
4136         struct procstat *psend;
4137
4138         psend = jp->ps + jp->nprocs;
4139         for (ps = jp->ps + 1; ps < psend; ps++)
4140                 printf(" | %s", ps->ps_cmd);
4141         newline_and_flush(stdout);
4142         flush_stdout_stderr();
4143 }
4144
4145
4146 static int
4147 restartjob(struct job *jp, int mode)
4148 {
4149         struct procstat *ps;
4150         int i;
4151         int status;
4152         pid_t pgid;
4153
4154         INT_OFF;
4155         if (jp->state == JOBDONE)
4156                 goto out;
4157         jp->state = JOBRUNNING;
4158         pgid = jp->ps[0].ps_pid;
4159         if (mode == FORK_FG) {
4160                 get_tty_state();
4161                 xtcsetpgrp(ttyfd, pgid);
4162         }
4163         killpg(pgid, SIGCONT);
4164         ps = jp->ps;
4165         i = jp->nprocs;
4166         do {
4167                 if (WIFSTOPPED(ps->ps_status)) {
4168                         ps->ps_status = -1;
4169                 }
4170                 ps++;
4171         } while (--i);
4172  out:
4173         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4174         INT_ON;
4175         return status;
4176 }
4177
4178 static int FAST_FUNC
4179 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4180 {
4181         struct job *jp;
4182         int mode;
4183         int retval;
4184
4185         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4186         nextopt(nullstr);
4187         argv = argptr;
4188         do {
4189                 jp = getjob(*argv, 1);
4190                 if (mode == FORK_BG) {
4191                         set_curjob(jp, CUR_RUNNING);
4192                         printf("[%d] ", jobno(jp));
4193                 }
4194                 out1str(jp->ps[0].ps_cmd);
4195                 showpipe(jp /*, stdout*/);
4196                 retval = restartjob(jp, mode);
4197         } while (*argv && *++argv);
4198         return retval;
4199 }
4200 #endif
4201
4202 static int
4203 sprint_status48(char *s, int status, int sigonly)
4204 {
4205         int col;
4206         int st;
4207
4208         col = 0;
4209         if (!WIFEXITED(status)) {
4210 #if JOBS
4211                 if (WIFSTOPPED(status))
4212                         st = WSTOPSIG(status);
4213                 else
4214 #endif
4215                         st = WTERMSIG(status);
4216                 if (sigonly) {
4217                         if (st == SIGINT || st == SIGPIPE)
4218                                 goto out;
4219 #if JOBS
4220                         if (WIFSTOPPED(status))
4221                                 goto out;
4222 #endif
4223                 }
4224                 st &= 0x7f;
4225 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4226                 col = fmtstr(s, 32, strsignal(st));
4227                 if (WCOREDUMP(status)) {
4228                         strcpy(s + col, " (core dumped)");
4229                         col += sizeof(" (core dumped)")-1;
4230                 }
4231         } else if (!sigonly) {
4232                 st = WEXITSTATUS(status);
4233                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4234         }
4235  out:
4236         return col;
4237 }
4238
4239 static int
4240 wait_block_or_sig(int *status)
4241 {
4242         int pid;
4243
4244         do {
4245                 sigset_t mask;
4246
4247                 /* Poll all children for changes in their state */
4248                 got_sigchld = 0;
4249                 /* if job control is active, accept stopped processes too */
4250                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4251                 if (pid != 0)
4252                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4253
4254                 /* Children exist, but none are ready. Sleep until interesting signal */
4255 #if 1
4256                 sigfillset(&mask);
4257                 sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */
4258                 while (!got_sigchld && !pending_sig)
4259                         sigsuspend(&mask);
4260                 sigprocmask(SIG_SETMASK, &mask, NULL);
4261 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4262                 while (!got_sigchld && !pending_sig)
4263                         pause();
4264 #endif
4265
4266                 /* If it was SIGCHLD, poll children again */
4267         } while (got_sigchld);
4268
4269         return pid;
4270 }
4271
4272 #define DOWAIT_NONBLOCK 0
4273 #define DOWAIT_BLOCK    1
4274 #define DOWAIT_BLOCK_OR_SIG 2
4275 #if BASH_WAIT_N
4276 # define DOWAIT_JOBSTATUS 0x10   /* OR this to get job's exitstatus instead of pid */
4277 #endif
4278
4279 static int
4280 dowait(int block, struct job *job)
4281 {
4282         int pid;
4283         int status;
4284         struct job *jp;
4285         struct job *thisjob;
4286 #if BASH_WAIT_N
4287         bool want_jobexitstatus = (block & DOWAIT_JOBSTATUS);
4288         block = (block & ~DOWAIT_JOBSTATUS);
4289 #endif
4290
4291         TRACE(("dowait(0x%x) called\n", block));
4292
4293         /* It's wrong to call waitpid() outside of INT_OFF region:
4294          * signal can arrive just after syscall return and handler can
4295          * longjmp away, losing stop/exit notification processing.
4296          * Thus, for "jobs" builtin, and for waiting for a fg job,
4297          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4298          *
4299          * However, for "wait" builtin it is wrong to simply call waitpid()
4300          * in INT_OFF region: "wait" needs to wait for any running job
4301          * to change state, but should exit on any trap too.
4302          * In INT_OFF region, a signal just before syscall entry can set
4303          * pending_sig variables, but we can't check them, and we would
4304          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4305          *
4306          * Because of this, we run inside INT_OFF, but use a special routine
4307          * which combines waitpid() and sigsuspend().
4308          * This is the reason why we need to have a handler for SIGCHLD:
4309          * SIG_DFL handler does not wake sigsuspend().
4310          */
4311         INT_OFF;
4312         if (block == DOWAIT_BLOCK_OR_SIG) {
4313                 pid = wait_block_or_sig(&status);
4314         } else {
4315                 int wait_flags = 0;
4316                 if (block == DOWAIT_NONBLOCK)
4317                         wait_flags = WNOHANG;
4318                 /* if job control is active, accept stopped processes too */
4319                 if (doing_jobctl)
4320                         wait_flags |= WUNTRACED;
4321                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4322                 pid = waitpid(-1, &status, wait_flags);
4323         }
4324         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4325                                 pid, status, errno, strerror(errno)));
4326         thisjob = NULL;
4327         if (pid <= 0)
4328                 goto out;
4329
4330         for (jp = curjob; jp; jp = jp->prev_job) {
4331                 int jobstate;
4332                 struct procstat *ps;
4333                 struct procstat *psend;
4334                 if (jp->state == JOBDONE)
4335                         continue;
4336                 jobstate = JOBDONE;
4337                 ps = jp->ps;
4338                 psend = ps + jp->nprocs;
4339                 do {
4340                         if (ps->ps_pid == pid) {
4341                                 TRACE(("Job %d: changing status of proc %d "
4342                                         "from 0x%x to 0x%x\n",
4343                                         jobno(jp), pid, ps->ps_status, status));
4344                                 ps->ps_status = status;
4345                                 thisjob = jp;
4346                         }
4347                         if (ps->ps_status == -1)
4348                                 jobstate = JOBRUNNING;
4349 #if JOBS
4350                         if (jobstate == JOBRUNNING)
4351                                 continue;
4352                         if (WIFSTOPPED(ps->ps_status)) {
4353                                 jp->stopstatus = ps->ps_status;
4354                                 jobstate = JOBSTOPPED;
4355                         }
4356 #endif
4357                 } while (++ps < psend);
4358                 if (!thisjob)
4359                         continue;
4360
4361                 /* Found the job where one of its processes changed its state.
4362                  * Is there at least one live and running process in this job? */
4363                 if (jobstate != JOBRUNNING) {
4364                         /* No. All live processes in the job are stopped
4365                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4366                          */
4367                         thisjob->changed = 1;
4368                         if (thisjob->state != jobstate) {
4369                                 TRACE(("Job %d: changing state from %d to %d\n",
4370                                         jobno(thisjob), thisjob->state, jobstate));
4371                                 thisjob->state = jobstate;
4372 #if JOBS
4373                                 if (jobstate == JOBSTOPPED)
4374                                         set_curjob(thisjob, CUR_STOPPED);
4375 #endif
4376                         }
4377                 }
4378                 goto out;
4379         }
4380         /* The process wasn't found in job list */
4381 #if JOBS
4382         if (!WIFSTOPPED(status))
4383                 jobless--;
4384 #endif
4385  out:
4386         INT_ON;
4387
4388 #if BASH_WAIT_N
4389         if (want_jobexitstatus) {
4390                 pid = -1;
4391                 if (thisjob && thisjob->state == JOBDONE)
4392                         pid = thisjob->ps[thisjob->nprocs - 1].ps_status;
4393         }
4394 #endif
4395         if (thisjob && thisjob == job) {
4396                 char s[48 + 1];
4397                 int len;
4398
4399                 len = sprint_status48(s, status, 1);
4400                 if (len) {
4401                         s[len] = '\n';
4402                         s[len + 1] = '\0';
4403                         out2str(s);
4404                 }
4405         }
4406         return pid;
4407 }
4408
4409 #if JOBS
4410 static void
4411 showjob(struct job *jp, int mode)
4412 {
4413         struct procstat *ps;
4414         struct procstat *psend;
4415         int col;
4416         int indent_col;
4417         char s[16 + 16 + 48];
4418         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4419
4420         ps = jp->ps;
4421
4422         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4423                 /* just output process (group) id of pipeline */
4424                 fprintf(out, "%d\n", ps->ps_pid);
4425                 return;
4426         }
4427
4428         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4429         indent_col = col;
4430
4431         if (jp == curjob)
4432                 s[col - 3] = '+';
4433         else if (curjob && jp == curjob->prev_job)
4434                 s[col - 3] = '-';
4435
4436         if (mode & SHOW_PIDS)
4437                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4438
4439         psend = ps + jp->nprocs;
4440
4441         if (jp->state == JOBRUNNING) {
4442                 strcpy(s + col, "Running");
4443                 col += sizeof("Running") - 1;
4444         } else {
4445                 int status = psend[-1].ps_status;
4446                 if (jp->state == JOBSTOPPED)
4447                         status = jp->stopstatus;
4448                 col += sprint_status48(s + col, status, 0);
4449         }
4450         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4451
4452         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4453          * or prints several "PID             | <cmdN>" lines,
4454          * depending on SHOW_PIDS bit.
4455          * We do not print status of individual processes
4456          * between PID and <cmdN>. bash does it, but not very well:
4457          * first line shows overall job status, not process status,
4458          * making it impossible to know 1st process status.
4459          */
4460         goto start;
4461         do {
4462                 /* for each process */
4463                 s[0] = '\0';
4464                 col = 33;
4465                 if (mode & SHOW_PIDS)
4466                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4467  start:
4468                 fprintf(out, "%s%*c%s%s",
4469                                 s,
4470                                 33 - col >= 0 ? 33 - col : 0, ' ',
4471                                 ps == jp->ps ? "" : "| ",
4472                                 ps->ps_cmd
4473                 );
4474         } while (++ps != psend);
4475         newline_and_flush(out);
4476
4477         jp->changed = 0;
4478
4479         if (jp->state == JOBDONE) {
4480                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4481                 freejob(jp);
4482         }
4483 }
4484
4485 /*
4486  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4487  * statuses have changed since the last call to showjobs.
4488  */
4489 static void
4490 showjobs(int mode)
4491 {
4492         struct job *jp;
4493
4494         TRACE(("showjobs(0x%x) called\n", mode));
4495
4496         /* Handle all finished jobs */
4497         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4498                 continue;
4499
4500         for (jp = curjob; jp; jp = jp->prev_job) {
4501                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4502                         showjob(jp, mode);
4503                 }
4504         }
4505 }
4506
4507 static int FAST_FUNC
4508 jobscmd(int argc UNUSED_PARAM, char **argv)
4509 {
4510         int mode, m;
4511
4512         mode = 0;
4513         while ((m = nextopt("lp")) != '\0') {
4514                 if (m == 'l')
4515                         mode |= SHOW_PIDS;
4516                 else
4517                         mode |= SHOW_ONLY_PGID;
4518         }
4519
4520         argv = argptr;
4521         if (*argv) {
4522                 do
4523                         showjob(getjob(*argv, 0), mode);
4524                 while (*++argv);
4525         } else {
4526                 showjobs(mode);
4527         }
4528
4529         return 0;
4530 }
4531 #endif /* JOBS */
4532
4533 /* Called only on finished or stopped jobs (no members are running) */
4534 static int
4535 getstatus(struct job *job)
4536 {
4537         int status;
4538         int retval;
4539         struct procstat *ps;
4540
4541         /* Fetch last member's status */
4542         ps = job->ps + job->nprocs - 1;
4543         status = ps->ps_status;
4544         if (pipefail) {
4545                 /* "set -o pipefail" mode: use last _nonzero_ status */
4546                 while (status == 0 && --ps >= job->ps)
4547                         status = ps->ps_status;
4548         }
4549
4550         retval = WEXITSTATUS(status);
4551         if (!WIFEXITED(status)) {
4552 #if JOBS
4553                 retval = WSTOPSIG(status);
4554                 if (!WIFSTOPPED(status))
4555 #endif
4556                 {
4557                         /* XXX: limits number of signals */
4558                         retval = WTERMSIG(status);
4559 #if JOBS
4560                         if (retval == SIGINT)
4561                                 job->sigint = 1;
4562 #endif
4563                 }
4564                 retval += 128;
4565         }
4566         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4567                 jobno(job), job->nprocs, status, retval));
4568         return retval;
4569 }
4570
4571 static int FAST_FUNC
4572 waitcmd(int argc UNUSED_PARAM, char **argv)
4573 {
4574         struct job *job;
4575         int retval;
4576         struct job *jp;
4577 #if BASH_WAIT_N
4578         int status;
4579         char one = nextopt("n");
4580 #else
4581         nextopt(nullstr);
4582 #endif
4583         retval = 0;
4584
4585         argv = argptr;
4586         if (!argv[0]) {
4587                 /* wait for all jobs / one job if -n */
4588                 for (;;) {
4589                         jp = curjob;
4590 #if BASH_WAIT_N
4591                         if (one && !jp)
4592                                 /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */
4593                                 retval = 127;
4594 #endif
4595                         while (1) {
4596                                 if (!jp) /* no running procs */
4597                                         goto ret;
4598                                 if (jp->state == JOBRUNNING)
4599                                         break;
4600                                 jp->waited = 1;
4601                                 jp = jp->prev_job;
4602                         }
4603         /* man bash:
4604          * "When bash is waiting for an asynchronous command via
4605          * the wait builtin, the reception of a signal for which a trap
4606          * has been set will cause the wait builtin to return immediately
4607          * with an exit status greater than 128, immediately after which
4608          * the trap is executed."
4609          */
4610 #if BASH_WAIT_N
4611                         status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL);
4612 #else
4613                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4614 #endif
4615         /* if child sends us a signal *and immediately exits*,
4616          * dowait() returns pid > 0. Check this case,
4617          * not "if (dowait() < 0)"!
4618          */
4619                         if (pending_sig)
4620                                 goto sigout;
4621 #if BASH_WAIT_N
4622                         if (one) {
4623                                 /* wait -n waits for one _job_, not one _process_.
4624                                  *  date; sleep 3 & sleep 2 | sleep 1 & wait -n; date
4625                                  * should wait for 2 seconds. Not 1 or 3.
4626                                  */
4627                                 if (status != -1 && !WIFSTOPPED(status)) {
4628                                         retval = WEXITSTATUS(status);
4629                                         if (WIFSIGNALED(status))
4630                                                 retval = WTERMSIG(status) + 128;
4631                                         goto ret;
4632                                 }
4633                         }
4634 #endif
4635                 }
4636         }
4637
4638         retval = 127;
4639         do {
4640                 if (**argv != '%') {
4641                         pid_t pid = number(*argv);
4642                         job = curjob;
4643                         while (1) {
4644                                 if (!job)
4645                                         goto repeat;
4646                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4647                                         break;
4648                                 job = job->prev_job;
4649                         }
4650                 } else {
4651                         job = getjob(*argv, 0);
4652                 }
4653                 /* loop until process terminated or stopped */
4654                 while (job->state == JOBRUNNING) {
4655                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4656                         if (pending_sig)
4657                                 goto sigout;
4658                 }
4659                 job->waited = 1;
4660                 retval = getstatus(job);
4661  repeat: ;
4662         } while (*++argv);
4663
4664  ret:
4665         return retval;
4666  sigout:
4667         retval = 128 + pending_sig;
4668         return retval;
4669 }
4670
4671 static struct job *
4672 growjobtab(void)
4673 {
4674         size_t len;
4675         ptrdiff_t offset;
4676         struct job *jp, *jq;
4677
4678         len = njobs * sizeof(*jp);
4679         jq = jobtab;
4680         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4681
4682         offset = (char *)jp - (char *)jq;
4683         if (offset) {
4684                 /* Relocate pointers */
4685                 size_t l = len;
4686
4687                 jq = (struct job *)((char *)jq + l);
4688                 while (l) {
4689                         l -= sizeof(*jp);
4690                         jq--;
4691 #define joff(p) ((struct job *)((char *)(p) + l))
4692 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4693                         if (joff(jp)->ps == &jq->ps0)
4694                                 jmove(joff(jp)->ps);
4695                         if (joff(jp)->prev_job)
4696                                 jmove(joff(jp)->prev_job);
4697                 }
4698                 if (curjob)
4699                         jmove(curjob);
4700 #undef joff
4701 #undef jmove
4702         }
4703
4704         njobs += 4;
4705         jobtab = jp;
4706         jp = (struct job *)((char *)jp + len);
4707         jq = jp + 3;
4708         do {
4709                 jq->used = 0;
4710         } while (--jq >= jp);
4711         return jp;
4712 }
4713
4714 /*
4715  * Return a new job structure.
4716  * Called with interrupts off.
4717  */
4718 static struct job *
4719 makejob(/*union node *node,*/ int nprocs)
4720 {
4721         int i;
4722         struct job *jp;
4723
4724         for (i = njobs, jp = jobtab; ; jp++) {
4725                 if (--i < 0) {
4726                         jp = growjobtab();
4727                         break;
4728                 }
4729                 if (jp->used == 0)
4730                         break;
4731                 if (jp->state != JOBDONE || !jp->waited)
4732                         continue;
4733 #if JOBS
4734                 if (doing_jobctl)
4735                         continue;
4736 #endif
4737                 freejob(jp);
4738                 break;
4739         }
4740         memset(jp, 0, sizeof(*jp));
4741 #if JOBS
4742         /* jp->jobctl is a bitfield.
4743          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4744         if (doing_jobctl)
4745                 jp->jobctl = 1;
4746 #endif
4747         jp->prev_job = curjob;
4748         curjob = jp;
4749         jp->used = 1;
4750         jp->ps = &jp->ps0;
4751         if (nprocs > 1) {
4752                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4753         }
4754         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4755                                 jobno(jp)));
4756         return jp;
4757 }
4758
4759 #if JOBS
4760 /*
4761  * Return a string identifying a command (to be printed by the
4762  * jobs command).
4763  */
4764 static char *cmdnextc;
4765
4766 static void
4767 cmdputs(const char *s)
4768 {
4769         static const char vstype[VSTYPE + 1][3] = {
4770                 "", "}", "-", "+", "?", "=",
4771                 "%", "%%", "#", "##"
4772                 IF_BASH_SUBSTR(, ":")
4773                 IF_BASH_PATTERN_SUBST(, "/", "//")
4774         };
4775
4776         const char *p, *str;
4777         char cc[2];
4778         char *nextc;
4779         unsigned char c;
4780         unsigned char subtype = 0;
4781         int quoted = 0;
4782
4783         cc[1] = '\0';
4784         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4785         p = s;
4786         while ((c = *p++) != '\0') {
4787                 str = NULL;
4788                 switch (c) {
4789                 case CTLESC:
4790                         c = *p++;
4791                         break;
4792                 case CTLVAR:
4793                         subtype = *p++;
4794                         if ((subtype & VSTYPE) == VSLENGTH)
4795                                 str = "${#";
4796                         else
4797                                 str = "${";
4798                         goto dostr;
4799                 case CTLENDVAR:
4800                         str = "\"}" + !(quoted & 1);
4801                         quoted >>= 1;
4802                         subtype = 0;
4803                         goto dostr;
4804                 case CTLBACKQ:
4805                         str = "$(...)";
4806                         goto dostr;
4807 #if ENABLE_FEATURE_SH_MATH
4808                 case CTLARI:
4809                         str = "$((";
4810                         goto dostr;
4811                 case CTLENDARI:
4812                         str = "))";
4813                         goto dostr;
4814 #endif
4815                 case CTLQUOTEMARK:
4816                         quoted ^= 1;
4817                         c = '"';
4818                         break;
4819                 case '=':
4820                         if (subtype == 0)
4821                                 break;
4822                         if ((subtype & VSTYPE) != VSNORMAL)
4823                                 quoted <<= 1;
4824                         str = vstype[subtype & VSTYPE];
4825                         if (subtype & VSNUL)
4826                                 c = ':';
4827                         else
4828                                 goto checkstr;
4829                         break;
4830                 case '\'':
4831                 case '\\':
4832                 case '"':
4833                 case '$':
4834                         /* These can only happen inside quotes */
4835                         cc[0] = c;
4836                         str = cc;
4837 //FIXME:
4838 // $ true $$ &
4839 // $ <cr>
4840 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4841                         c = '\\';
4842                         break;
4843                 default:
4844                         break;
4845                 }
4846                 USTPUTC(c, nextc);
4847  checkstr:
4848                 if (!str)
4849                         continue;
4850  dostr:
4851                 while ((c = *str++) != '\0') {
4852                         USTPUTC(c, nextc);
4853                 }
4854         } /* while *p++ not NUL */
4855
4856         if (quoted & 1) {
4857                 USTPUTC('"', nextc);
4858         }
4859         *nextc = 0;
4860         cmdnextc = nextc;
4861 }
4862
4863 /* cmdtxt() and cmdlist() call each other */
4864 static void cmdtxt(union node *n);
4865
4866 static void
4867 cmdlist(union node *np, int sep)
4868 {
4869         for (; np; np = np->narg.next) {
4870                 if (!sep)
4871                         cmdputs(" ");
4872                 cmdtxt(np);
4873                 if (sep && np->narg.next)
4874                         cmdputs(" ");
4875         }
4876 }
4877
4878 static void
4879 cmdtxt(union node *n)
4880 {
4881         union node *np;
4882         struct nodelist *lp;
4883         const char *p;
4884
4885         if (!n)
4886                 return;
4887         switch (n->type) {
4888         default:
4889 #if DEBUG
4890                 abort();
4891 #endif
4892         case NPIPE:
4893                 lp = n->npipe.cmdlist;
4894                 for (;;) {
4895                         cmdtxt(lp->n);
4896                         lp = lp->next;
4897                         if (!lp)
4898                                 break;
4899                         cmdputs(" | ");
4900                 }
4901                 break;
4902         case NSEMI:
4903                 p = "; ";
4904                 goto binop;
4905         case NAND:
4906                 p = " && ";
4907                 goto binop;
4908         case NOR:
4909                 p = " || ";
4910  binop:
4911                 cmdtxt(n->nbinary.ch1);
4912                 cmdputs(p);
4913                 n = n->nbinary.ch2;
4914                 goto donode;
4915         case NREDIR:
4916         case NBACKGND:
4917                 n = n->nredir.n;
4918                 goto donode;
4919         case NNOT:
4920                 cmdputs("!");
4921                 n = n->nnot.com;
4922  donode:
4923                 cmdtxt(n);
4924                 break;
4925         case NIF:
4926                 cmdputs("if ");
4927                 cmdtxt(n->nif.test);
4928                 cmdputs("; then ");
4929                 if (n->nif.elsepart) {
4930                         cmdtxt(n->nif.ifpart);
4931                         cmdputs("; else ");
4932                         n = n->nif.elsepart;
4933                 } else {
4934                         n = n->nif.ifpart;
4935                 }
4936                 p = "; fi";
4937                 goto dotail;
4938         case NSUBSHELL:
4939                 cmdputs("(");
4940                 n = n->nredir.n;
4941                 p = ")";
4942                 goto dotail;
4943         case NWHILE:
4944                 p = "while ";
4945                 goto until;
4946         case NUNTIL:
4947                 p = "until ";
4948  until:
4949                 cmdputs(p);
4950                 cmdtxt(n->nbinary.ch1);
4951                 n = n->nbinary.ch2;
4952                 p = "; done";
4953  dodo:
4954                 cmdputs("; do ");
4955  dotail:
4956                 cmdtxt(n);
4957                 goto dotail2;
4958         case NFOR:
4959                 cmdputs("for ");
4960                 cmdputs(n->nfor.var);
4961                 cmdputs(" in ");
4962                 cmdlist(n->nfor.args, 1);
4963                 n = n->nfor.body;
4964                 p = "; done";
4965                 goto dodo;
4966         case NDEFUN:
4967                 cmdputs(n->ndefun.text);
4968                 p = "() { ... }";
4969                 goto dotail2;
4970         case NCMD:
4971                 cmdlist(n->ncmd.args, 1);
4972                 cmdlist(n->ncmd.redirect, 0);
4973                 break;
4974         case NARG:
4975                 p = n->narg.text;
4976  dotail2:
4977                 cmdputs(p);
4978                 break;
4979         case NHERE:
4980         case NXHERE:
4981                 p = "<<...";
4982                 goto dotail2;
4983         case NCASE:
4984                 cmdputs("case ");
4985                 cmdputs(n->ncase.expr->narg.text);
4986                 cmdputs(" in ");
4987                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4988                         cmdtxt(np->nclist.pattern);
4989                         cmdputs(") ");
4990                         cmdtxt(np->nclist.body);
4991                         cmdputs(";; ");
4992                 }
4993                 p = "esac";
4994                 goto dotail2;
4995         case NTO:
4996                 p = ">";
4997                 goto redir;
4998         case NCLOBBER:
4999                 p = ">|";
5000                 goto redir;
5001         case NAPPEND:
5002                 p = ">>";
5003                 goto redir;
5004 #if BASH_REDIR_OUTPUT
5005         case NTO2:
5006 #endif
5007         case NTOFD:
5008                 p = ">&";
5009                 goto redir;
5010         case NFROM:
5011                 p = "<";
5012                 goto redir;
5013         case NFROMFD:
5014                 p = "<&";
5015                 goto redir;
5016         case NFROMTO:
5017                 p = "<>";
5018  redir:
5019                 cmdputs(utoa(n->nfile.fd));
5020                 cmdputs(p);
5021                 if (n->type == NTOFD || n->type == NFROMFD) {
5022                         if (n->ndup.dupfd >= 0)
5023                                 cmdputs(utoa(n->ndup.dupfd));
5024                         else
5025                                 cmdputs("-");
5026                         break;
5027                 }
5028                 n = n->nfile.fname;
5029                 goto donode;
5030         }
5031 }
5032
5033 static char *
5034 commandtext(union node *n)
5035 {
5036         char *name;
5037
5038         STARTSTACKSTR(cmdnextc);
5039         cmdtxt(n);
5040         name = stackblock();
5041         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
5042         return ckstrdup(name);
5043 }
5044 #endif /* JOBS */
5045
5046 /*
5047  * Fork off a subshell.  If we are doing job control, give the subshell its
5048  * own process group.  Jp is a job structure that the job is to be added to.
5049  * N is the command that will be evaluated by the child.  Both jp and n may
5050  * be NULL.  The mode parameter can be one of the following:
5051  *      FORK_FG - Fork off a foreground process.
5052  *      FORK_BG - Fork off a background process.
5053  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
5054  *                   process group even if job control is on.
5055  *
5056  * When job control is turned off, background processes have their standard
5057  * input redirected to /dev/null (except for the second and later processes
5058  * in a pipeline).
5059  *
5060  * Called with interrupts off.
5061  */
5062 /*
5063  * Clear traps on a fork.
5064  */
5065 static void
5066 clear_traps(void)
5067 {
5068         char **tp;
5069
5070         INT_OFF;
5071         for (tp = trap; tp < &trap[NSIG]; tp++) {
5072                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
5073                         if (trap_ptr == trap)
5074                                 free(*tp);
5075                         /* else: it "belongs" to trap_ptr vector, don't free */
5076                         *tp = NULL;
5077                         if ((tp - trap) != 0)
5078                                 setsignal(tp - trap);
5079                 }
5080         }
5081         may_have_traps = 0;
5082         INT_ON;
5083 }
5084
5085 /* Lives far away from here, needed for forkchild */
5086 static void closescript(void);
5087
5088 /* Called after fork(), in child */
5089 /* jp and n are NULL when called by openhere() for heredoc support */
5090 static NOINLINE void
5091 forkchild(struct job *jp, union node *n, int mode)
5092 {
5093         int oldlvl;
5094
5095         TRACE(("Child shell %d\n", getpid()));
5096         oldlvl = shlvl;
5097         shlvl++;
5098
5099         /* man bash: "Non-builtin commands run by bash have signal handlers
5100          * set to the values inherited by the shell from its parent".
5101          * Do we do it correctly? */
5102
5103         closescript();
5104
5105         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5106          && n && n->type == NCMD        /* is it single cmd? */
5107         /* && n->ncmd.args->type == NARG - always true? */
5108          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5109          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5110         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5111         ) {
5112                 TRACE(("Trap hack\n"));
5113                 /* Awful hack for `trap` or $(trap).
5114                  *
5115                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5116                  * contains an example where "trap" is executed in a subshell:
5117                  *
5118                  * save_traps=$(trap)
5119                  * ...
5120                  * eval "$save_traps"
5121                  *
5122                  * Standard does not say that "trap" in subshell shall print
5123                  * parent shell's traps. It only says that its output
5124                  * must have suitable form, but then, in the above example
5125                  * (which is not supposed to be normative), it implies that.
5126                  *
5127                  * bash (and probably other shell) does implement it
5128                  * (traps are reset to defaults, but "trap" still shows them),
5129                  * but as a result, "trap" logic is hopelessly messed up:
5130                  *
5131                  * # trap
5132                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5133                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5134                  * # true | trap   <--- trap is in subshell - no output (ditto)
5135                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5136                  * trap -- 'echo Ho' SIGWINCH
5137                  * # echo `(trap)`         <--- in subshell in subshell - output
5138                  * trap -- 'echo Ho' SIGWINCH
5139                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5140                  * trap -- 'echo Ho' SIGWINCH
5141                  *
5142                  * The rules when to forget and when to not forget traps
5143                  * get really complex and nonsensical.
5144                  *
5145                  * Our solution: ONLY bare $(trap) or `trap` is special.
5146                  */
5147                 /* Save trap handler strings for trap builtin to print */
5148                 trap_ptr = xmemdup(trap, sizeof(trap));
5149                 /* Fall through into clearing traps */
5150         }
5151         clear_traps();
5152 #if JOBS
5153         /* do job control only in root shell */
5154         doing_jobctl = 0;
5155         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5156                 pid_t pgrp;
5157
5158                 if (jp->nprocs == 0)
5159                         pgrp = getpid();
5160                 else
5161                         pgrp = jp->ps[0].ps_pid;
5162                 /* this can fail because we are doing it in the parent also */
5163                 setpgid(0, pgrp);
5164                 if (mode == FORK_FG)
5165                         xtcsetpgrp(ttyfd, pgrp);
5166                 setsignal(SIGTSTP);
5167                 setsignal(SIGTTOU);
5168         } else
5169 #endif
5170         if (mode == FORK_BG) {
5171                 /* man bash: "When job control is not in effect,
5172                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5173                 ignoresig(SIGINT);
5174                 ignoresig(SIGQUIT);
5175                 if (jp->nprocs == 0) {
5176                         close(0);
5177                         if (open(bb_dev_null, O_RDONLY) != 0)
5178                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5179                 }
5180         }
5181         if (oldlvl == 0) {
5182                 if (iflag) { /* why if iflag only? */
5183                         setsignal(SIGINT);
5184                         setsignal(SIGTERM);
5185                 }
5186                 /* man bash:
5187                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5188                  * commands run by bash have signal handlers
5189                  * set to the values inherited by the shell
5190                  * from its parent".
5191                  * Take care of the second rule: */
5192                 setsignal(SIGQUIT);
5193         }
5194 #if JOBS
5195         if (n && n->type == NCMD
5196          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5197         ) {
5198                 TRACE(("Job hack\n"));
5199                 /* "jobs": we do not want to clear job list for it,
5200                  * instead we remove only _its_ own_ job from job list.
5201                  * This makes "jobs .... | cat" more useful.
5202                  */
5203                 freejob(curjob);
5204                 return;
5205         }
5206 #endif
5207         for (jp = curjob; jp; jp = jp->prev_job)
5208                 freejob(jp);
5209         jobless = 0;
5210 }
5211
5212 /* Called after fork(), in parent */
5213 #if !JOBS
5214 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5215 #endif
5216 static void
5217 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5218 {
5219         TRACE(("In parent shell: child = %d\n", pid));
5220         if (!jp) {
5221                 /* jp is NULL when called by openhere() for heredoc support */
5222                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5223                         continue;
5224                 jobless++;
5225                 return;
5226         }
5227 #if JOBS
5228         if (mode != FORK_NOJOB && jp->jobctl) {
5229                 int pgrp;
5230
5231                 if (jp->nprocs == 0)
5232                         pgrp = pid;
5233                 else
5234                         pgrp = jp->ps[0].ps_pid;
5235                 /* This can fail because we are doing it in the child also */
5236                 setpgid(pid, pgrp);
5237         }
5238 #endif
5239         if (mode == FORK_BG) {
5240                 backgndpid = pid;               /* set $! */
5241                 set_curjob(jp, CUR_RUNNING);
5242         }
5243         if (jp) {
5244                 struct procstat *ps = &jp->ps[jp->nprocs++];
5245                 ps->ps_pid = pid;
5246                 ps->ps_status = -1;
5247                 ps->ps_cmd = nullstr;
5248 #if JOBS
5249                 if (doing_jobctl && n)
5250                         ps->ps_cmd = commandtext(n);
5251 #endif
5252         }
5253 }
5254
5255 /* jp and n are NULL when called by openhere() for heredoc support */
5256 static int
5257 forkshell(struct job *jp, union node *n, int mode)
5258 {
5259         int pid;
5260
5261         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5262         pid = fork();
5263         if (pid < 0) {
5264                 TRACE(("Fork failed, errno=%d", errno));
5265                 if (jp)
5266                         freejob(jp);
5267                 ash_msg_and_raise_perror("can't fork");
5268         }
5269         if (pid == 0) {
5270                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5271                 forkchild(jp, n, mode);
5272         } else {
5273                 forkparent(jp, n, mode, pid);
5274         }
5275         return pid;
5276 }
5277
5278 /*
5279  * Wait for job to finish.
5280  *
5281  * Under job control we have the problem that while a child process
5282  * is running interrupts generated by the user are sent to the child
5283  * but not to the shell.  This means that an infinite loop started by
5284  * an interactive user may be hard to kill.  With job control turned off,
5285  * an interactive user may place an interactive program inside a loop.
5286  * If the interactive program catches interrupts, the user doesn't want
5287  * these interrupts to also abort the loop.  The approach we take here
5288  * is to have the shell ignore interrupt signals while waiting for a
5289  * foreground process to terminate, and then send itself an interrupt
5290  * signal if the child process was terminated by an interrupt signal.
5291  * Unfortunately, some programs want to do a bit of cleanup and then
5292  * exit on interrupt; unless these processes terminate themselves by
5293  * sending a signal to themselves (instead of calling exit) they will
5294  * confuse this approach.
5295  *
5296  * Called with interrupts off.
5297  */
5298 static int
5299 waitforjob(struct job *jp)
5300 {
5301         int st;
5302
5303         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5304
5305         INT_OFF;
5306         while (jp->state == JOBRUNNING) {
5307                 /* In non-interactive shells, we _can_ get
5308                  * a keyboard signal here and be EINTRed,
5309                  * but we just loop back, waiting for command to complete.
5310                  *
5311                  * man bash:
5312                  * "If bash is waiting for a command to complete and receives
5313                  * a signal for which a trap has been set, the trap
5314                  * will not be executed until the command completes."
5315                  *
5316                  * Reality is that even if trap is not set, bash
5317                  * will not act on the signal until command completes.
5318                  * Try this. sleep5intoff.c:
5319                  * #include <signal.h>
5320                  * #include <unistd.h>
5321                  * int main() {
5322                  *         sigset_t set;
5323                  *         sigemptyset(&set);
5324                  *         sigaddset(&set, SIGINT);
5325                  *         sigaddset(&set, SIGQUIT);
5326                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5327                  *         sleep(5);
5328                  *         return 0;
5329                  * }
5330                  * $ bash -c './sleep5intoff; echo hi'
5331                  * ^C^C^C^C <--- pressing ^C once a second
5332                  * $ _
5333                  * $ bash -c './sleep5intoff; echo hi'
5334                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5335                  * $ _
5336                  */
5337                 dowait(DOWAIT_BLOCK, jp);
5338         }
5339         INT_ON;
5340
5341         st = getstatus(jp);
5342 #if JOBS
5343         if (jp->jobctl) {
5344                 xtcsetpgrp(ttyfd, rootpid);
5345                 restore_tty_if_stopped_or_signaled(jp);
5346
5347                 /*
5348                  * This is truly gross.
5349                  * If we're doing job control, then we did a TIOCSPGRP which
5350                  * caused us (the shell) to no longer be in the controlling
5351                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5352                  * intuit from the subprocess exit status whether a SIGINT
5353                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5354                  */
5355                 if (jp->sigint) /* TODO: do the same with all signals */
5356                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5357         }
5358         if (jp->state == JOBDONE)
5359 #endif
5360                 freejob(jp);
5361         return st;
5362 }
5363
5364 /*
5365  * return 1 if there are stopped jobs, otherwise 0
5366  */
5367 static int
5368 stoppedjobs(void)
5369 {
5370         struct job *jp;
5371         int retval;
5372
5373         retval = 0;
5374         if (job_warning)
5375                 goto out;
5376         jp = curjob;
5377         if (jp && jp->state == JOBSTOPPED) {
5378                 out2str("You have stopped jobs.\n");
5379                 job_warning = 2;
5380                 retval++;
5381         }
5382  out:
5383         return retval;
5384 }
5385
5386
5387 /*
5388  * Code for dealing with input/output redirection.
5389  */
5390
5391 #undef EMPTY
5392 #undef CLOSED
5393 #define EMPTY -2                /* marks an unused slot in redirtab */
5394 #define CLOSED -1               /* marks a slot of previously-closed fd */
5395
5396 /*
5397  * Handle here documents.  Normally we fork off a process to write the
5398  * data to a pipe.  If the document is short, we can stuff the data in
5399  * the pipe without forking.
5400  */
5401 /* openhere needs this forward reference */
5402 static void expandhere(union node *arg, int fd);
5403 static int
5404 openhere(union node *redir)
5405 {
5406         int pip[2];
5407         size_t len = 0;
5408
5409         if (pipe(pip) < 0)
5410                 ash_msg_and_raise_perror("can't create pipe");
5411         if (redir->type == NHERE) {
5412                 len = strlen(redir->nhere.doc->narg.text);
5413                 if (len <= PIPE_BUF) {
5414                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5415                         goto out;
5416                 }
5417         }
5418         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5419                 /* child */
5420                 close(pip[0]);
5421                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5422                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5423                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5424                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5425                 signal(SIGPIPE, SIG_DFL);
5426                 if (redir->type == NHERE)
5427                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5428                 else /* NXHERE */
5429                         expandhere(redir->nhere.doc, pip[1]);
5430                 _exit(EXIT_SUCCESS);
5431         }
5432  out:
5433         close(pip[1]);
5434         return pip[0];
5435 }
5436
5437 static int
5438 openredirect(union node *redir)
5439 {
5440         struct stat sb;
5441         char *fname;
5442         int f;
5443
5444         switch (redir->nfile.type) {
5445 /* Can't happen, our single caller does this itself */
5446 //      case NTOFD:
5447 //      case NFROMFD:
5448 //              return -1;
5449         case NHERE:
5450         case NXHERE:
5451                 return openhere(redir);
5452         }
5453
5454         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5455          * allocated space. Do it only when we know it is safe.
5456          */
5457         fname = redir->nfile.expfname;
5458
5459         switch (redir->nfile.type) {
5460         default:
5461 #if DEBUG
5462                 abort();
5463 #endif
5464         case NFROM:
5465                 f = open(fname, O_RDONLY);
5466                 if (f < 0)
5467                         goto eopen;
5468                 break;
5469         case NFROMTO:
5470                 f = open(fname, O_RDWR|O_CREAT, 0666);
5471                 if (f < 0)
5472                         goto ecreate;
5473                 break;
5474         case NTO:
5475 #if BASH_REDIR_OUTPUT
5476         case NTO2:
5477 #endif
5478                 /* Take care of noclobber mode. */
5479                 if (Cflag) {
5480                         if (stat(fname, &sb) < 0) {
5481                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5482                                 if (f < 0)
5483                                         goto ecreate;
5484                         } else if (!S_ISREG(sb.st_mode)) {
5485                                 f = open(fname, O_WRONLY, 0666);
5486                                 if (f < 0)
5487                                         goto ecreate;
5488                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5489                                         close(f);
5490                                         errno = EEXIST;
5491                                         goto ecreate;
5492                                 }
5493                         } else {
5494                                 errno = EEXIST;
5495                                 goto ecreate;
5496                         }
5497                         break;
5498                 }
5499                 /* FALLTHROUGH */
5500         case NCLOBBER:
5501                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5502                 if (f < 0)
5503                         goto ecreate;
5504                 break;
5505         case NAPPEND:
5506                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5507                 if (f < 0)
5508                         goto ecreate;
5509                 break;
5510         }
5511
5512         return f;
5513  ecreate:
5514         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5515  eopen:
5516         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5517 }
5518
5519 /*
5520  * Copy a file descriptor to be >= 10. Throws exception on error.
5521  */
5522 static int
5523 savefd(int from)
5524 {
5525         int newfd;
5526         int err;
5527
5528         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5529         err = newfd < 0 ? errno : 0;
5530         if (err != EBADF) {
5531                 if (err)
5532                         ash_msg_and_raise_perror("%d", from);
5533                 close(from);
5534                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5535                         close_on_exec_on(newfd);
5536         }
5537
5538         return newfd;
5539 }
5540 static int
5541 dup2_or_raise(int from, int to)
5542 {
5543         int newfd;
5544
5545         newfd = (from != to) ? dup2(from, to) : to;
5546         if (newfd < 0) {
5547                 /* Happens when source fd is not open: try "echo >&99" */
5548                 ash_msg_and_raise_perror("%d", from);
5549         }
5550         return newfd;
5551 }
5552 static int
5553 dup_CLOEXEC(int fd, int avoid_fd)
5554 {
5555         int newfd;
5556  repeat:
5557         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5558         if (newfd >= 0) {
5559                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5560                         close_on_exec_on(newfd);
5561         } else { /* newfd < 0 */
5562                 if (errno == EBUSY)
5563                         goto repeat;
5564                 if (errno == EINTR)
5565                         goto repeat;
5566         }
5567         return newfd;
5568 }
5569 static int
5570 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5571 {
5572         int newfd;
5573  repeat:
5574         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5575         if (newfd < 0) {
5576                 if (errno == EBUSY)
5577                         goto repeat;
5578                 if (errno == EINTR)
5579                         goto repeat;
5580                 /* fd was not open? */
5581                 if (errno == EBADF)
5582                         return fd;
5583                 ash_msg_and_raise_perror("%d", newfd);
5584         }
5585         if (F_DUPFD_CLOEXEC == F_DUPFD)
5586                 close_on_exec_on(newfd);
5587         close(fd);
5588         return newfd;
5589 }
5590
5591 /* Struct def and variable are moved down to the first usage site */
5592 struct squirrel {
5593         int orig_fd;
5594         int moved_to;
5595 };
5596 struct redirtab {
5597         struct redirtab *next;
5598         int pair_count;
5599         struct squirrel two_fd[];
5600 };
5601 #define redirlist (G_var.redirlist)
5602
5603 static void
5604 add_squirrel_closed(struct redirtab *sq, int fd)
5605 {
5606         int i;
5607
5608         if (!sq)
5609                 return;
5610
5611         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5612                 /* If we collide with an already moved fd... */
5613                 if (fd == sq->two_fd[i].orig_fd) {
5614                         /* Examples:
5615                          * "echo 3>FILE 3>&- 3>FILE"
5616                          * "echo 3>&- 3>FILE"
5617                          * No need for last redirect to insert
5618                          * another "need to close 3" indicator.
5619                          */
5620                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5621                         return;
5622                 }
5623         }
5624         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5625         sq->two_fd[i].orig_fd = fd;
5626         sq->two_fd[i].moved_to = CLOSED;
5627 }
5628
5629 static int
5630 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5631 {
5632         int i, new_fd;
5633
5634         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5635                 avoid_fd = 9;
5636
5637 #if JOBS
5638         if (fd == ttyfd) {
5639                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5640                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5641                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5642                 return 1; /* "we closed fd" */
5643         }
5644 #endif
5645         /* Are we called from redirect(0)? E.g. redirect
5646          * in a forked child. No need to save fds,
5647          * we aren't going to use them anymore, ok to trash.
5648          */
5649         if (!sq)
5650                 return 0;
5651
5652         /* If this one of script's fds? */
5653         if (fd != 0) {
5654                 struct parsefile *pf = g_parsefile;
5655                 while (pf) {
5656                         /* We skip fd == 0 case because of the following:
5657                          * $ ash  # running ash interactively
5658                          * $ . ./script.sh
5659                          * and in script.sh: "exec 9>&0".
5660                          * Even though top-level pf_fd _is_ 0,
5661                          * it's still ok to use it: "read" builtin uses it,
5662                          * why should we cripple "exec" builtin?
5663                          */
5664                         if (fd == pf->pf_fd) {
5665                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5666                                 return 1; /* "we closed fd" */
5667                         }
5668                         pf = pf->prev;
5669                 }
5670         }
5671
5672         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5673
5674         /* First: do we collide with some already moved fds? */
5675         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5676                 /* If we collide with an already moved fd... */
5677                 if (fd == sq->two_fd[i].moved_to) {
5678                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5679                         sq->two_fd[i].moved_to = new_fd;
5680                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5681                         if (new_fd < 0) /* what? */
5682                                 xfunc_die();
5683                         return 0; /* "we did not close fd" */
5684                 }
5685                 if (fd == sq->two_fd[i].orig_fd) {
5686                         /* Example: echo Hello >/dev/null 1>&2 */
5687                         TRACE(("redirect_fd %d: already moved\n", fd));
5688                         return 0; /* "we did not close fd" */
5689                 }
5690         }
5691
5692         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5693         new_fd = dup_CLOEXEC(fd, avoid_fd);
5694         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5695         if (new_fd < 0) {
5696                 if (errno != EBADF)
5697                         xfunc_die();
5698                 /* new_fd = CLOSED; - already is -1 */
5699         }
5700         sq->two_fd[i].moved_to = new_fd;
5701         sq->two_fd[i].orig_fd = fd;
5702
5703         /* if we move stderr, let "set -x" code know */
5704         if (fd == preverrout_fd)
5705                 preverrout_fd = new_fd;
5706
5707         return 0; /* "we did not close fd" */
5708 }
5709
5710 static int
5711 internally_opened_fd(int fd, struct redirtab *sq)
5712 {
5713         int i;
5714 #if JOBS
5715         if (fd == ttyfd)
5716                 return 1;
5717 #endif
5718         /* If this one of script's fds? */
5719         if (fd != 0) {
5720                 struct parsefile *pf = g_parsefile;
5721                 while (pf) {
5722                         if (fd == pf->pf_fd)
5723                                 return 1;
5724                         pf = pf->prev;
5725                 }
5726         }
5727
5728         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5729                 if (fd == sq->two_fd[i].moved_to)
5730                         return 1;
5731         }
5732         return 0;
5733 }
5734
5735 /*
5736  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5737  * old file descriptors are stashed away so that the redirection can be
5738  * undone by calling popredir.
5739  */
5740 /* flags passed to redirect */
5741 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5742 static void
5743 redirect(union node *redir, int flags)
5744 {
5745         struct redirtab *sv;
5746
5747         if (!redir)
5748                 return;
5749
5750         sv = NULL;
5751         INT_OFF;
5752         if (flags & REDIR_PUSH)
5753                 sv = redirlist;
5754         do {
5755                 int fd;
5756                 int newfd;
5757                 int close_fd;
5758                 int closed;
5759
5760                 fd = redir->nfile.fd;
5761                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5762                         //bb_error_msg("doing %d > %d", fd, newfd);
5763                         newfd = redir->ndup.dupfd;
5764                         close_fd = -1;
5765                 } else {
5766                         newfd = openredirect(redir); /* always >= 0 */
5767                         if (fd == newfd) {
5768                                 /* open() gave us precisely the fd we wanted.
5769                                  * This means that this fd was not busy
5770                                  * (not opened to anywhere).
5771                                  * Remember to close it on restore:
5772                                  */
5773                                 add_squirrel_closed(sv, fd);
5774                                 continue;
5775                         }
5776                         close_fd = newfd;
5777                 }
5778
5779                 if (fd == newfd)
5780                         continue;
5781
5782                 /* if "N>FILE": move newfd to fd */
5783                 /* if "N>&M": dup newfd to fd */
5784                 /* if "N>&-": close fd (newfd is -1) */
5785
5786  IF_BASH_REDIR_OUTPUT(redirect_more:)
5787
5788                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5789                 if (newfd == -1) {
5790                         /* "N>&-" means "close me" */
5791                         if (!closed) {
5792                                 /* ^^^ optimization: saving may already
5793                                  * have closed it. If not... */
5794                                 close(fd);
5795                         }
5796                 } else {
5797                         /* if newfd is a script fd or saved fd, simulate EBADF */
5798                         if (internally_opened_fd(newfd, sv)) {
5799                                 errno = EBADF;
5800                                 ash_msg_and_raise_perror("%d", newfd);
5801                         }
5802                         dup2_or_raise(newfd, fd);
5803                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5804                                 close(close_fd);
5805 #if BASH_REDIR_OUTPUT
5806                         if (redir->nfile.type == NTO2 && fd == 1) {
5807                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5808                                 fd = 2;
5809                                 newfd = 1;
5810                                 close_fd = -1;
5811                                 goto redirect_more;
5812                         }
5813 #endif
5814                 }
5815         } while ((redir = redir->nfile.next) != NULL);
5816         INT_ON;
5817
5818 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5819 #define REDIR_SAVEFD2 0
5820         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5821         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5822         // not only for calls with flags containing REDIR_SAVEFD2.
5823         // We do this unconditionally (see save_fd_on_redirect()).
5824         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5825         //      preverrout_fd = copied_fd2;
5826 }
5827
5828 static int
5829 redirectsafe(union node *redir, int flags)
5830 {
5831         int err;
5832         volatile int saveint;
5833         struct jmploc *volatile savehandler = exception_handler;
5834         struct jmploc jmploc;
5835
5836         SAVE_INT(saveint);
5837         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5838         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5839         if (!err) {
5840                 exception_handler = &jmploc;
5841                 redirect(redir, flags);
5842         }
5843         exception_handler = savehandler;
5844         if (err && exception_type != EXERROR)
5845                 longjmp(exception_handler->loc, 1);
5846         RESTORE_INT(saveint);
5847         return err;
5848 }
5849
5850 static struct redirtab*
5851 pushredir(union node *redir)
5852 {
5853         struct redirtab *sv;
5854         int i;
5855
5856         if (!redir)
5857                 return redirlist;
5858
5859         i = 0;
5860         do {
5861                 i++;
5862 #if BASH_REDIR_OUTPUT
5863                 if (redir->nfile.type == NTO2)
5864                         i++;
5865 #endif
5866                 redir = redir->nfile.next;
5867         } while (redir);
5868
5869         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5870         sv->pair_count = i;
5871         while (--i >= 0)
5872                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5873         sv->next = redirlist;
5874         redirlist = sv;
5875         return sv->next;
5876 }
5877
5878 /*
5879  * Undo the effects of the last redirection.
5880  */
5881 static void
5882 popredir(int drop)
5883 {
5884         struct redirtab *rp;
5885         int i;
5886
5887         if (redirlist == NULL)
5888                 return;
5889         INT_OFF;
5890         rp = redirlist;
5891         for (i = 0; i < rp->pair_count; i++) {
5892                 int fd = rp->two_fd[i].orig_fd;
5893                 int copy = rp->two_fd[i].moved_to;
5894                 if (copy == CLOSED) {
5895                         if (!drop)
5896                                 close(fd);
5897                         continue;
5898                 }
5899                 if (copy != EMPTY) {
5900                         if (!drop) {
5901                                 /*close(fd);*/
5902                                 dup2_or_raise(copy, fd);
5903                         }
5904                         close(copy);
5905                 }
5906         }
5907         redirlist = rp->next;
5908         free(rp);
5909         INT_ON;
5910 }
5911
5912 static void
5913 unwindredir(struct redirtab *stop)
5914 {
5915         while (redirlist != stop)
5916                 popredir(/*drop:*/ 0);
5917 }
5918
5919
5920 /* ============ Routines to expand arguments to commands
5921  *
5922  * We have to deal with backquotes, shell variables, and file metacharacters.
5923  */
5924
5925 #if ENABLE_FEATURE_SH_MATH
5926 static arith_t
5927 ash_arith(const char *s)
5928 {
5929         arith_state_t math_state;
5930         arith_t result;
5931
5932         math_state.lookupvar = lookupvar;
5933         math_state.setvar    = setvar0;
5934         //math_state.endofname = endofname;
5935
5936         INT_OFF;
5937         result = arith(&math_state, s);
5938         if (math_state.errmsg)
5939                 ash_msg_and_raise_error(math_state.errmsg);
5940         INT_ON;
5941
5942         return result;
5943 }
5944 #endif
5945 #if BASH_SUBSTR
5946 # if ENABLE_FEATURE_SH_MATH
5947 static int substr_atoi(const char *s)
5948 {
5949         arith_t t = ash_arith(s);
5950         if (sizeof(t) > sizeof(int)) {
5951                 /* clamp very large or very large negative nums for ${v:N:M}:
5952                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5953                  */
5954                 if (t > INT_MAX)
5955                         t = INT_MAX;
5956                 if (t < INT_MIN)
5957                         t = INT_MIN;
5958         }
5959         return t;
5960 }
5961 # else
5962 #  define substr_atoi(s) number(s)
5963 # endif
5964 #endif
5965
5966 /*
5967  * expandarg flags
5968  */
5969 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5970 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5971 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5972 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5973 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5974  * POSIX says for this case:
5975  *  Pathname expansion shall not be performed on the word by a
5976  *  non-interactive shell; an interactive shell may perform it, but shall
5977  *  do so only when the expansion would result in one word.
5978  * Currently, our code complies to the above rule by never globbing
5979  * redirection filenames.
5980  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5981  * (this means that on a typical Linux distro, bash almost always
5982  * performs globbing, and thus diverges from what we do).
5983  */
5984 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5985 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
5986 #define EXP_WORD        0x40    /* expand word in parameter expansion */
5987 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5988 /*
5989  * rmescape() flags
5990  */
5991 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5992 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5993 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5994 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5995
5996 /* Add CTLESC when necessary. */
5997 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
5998 /* Do not skip NUL characters. */
5999 #define QUOTES_KEEPNUL EXP_TILDE
6000
6001 /*
6002  * Structure specifying which parts of the string should be searched
6003  * for IFS characters.
6004  */
6005 struct ifsregion {
6006         struct ifsregion *next; /* next region in list */
6007         int begoff;             /* offset of start of region */
6008         int endoff;             /* offset of end of region */
6009         int nulonly;            /* search for nul bytes only */
6010 };
6011
6012 struct arglist {
6013         struct strlist *list;
6014         struct strlist **lastp;
6015 };
6016
6017 /* output of current string */
6018 static char *expdest;
6019 /* list of back quote expressions */
6020 static struct nodelist *argbackq;
6021 /* first struct in list of ifs regions */
6022 static struct ifsregion ifsfirst;
6023 /* last struct in list */
6024 static struct ifsregion *ifslastp;
6025 /* holds expanded arg list */
6026 static struct arglist exparg;
6027
6028 /*
6029  * Our own itoa().
6030  * cvtnum() is used even if math support is off (to prepare $? values and such).
6031  */
6032 static int
6033 cvtnum(arith_t num)
6034 {
6035         int len;
6036
6037         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
6038         len = sizeof(arith_t) * 3;
6039         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
6040         if (sizeof(arith_t) < 4) len += 2;
6041
6042         expdest = makestrspace(len, expdest);
6043         len = fmtstr(expdest, len, ARITH_FMT, num);
6044         STADJUST(len, expdest);
6045         return len;
6046 }
6047
6048 /*
6049  * Break the argument string into pieces based upon IFS and add the
6050  * strings to the argument list.  The regions of the string to be
6051  * searched for IFS characters have been stored by recordregion.
6052  */
6053 static void
6054 ifsbreakup(char *string, struct arglist *arglist)
6055 {
6056         struct ifsregion *ifsp;
6057         struct strlist *sp;
6058         char *start;
6059         char *p;
6060         char *q;
6061         const char *ifs, *realifs;
6062         int ifsspc;
6063         int nulonly;
6064
6065         start = string;
6066         if (ifslastp != NULL) {
6067                 ifsspc = 0;
6068                 nulonly = 0;
6069                 realifs = ifsset() ? ifsval() : defifs;
6070                 ifsp = &ifsfirst;
6071                 do {
6072                         int afternul;
6073
6074                         p = string + ifsp->begoff;
6075                         afternul = nulonly;
6076                         nulonly = ifsp->nulonly;
6077                         ifs = nulonly ? nullstr : realifs;
6078                         ifsspc = 0;
6079                         while (p < string + ifsp->endoff) {
6080                                 q = p;
6081                                 if ((unsigned char)*p == CTLESC)
6082                                         p++;
6083                                 if (!strchr(ifs, *p)) {
6084                                         p++;
6085                                         continue;
6086                                 }
6087                                 if (!(afternul || nulonly))
6088                                         ifsspc = (strchr(defifs, *p) != NULL);
6089                                 /* Ignore IFS whitespace at start */
6090                                 if (q == start && ifsspc) {
6091                                         p++;
6092                                         start = p;
6093                                         continue;
6094                                 }
6095                                 *q = '\0';
6096                                 sp = stzalloc(sizeof(*sp));
6097                                 sp->text = start;
6098                                 *arglist->lastp = sp;
6099                                 arglist->lastp = &sp->next;
6100                                 p++;
6101                                 if (!nulonly) {
6102                                         for (;;) {
6103                                                 if (p >= string + ifsp->endoff) {
6104                                                         break;
6105                                                 }
6106                                                 q = p;
6107                                                 if ((unsigned char)*p == CTLESC)
6108                                                         p++;
6109                                                 if (strchr(ifs, *p) == NULL) {
6110                                                         p = q;
6111                                                         break;
6112                                                 }
6113                                                 if (strchr(defifs, *p) == NULL) {
6114                                                         if (ifsspc) {
6115                                                                 p++;
6116                                                                 ifsspc = 0;
6117                                                         } else {
6118                                                                 p = q;
6119                                                                 break;
6120                                                         }
6121                                                 } else
6122                                                         p++;
6123                                         }
6124                                 }
6125                                 start = p;
6126                         } /* while */
6127                         ifsp = ifsp->next;
6128                 } while (ifsp != NULL);
6129                 if (nulonly)
6130                         goto add;
6131         }
6132
6133         if (!*start)
6134                 return;
6135
6136  add:
6137         sp = stzalloc(sizeof(*sp));
6138         sp->text = start;
6139         *arglist->lastp = sp;
6140         arglist->lastp = &sp->next;
6141 }
6142
6143 static void
6144 ifsfree(void)
6145 {
6146         struct ifsregion *p = ifsfirst.next;
6147
6148         if (!p)
6149                 goto out;
6150
6151         INT_OFF;
6152         do {
6153                 struct ifsregion *ifsp;
6154                 ifsp = p->next;
6155                 free(p);
6156                 p = ifsp;
6157         } while (p);
6158         ifsfirst.next = NULL;
6159         INT_ON;
6160  out:
6161         ifslastp = NULL;
6162 }
6163
6164 static size_t
6165 esclen(const char *start, const char *p)
6166 {
6167         size_t esc = 0;
6168
6169         while (p > start && (unsigned char)*--p == CTLESC) {
6170                 esc++;
6171         }
6172         return esc;
6173 }
6174
6175 /*
6176  * Remove any CTLESC characters from a string.
6177  */
6178 #if !BASH_PATTERN_SUBST
6179 #define rmescapes(str, flag, slash_position) \
6180         rmescapes(str, flag)
6181 #endif
6182 static char *
6183 rmescapes(char *str, int flag, int *slash_position)
6184 {
6185         static const char qchars[] ALIGN1 = {
6186                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6187
6188         char *p, *q, *r;
6189         unsigned protect_against_glob;
6190         unsigned globbing;
6191
6192         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6193         if (!p)
6194                 return str;
6195
6196         q = p;
6197         r = str;
6198         if (flag & RMESCAPE_ALLOC) {
6199                 size_t len = p - str;
6200                 size_t fulllen = len + strlen(p) + 1;
6201
6202                 if (flag & RMESCAPE_GROW) {
6203                         int strloc = str - (char *)stackblock();
6204                         r = makestrspace(fulllen, expdest);
6205                         /* p and str may be invalidated by makestrspace */
6206                         str = (char *)stackblock() + strloc;
6207                         p = str + len;
6208                 } else if (flag & RMESCAPE_HEAP) {
6209                         r = ckmalloc(fulllen);
6210                 } else {
6211                         r = stalloc(fulllen);
6212                 }
6213                 q = r;
6214                 if (len > 0) {
6215                         q = (char *)mempcpy(q, str, len);
6216                 }
6217         }
6218
6219         globbing = flag & RMESCAPE_GLOB;
6220         protect_against_glob = globbing;
6221         while (*p) {
6222                 if ((unsigned char)*p == CTLQUOTEMARK) {
6223 // Note: protect_against_glob only affect whether
6224 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6225                         p++;
6226                         protect_against_glob = globbing;
6227                         continue;
6228                 }
6229                 if (*p == '\\') {
6230                         /* naked back slash */
6231                         protect_against_glob = 0;
6232                         goto copy;
6233                 }
6234                 if ((unsigned char)*p == CTLESC) {
6235                         p++;
6236 #if DEBUG
6237                         if (*p == '\0')
6238                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6239 #endif
6240                         if (protect_against_glob) {
6241                                 /*
6242                                  * We used to trust glob() and fnmatch() to eat
6243                                  * superfluous escapes (\z where z has no
6244                                  * special meaning anyway). But this causes
6245                                  * bugs such as string of one greek letter rho
6246                                  * (unicode-encoded as two bytes "cf,81")
6247                                  * getting encoded as "cf,CTLESC,81"
6248                                  * and here, converted to "cf,\,81" -
6249                                  * which does not go well with some flavors
6250                                  * of fnmatch() in unicode locales
6251                                  * (for example, glibc <= 2.22).
6252                                  *
6253                                  * Lets add "\" only on the chars which need it.
6254                                  * Testcases for less obvious chars are shown.
6255                                  */
6256                                 if (*p == '*'
6257                                  || *p == '?'
6258                                  || *p == '['
6259                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6260                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6261                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6262                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6263                                 /* Some libc support [^negate], that's why "^" also needs love */
6264                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6265                                 ) {
6266                                         *q++ = '\\';
6267                                 }
6268                         }
6269                 }
6270 #if BASH_PATTERN_SUBST
6271                 else if (slash_position && p == str + *slash_position) {
6272                         /* stop handling globbing */
6273                         globbing = 0;
6274                         *slash_position = q - r;
6275                         slash_position = NULL;
6276                 }
6277 #endif
6278                 protect_against_glob = globbing;
6279  copy:
6280                 *q++ = *p++;
6281         }
6282         *q = '\0';
6283         if (flag & RMESCAPE_GROW) {
6284                 expdest = r;
6285                 STADJUST(q - r + 1, expdest);
6286         }
6287         return r;
6288 }
6289 #define pmatch(a, b) !fnmatch((a), (b), 0)
6290
6291 /*
6292  * Prepare a pattern for a expmeta (internal glob(3)) call.
6293  *
6294  * Returns an stalloced string.
6295  */
6296 static char *
6297 preglob(const char *pattern, int flag)
6298 {
6299         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6300 }
6301
6302 /*
6303  * Put a string on the stack.
6304  */
6305 static void
6306 memtodest(const char *p, size_t len, int syntax, int quotes)
6307 {
6308         char *q;
6309
6310         if (!len)
6311                 return;
6312
6313         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6314
6315         do {
6316                 unsigned char c = *p++;
6317                 if (c) {
6318                         if (quotes & QUOTES_ESC) {
6319                                 int n = SIT(c, syntax);
6320                                 if (n == CCTL
6321                                  || (syntax != BASESYNTAX && n == CBACK)
6322                                 ) {
6323                                         USTPUTC(CTLESC, q);
6324                                 }
6325                         }
6326                 } else if (!(quotes & QUOTES_KEEPNUL))
6327                         continue;
6328                 USTPUTC(c, q);
6329         } while (--len);
6330
6331         expdest = q;
6332 }
6333
6334 static size_t
6335 strtodest(const char *p, int syntax, int quotes)
6336 {
6337         size_t len = strlen(p);
6338         memtodest(p, len, syntax, quotes);
6339         return len;
6340 }
6341
6342 /*
6343  * Record the fact that we have to scan this region of the
6344  * string for IFS characters.
6345  */
6346 static void
6347 recordregion(int start, int end, int nulonly)
6348 {
6349         struct ifsregion *ifsp;
6350
6351         if (ifslastp == NULL) {
6352                 ifsp = &ifsfirst;
6353         } else {
6354                 INT_OFF;
6355                 ifsp = ckzalloc(sizeof(*ifsp));
6356                 /*ifsp->next = NULL; - ckzalloc did it */
6357                 ifslastp->next = ifsp;
6358                 INT_ON;
6359         }
6360         ifslastp = ifsp;
6361         ifslastp->begoff = start;
6362         ifslastp->endoff = end;
6363         ifslastp->nulonly = nulonly;
6364 }
6365
6366 static void
6367 removerecordregions(int endoff)
6368 {
6369         if (ifslastp == NULL)
6370                 return;
6371
6372         if (ifsfirst.endoff > endoff) {
6373                 while (ifsfirst.next) {
6374                         struct ifsregion *ifsp;
6375                         INT_OFF;
6376                         ifsp = ifsfirst.next->next;
6377                         free(ifsfirst.next);
6378                         ifsfirst.next = ifsp;
6379                         INT_ON;
6380                 }
6381                 if (ifsfirst.begoff > endoff) {
6382                         ifslastp = NULL;
6383                 } else {
6384                         ifslastp = &ifsfirst;
6385                         ifsfirst.endoff = endoff;
6386                 }
6387                 return;
6388         }
6389
6390         ifslastp = &ifsfirst;
6391         while (ifslastp->next && ifslastp->next->begoff < endoff)
6392                 ifslastp = ifslastp->next;
6393         while (ifslastp->next) {
6394                 struct ifsregion *ifsp;
6395                 INT_OFF;
6396                 ifsp = ifslastp->next->next;
6397                 free(ifslastp->next);
6398                 ifslastp->next = ifsp;
6399                 INT_ON;
6400         }
6401         if (ifslastp->endoff > endoff)
6402                 ifslastp->endoff = endoff;
6403 }
6404
6405 static char *
6406 exptilde(char *startp, char *p, int flags)
6407 {
6408         unsigned char c;
6409         char *name;
6410         struct passwd *pw;
6411         const char *home;
6412         int quotes = flags & QUOTES_ESC;
6413
6414         name = p + 1;
6415
6416         while ((c = *++p) != '\0') {
6417                 switch (c) {
6418                 case CTLESC:
6419                         return startp;
6420                 case CTLQUOTEMARK:
6421                         return startp;
6422                 case ':':
6423                         if (flags & EXP_VARTILDE)
6424                                 goto done;
6425                         break;
6426                 case '/':
6427                 case CTLENDVAR:
6428                         goto done;
6429                 }
6430         }
6431  done:
6432         *p = '\0';
6433         if (*name == '\0') {
6434                 home = lookupvar("HOME");
6435         } else {
6436                 pw = getpwnam(name);
6437                 if (pw == NULL)
6438                         goto lose;
6439                 home = pw->pw_dir;
6440         }
6441         if (!home || !*home)
6442                 goto lose;
6443         *p = c;
6444         strtodest(home, SQSYNTAX, quotes);
6445         return p;
6446  lose:
6447         *p = c;
6448         return startp;
6449 }
6450
6451 /*
6452  * Execute a command inside back quotes.  If it's a builtin command, we
6453  * want to save its output in a block obtained from malloc.  Otherwise
6454  * we fork off a subprocess and get the output of the command via a pipe.
6455  * Should be called with interrupts off.
6456  */
6457 struct backcmd {                /* result of evalbackcmd */
6458         int fd;                 /* file descriptor to read from */
6459         int nleft;              /* number of chars in buffer */
6460         char *buf;              /* buffer */
6461         struct job *jp;         /* job structure for command */
6462 };
6463
6464 /* These forward decls are needed to use "eval" code for backticks handling: */
6465 /* flags in argument to evaltree */
6466 #define EV_EXIT    01           /* exit after evaluating tree */
6467 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6468 static int evaltree(union node *, int);
6469
6470 /* An evaltree() which is known to never return.
6471  * Used to use an alias:
6472  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6473  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6474  */
6475 static ALWAYS_INLINE NORETURN void
6476 evaltreenr(union node *n, int flags)
6477 {
6478         evaltree(n, flags);
6479         bb_unreachable(abort());
6480         /* NOTREACHED */
6481 }
6482
6483 static void FAST_FUNC
6484 evalbackcmd(union node *n, struct backcmd *result)
6485 {
6486         int pip[2];
6487         struct job *jp;
6488
6489         result->fd = -1;
6490         result->buf = NULL;
6491         result->nleft = 0;
6492         result->jp = NULL;
6493         if (n == NULL) {
6494                 goto out;
6495         }
6496
6497         if (pipe(pip) < 0)
6498                 ash_msg_and_raise_perror("can't create pipe");
6499         jp = makejob(/*n,*/ 1);
6500         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6501                 /* child */
6502                 FORCE_INT_ON;
6503                 close(pip[0]);
6504                 if (pip[1] != 1) {
6505                         /*close(1);*/
6506                         dup2_or_raise(pip[1], 1);
6507                         close(pip[1]);
6508                 }
6509 /* TODO: eflag clearing makes the following not abort:
6510  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6511  * which is what bash does (unless it is in POSIX mode).
6512  * dash deleted "eflag = 0" line in the commit
6513  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6514  *  [EVAL] Don't clear eflag in evalbackcmd
6515  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6516  */
6517                 eflag = 0;
6518                 ifsfree();
6519                 evaltreenr(n, EV_EXIT);
6520                 /* NOTREACHED */
6521         }
6522         /* parent */
6523         close(pip[1]);
6524         result->fd = pip[0];
6525         result->jp = jp;
6526
6527  out:
6528         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6529                 result->fd, result->buf, result->nleft, result->jp));
6530 }
6531
6532 /*
6533  * Expand stuff in backwards quotes.
6534  */
6535 static void
6536 expbackq(union node *cmd, int flag)
6537 {
6538         struct backcmd in;
6539         int i;
6540         char buf[128];
6541         char *p;
6542         char *dest;
6543         int startloc;
6544         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6545         struct stackmark smark;
6546
6547         INT_OFF;
6548         startloc = expdest - (char *)stackblock();
6549         pushstackmark(&smark, startloc);
6550         evalbackcmd(cmd, &in);
6551         popstackmark(&smark);
6552
6553         p = in.buf;
6554         i = in.nleft;
6555         if (i == 0)
6556                 goto read;
6557         for (;;) {
6558                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6559  read:
6560                 if (in.fd < 0)
6561                         break;
6562                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6563                 TRACE(("expbackq: read returns %d\n", i));
6564                 if (i <= 0)
6565                         break;
6566                 p = buf;
6567         }
6568
6569         free(in.buf);
6570         if (in.fd >= 0) {
6571                 close(in.fd);
6572                 back_exitstatus = waitforjob(in.jp);
6573         }
6574         INT_ON;
6575
6576         /* Eat all trailing newlines */
6577         dest = expdest;
6578         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6579                 STUNPUTC(dest);
6580         expdest = dest;
6581
6582         if (!(flag & EXP_QUOTED))
6583                 recordregion(startloc, dest - (char *)stackblock(), 0);
6584         TRACE(("evalbackq: size:%d:'%.*s'\n",
6585                 (int)((dest - (char *)stackblock()) - startloc),
6586                 (int)((dest - (char *)stackblock()) - startloc),
6587                 stackblock() + startloc));
6588 }
6589
6590 #if ENABLE_FEATURE_SH_MATH
6591 /*
6592  * Expand arithmetic expression.  Backup to start of expression,
6593  * evaluate, place result in (backed up) result, adjust string position.
6594  */
6595 static void
6596 expari(int flag)
6597 {
6598         char *p, *start;
6599         int begoff;
6600         int len;
6601
6602         /* ifsfree(); */
6603
6604         /*
6605          * This routine is slightly over-complicated for
6606          * efficiency.  Next we scan backwards looking for the
6607          * start of arithmetic.
6608          */
6609         start = stackblock();
6610         p = expdest - 1;
6611         *p = '\0';
6612         p--;
6613         while (1) {
6614                 int esc;
6615
6616                 while ((unsigned char)*p != CTLARI) {
6617                         p--;
6618 #if DEBUG
6619                         if (p < start) {
6620                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6621                         }
6622 #endif
6623                 }
6624
6625                 esc = esclen(start, p);
6626                 if (!(esc % 2)) {
6627                         break;
6628                 }
6629
6630                 p -= esc + 1;
6631         }
6632
6633         begoff = p - start;
6634
6635         removerecordregions(begoff);
6636
6637         expdest = p;
6638
6639         if (flag & QUOTES_ESC)
6640                 rmescapes(p + 1, 0, NULL);
6641
6642         len = cvtnum(ash_arith(p + 1));
6643
6644         if (!(flag & EXP_QUOTED))
6645                 recordregion(begoff, begoff + len, 0);
6646 }
6647 #endif
6648
6649 /* argstr needs it */
6650 static char *evalvar(char *p, int flags);
6651
6652 /*
6653  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6654  * characters to allow for further processing.  Otherwise treat
6655  * $@ like $* since no splitting will be performed.
6656  */
6657 static void
6658 argstr(char *p, int flags)
6659 {
6660         static const char spclchars[] ALIGN1 = {
6661                 '=',
6662                 ':',
6663                 CTLQUOTEMARK,
6664                 CTLENDVAR,
6665                 CTLESC,
6666                 CTLVAR,
6667                 CTLBACKQ,
6668 #if ENABLE_FEATURE_SH_MATH
6669                 CTLENDARI,
6670 #endif
6671                 '\0'
6672         };
6673         const char *reject = spclchars;
6674         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6675         int inquotes;
6676         size_t length;
6677         int startloc;
6678
6679         if (!(flags & EXP_VARTILDE)) {
6680                 reject += 2;
6681         } else if (flags & EXP_VARTILDE2) {
6682                 reject++;
6683         }
6684         inquotes = 0;
6685         length = 0;
6686         if (flags & EXP_TILDE) {
6687                 char *q;
6688
6689                 flags &= ~EXP_TILDE;
6690  tilde:
6691                 q = p;
6692                 if (*q == '~')
6693                         p = exptilde(p, q, flags);
6694         }
6695  start:
6696         startloc = expdest - (char *)stackblock();
6697         for (;;) {
6698                 unsigned char c;
6699
6700                 length += strcspn(p + length, reject);
6701                 c = p[length];
6702                 if (c) {
6703                         if (!(c & 0x80)
6704                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6705                         ) {
6706                                 /* c == '=' || c == ':' || c == CTLENDARI */
6707                                 length++;
6708                         }
6709                 }
6710                 if (length > 0) {
6711                         int newloc;
6712                         expdest = stack_nputstr(p, length, expdest);
6713                         newloc = expdest - (char *)stackblock();
6714                         if (breakall && !inquotes && newloc > startloc) {
6715                                 recordregion(startloc, newloc, 0);
6716                         }
6717                         startloc = newloc;
6718                 }
6719                 p += length + 1;
6720                 length = 0;
6721
6722                 switch (c) {
6723                 case '\0':
6724                         goto breakloop;
6725                 case '=':
6726                         if (flags & EXP_VARTILDE2) {
6727                                 p--;
6728                                 continue;
6729                         }
6730                         flags |= EXP_VARTILDE2;
6731                         reject++;
6732                         /* fall through */
6733                 case ':':
6734                         /*
6735                          * sort of a hack - expand tildes in variable
6736                          * assignments (after the first '=' and after ':'s).
6737                          */
6738                         if (*--p == '~') {
6739                                 goto tilde;
6740                         }
6741                         continue;
6742                 }
6743
6744                 switch (c) {
6745                 case CTLENDVAR: /* ??? */
6746                         goto breakloop;
6747                 case CTLQUOTEMARK:
6748                         /* "$@" syntax adherence hack */
6749                         if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6750                                 p = evalvar(p + 1, flags | EXP_QUOTED) + 1;
6751                                 goto start;
6752                         }
6753                         inquotes ^= EXP_QUOTED;
6754  addquote:
6755                         if (flags & QUOTES_ESC) {
6756                                 p--;
6757                                 length++;
6758                                 startloc++;
6759                         }
6760                         break;
6761                 case CTLESC:
6762                         startloc++;
6763                         length++;
6764                         goto addquote;
6765                 case CTLVAR:
6766                         TRACE(("argstr: evalvar('%s')\n", p));
6767                         p = evalvar(p, flags | inquotes);
6768                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6769                         goto start;
6770                 case CTLBACKQ:
6771                         expbackq(argbackq->n, flags | inquotes);
6772                         argbackq = argbackq->next;
6773                         goto start;
6774 #if ENABLE_FEATURE_SH_MATH
6775                 case CTLENDARI:
6776                         p--;
6777                         expari(flags | inquotes);
6778                         goto start;
6779 #endif
6780                 }
6781         }
6782  breakloop: ;
6783 }
6784
6785 static char *
6786 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6787                 char *pattern, int quotes, int zero)
6788 {
6789         char *loc, *loc2;
6790         char c;
6791
6792         loc = startp;
6793         loc2 = rmesc;
6794         do {
6795                 int match;
6796                 const char *s = loc2;
6797
6798                 c = *loc2;
6799                 if (zero) {
6800                         *loc2 = '\0';
6801                         s = rmesc;
6802                 }
6803                 match = pmatch(pattern, s);
6804
6805                 *loc2 = c;
6806                 if (match)
6807                         return loc;
6808                 if (quotes && (unsigned char)*loc == CTLESC)
6809                         loc++;
6810                 loc++;
6811                 loc2++;
6812         } while (c);
6813         return NULL;
6814 }
6815
6816 static char *
6817 scanright(char *startp, char *rmesc, char *rmescend,
6818                 char *pattern, int quotes, int match_at_start)
6819 {
6820 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6821         int try2optimize = match_at_start;
6822 #endif
6823         int esc = 0;
6824         char *loc;
6825         char *loc2;
6826
6827         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6828          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6829          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6830          * Logic:
6831          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6832          * and on each iteration they go back two/one char until they reach the beginning.
6833          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6834          */
6835         /* TODO: document in what other circumstances we are called. */
6836
6837         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6838                 int match;
6839                 char c = *loc2;
6840                 const char *s = loc2;
6841                 if (match_at_start) {
6842                         *loc2 = '\0';
6843                         s = rmesc;
6844                 }
6845                 match = pmatch(pattern, s);
6846                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6847                 *loc2 = c;
6848                 if (match)
6849                         return loc;
6850 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6851                 if (try2optimize) {
6852                         /* Maybe we can optimize this:
6853                          * if pattern ends with unescaped *, we can avoid checking
6854                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6855                          * it won't match truncated "raw_value_of_" strings too.
6856                          */
6857                         unsigned plen = strlen(pattern);
6858                         /* Does it end with "*"? */
6859                         if (plen != 0 && pattern[--plen] == '*') {
6860                                 /* "xxxx*" is not escaped */
6861                                 /* "xxx\*" is escaped */
6862                                 /* "xx\\*" is not escaped */
6863                                 /* "x\\\*" is escaped */
6864                                 int slashes = 0;
6865                                 while (plen != 0 && pattern[--plen] == '\\')
6866                                         slashes++;
6867                                 if (!(slashes & 1))
6868                                         break; /* ends with unescaped "*" */
6869                         }
6870                         try2optimize = 0;
6871                 }
6872 #endif
6873                 loc--;
6874                 if (quotes) {
6875                         if (--esc < 0) {
6876                                 esc = esclen(startp, loc);
6877                         }
6878                         if (esc % 2) {
6879                                 esc--;
6880                                 loc--;
6881                         }
6882                 }
6883         }
6884         return NULL;
6885 }
6886
6887 static void varunset(const char *, const char *, const char *, int) NORETURN;
6888 static void
6889 varunset(const char *end, const char *var, const char *umsg, int varflags)
6890 {
6891         const char *msg;
6892         const char *tail;
6893
6894         tail = nullstr;
6895         msg = "parameter not set";
6896         if (umsg) {
6897                 if ((unsigned char)*end == CTLENDVAR) {
6898                         if (varflags & VSNUL)
6899                                 tail = " or null";
6900                 } else {
6901                         msg = umsg;
6902                 }
6903         }
6904         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6905 }
6906
6907 static const char *
6908 subevalvar(char *p, char *varname, int strloc, int subtype,
6909                 int startloc, int varflags, int flag)
6910 {
6911         struct nodelist *saveargbackq = argbackq;
6912         int quotes = flag & QUOTES_ESC;
6913         char *startp;
6914         char *loc;
6915         char *rmesc, *rmescend;
6916         char *str;
6917         int amount, resetloc;
6918         int argstr_flags;
6919         IF_BASH_PATTERN_SUBST(int workloc;)
6920         IF_BASH_PATTERN_SUBST(int slash_pos;)
6921         IF_BASH_PATTERN_SUBST(char *repl;)
6922         int zero;
6923         char *(*scan)(char*, char*, char*, char*, int, int);
6924
6925         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6926         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6927
6928 #if BASH_PATTERN_SUBST
6929         /* For "${v/pattern/repl}", we must find the delimiter _before_
6930          * argstr() call expands possible variable references in pattern:
6931          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6932          */
6933         repl = NULL;
6934         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6935                 /* Find '/' and replace with NUL */
6936                 repl = p;
6937                 /* The pattern can't be empty.
6938                  * IOW: if the first char after "${v//" is a slash,
6939                  * it does not terminate the pattern - it's the first char of the pattern:
6940                  *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
6941                  *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
6942                  */
6943                 if (*repl == '/')
6944                         repl++;
6945                 for (;;) {
6946                         if (*repl == '\0') {
6947                                 repl = NULL;
6948                                 break;
6949                         }
6950                         if (*repl == '/') {
6951                                 *repl = '\0';
6952                                 break;
6953                         }
6954                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6955                         if ((unsigned char)*repl == CTLESC && repl[1])
6956                                 repl++;
6957                         repl++;
6958                 }
6959         }
6960 #endif
6961         argstr_flags = EXP_TILDE;
6962         if (subtype != VSASSIGN
6963          && subtype != VSQUESTION
6964 #if BASH_SUBSTR
6965          && subtype != VSSUBSTR
6966 #endif
6967         ) {
6968                 /* EXP_CASE keeps CTLESC's */
6969                 argstr_flags = EXP_TILDE | EXP_CASE;
6970         }
6971         argstr(p, argstr_flags);
6972         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
6973 #if BASH_PATTERN_SUBST
6974         slash_pos = -1;
6975         if (repl) {
6976                 slash_pos = expdest - ((char *)stackblock() + strloc);
6977                 STPUTC('/', expdest);
6978                 //bb_error_msg("repl+1:'%s'", repl + 1);
6979                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
6980                 *repl = '/';
6981         }
6982 #endif
6983         STPUTC('\0', expdest);
6984         argbackq = saveargbackq;
6985         startp = (char *)stackblock() + startloc;
6986         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6987
6988         switch (subtype) {
6989         case VSASSIGN:
6990                 setvar0(varname, startp);
6991                 amount = startp - expdest;
6992                 STADJUST(amount, expdest);
6993                 return startp;
6994
6995         case VSQUESTION:
6996                 varunset(p, varname, startp, varflags);
6997                 /* NOTREACHED */
6998
6999 #if BASH_SUBSTR
7000         case VSSUBSTR: {
7001                 int pos, len, orig_len;
7002                 char *colon;
7003
7004                 loc = str = stackblock() + strloc;
7005
7006                 /* Read POS in ${var:POS:LEN} */
7007                 colon = strchr(loc, ':');
7008                 if (colon) *colon = '\0';
7009                 pos = substr_atoi(loc);
7010                 if (colon) *colon = ':';
7011
7012                 /* Read LEN in ${var:POS:LEN} */
7013                 len = str - startp - 1;
7014                 /* *loc != '\0', guaranteed by parser */
7015                 if (quotes) {
7016                         char *ptr;
7017                         /* Adjust the length by the number of escapes */
7018                         for (ptr = startp; ptr < (str - 1); ptr++) {
7019                                 if ((unsigned char)*ptr == CTLESC) {
7020                                         len--;
7021                                         ptr++;
7022                                 }
7023                         }
7024                 }
7025                 orig_len = len;
7026                 if (*loc++ == ':') {
7027                         /* ${var::LEN} */
7028                         len = substr_atoi(loc);
7029                 } else {
7030                         /* Skip POS in ${var:POS:LEN} */
7031                         len = orig_len;
7032                         while (*loc && *loc != ':')
7033                                 loc++;
7034                         if (*loc++ == ':')
7035                                 len = substr_atoi(loc);
7036                 }
7037                 if (pos < 0) {
7038                         /* ${VAR:$((-n)):l} starts n chars from the end */
7039                         pos = orig_len + pos;
7040                 }
7041                 if ((unsigned)pos >= orig_len) {
7042                         /* apart from obvious ${VAR:999999:l},
7043                          * covers ${VAR:$((-9999999)):l} - result is ""
7044                          * (bash compat)
7045                          */
7046                         pos = 0;
7047                         len = 0;
7048                 }
7049                 if (len < 0) {
7050                         /* ${VAR:N:-M} sets LEN to strlen()-M */
7051                         len = (orig_len - pos) + len;
7052                 }
7053                 if ((unsigned)len > (orig_len - pos))
7054                         len = orig_len - pos;
7055
7056                 for (str = startp; pos; str++, pos--) {
7057                         if (quotes && (unsigned char)*str == CTLESC)
7058                                 str++;
7059                 }
7060                 for (loc = startp; len; len--) {
7061                         if (quotes && (unsigned char)*str == CTLESC)
7062                                 *loc++ = *str++;
7063                         *loc++ = *str++;
7064                 }
7065                 *loc = '\0';
7066                 amount = loc - expdest;
7067                 STADJUST(amount, expdest);
7068                 return loc;
7069         }
7070 #endif /* BASH_SUBSTR */
7071         }
7072
7073         resetloc = expdest - (char *)stackblock();
7074
7075 #if BASH_PATTERN_SUBST
7076         repl = NULL;
7077
7078         /* We'll comeback here if we grow the stack while handling
7079          * a VSREPLACE or VSREPLACEALL, since our pointers into the
7080          * stack will need rebasing, and we'll need to remove our work
7081          * areas each time
7082          */
7083  restart:
7084 #endif
7085
7086         amount = expdest - ((char *)stackblock() + resetloc);
7087         STADJUST(-amount, expdest);
7088         startp = (char *)stackblock() + startloc;
7089
7090         rmesc = startp;
7091         rmescend = (char *)stackblock() + strloc;
7092         //bb_error_msg("str7:'%s'", rmescend);
7093         if (quotes) {
7094 //TODO: how to handle slash_pos here if string changes (shortens?)
7095                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
7096                 if (rmesc != startp) {
7097                         rmescend = expdest;
7098                         startp = (char *)stackblock() + startloc;
7099                 }
7100         }
7101         rmescend--;
7102         str = (char *)stackblock() + strloc;
7103         /*
7104          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7105          * The result is a_\_z_c (not a\_\_z_c)!
7106          *
7107          * The search pattern and replace string treat backslashes differently!
7108          * "&slash_pos" causes rmescapes() to work differently on the pattern
7109          * and string.  It's only used on the first call.
7110          */
7111         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7112         rmescapes(str, RMESCAPE_GLOB,
7113                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7114         );
7115
7116 #if BASH_PATTERN_SUBST
7117         workloc = expdest - (char *)stackblock();
7118         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7119                 int len;
7120                 char *idx, *end;
7121
7122                 if (!repl) {
7123                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7124                         repl = nullstr;
7125                         if (slash_pos >= 0) {
7126                                 repl = str + slash_pos;
7127                                 *repl++ = '\0';
7128                         }
7129                 }
7130                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7131
7132                 /* If there's no pattern to match, return the expansion unmolested */
7133                 if (str[0] == '\0')
7134                         return NULL;
7135
7136                 len = 0;
7137                 idx = startp;
7138                 end = str - 1;
7139                 while (idx < end) {
7140  try_to_match:
7141                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7142                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7143                         if (!loc) {
7144                                 /* No match, advance */
7145                                 char *restart_detect = stackblock();
7146  skip_matching:
7147                                 STPUTC(*idx, expdest);
7148                                 if (quotes && (unsigned char)*idx == CTLESC) {
7149                                         idx++;
7150                                         len++;
7151                                         STPUTC(*idx, expdest);
7152                                 }
7153                                 if (stackblock() != restart_detect)
7154                                         goto restart;
7155                                 idx++;
7156                                 len++;
7157                                 rmesc++;
7158                                 /* continue; - prone to quadratic behavior, smarter code: */
7159                                 if (idx >= end)
7160                                         break;
7161                                 if (str[0] == '*') {
7162                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7163                                          * it would never match "ong_string" etc, no point in trying.
7164                                          */
7165                                         goto skip_matching;
7166                                 }
7167                                 goto try_to_match;
7168                         }
7169
7170                         if (subtype == VSREPLACEALL) {
7171                                 while (idx < loc) {
7172                                         if (quotes && (unsigned char)*idx == CTLESC)
7173                                                 idx++;
7174                                         idx++;
7175                                         rmesc++;
7176                                 }
7177                         } else {
7178                                 idx = loc;
7179                         }
7180
7181                         //bb_error_msg("repl:'%s'", repl);
7182                         for (loc = (char*)repl; *loc; loc++) {
7183                                 char *restart_detect = stackblock();
7184                                 if (quotes && *loc == '\\') {
7185                                         STPUTC(CTLESC, expdest);
7186                                         len++;
7187                                 }
7188                                 STPUTC(*loc, expdest);
7189                                 if (stackblock() != restart_detect)
7190                                         goto restart;
7191                                 len++;
7192                         }
7193
7194                         if (subtype == VSREPLACE) {
7195                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7196                                 while (*idx) {
7197                                         char *restart_detect = stackblock();
7198                                         STPUTC(*idx, expdest);
7199                                         if (stackblock() != restart_detect)
7200                                                 goto restart;
7201                                         len++;
7202                                         idx++;
7203                                 }
7204                                 break;
7205                         }
7206                 }
7207
7208                 /* We've put the replaced text into a buffer at workloc, now
7209                  * move it to the right place and adjust the stack.
7210                  */
7211                 STPUTC('\0', expdest);
7212                 startp = (char *)stackblock() + startloc;
7213                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7214                 //bb_error_msg("startp:'%s'", startp);
7215                 amount = expdest - (startp + len);
7216                 STADJUST(-amount, expdest);
7217                 return startp;
7218         }
7219 #endif /* BASH_PATTERN_SUBST */
7220
7221         subtype -= VSTRIMRIGHT;
7222 #if DEBUG
7223         if (subtype < 0 || subtype > 7)
7224                 abort();
7225 #endif
7226         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7227         zero = subtype >> 1;
7228         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7229         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7230
7231         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7232         if (loc) {
7233                 if (zero) {
7234                         memmove(startp, loc, str - loc);
7235                         loc = startp + (str - loc) - 1;
7236                 }
7237                 *loc = '\0';
7238                 amount = loc - expdest;
7239                 STADJUST(amount, expdest);
7240         }
7241         return loc;
7242 }
7243
7244 /*
7245  * Add the value of a specialized variable to the stack string.
7246  * name parameter (examples):
7247  * ash -c 'echo $1'      name:'1='
7248  * ash -c 'echo $qwe'    name:'qwe='
7249  * ash -c 'echo $$'      name:'$='
7250  * ash -c 'echo ${$}'    name:'$='
7251  * ash -c 'echo ${$##q}' name:'$=q'
7252  * ash -c 'echo ${#$}'   name:'$='
7253  * note: examples with bad shell syntax:
7254  * ash -c 'echo ${#$1}'  name:'$=1'
7255  * ash -c 'echo ${#1#}'  name:'1=#'
7256  */
7257 static NOINLINE ssize_t
7258 varvalue(char *name, int varflags, int flags, int quoted)
7259 {
7260         const char *p;
7261         int num;
7262         int i;
7263         ssize_t len = 0;
7264         int sep;
7265         int subtype = varflags & VSTYPE;
7266         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7267         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7268         int syntax;
7269
7270         sep = (flags & EXP_FULL) << CHAR_BIT;
7271         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7272
7273         switch (*name) {
7274         case '$':
7275                 num = rootpid;
7276                 goto numvar;
7277         case '?':
7278                 num = exitstatus;
7279                 goto numvar;
7280         case '#':
7281                 num = shellparam.nparam;
7282                 goto numvar;
7283         case '!':
7284                 num = backgndpid;
7285                 if (num == 0)
7286                         return -1;
7287  numvar:
7288                 len = cvtnum(num);
7289                 goto check_1char_name;
7290         case '-':
7291                 expdest = makestrspace(NOPTS, expdest);
7292                 for (i = NOPTS - 1; i >= 0; i--) {
7293                         if (optlist[i] && optletters(i)) {
7294                                 USTPUTC(optletters(i), expdest);
7295                                 len++;
7296                         }
7297                 }
7298  check_1char_name:
7299 #if 0
7300                 /* handles cases similar to ${#$1} */
7301                 if (name[2] != '\0')
7302                         raise_error_syntax("bad substitution");
7303 #endif
7304                 break;
7305         case '@':
7306                 if (quoted && sep)
7307                         goto param;
7308                 /* fall through */
7309         case '*': {
7310                 char **ap;
7311                 char sepc;
7312                 char c;
7313
7314                 /* We will set c to 0 or ~0 depending on whether
7315                  * we're doing field splitting.  We won't do field
7316                  * splitting if either we're quoted or sep is zero.
7317                  *
7318                  * Instead of testing (quoted || !sep) the following
7319                  * trick optimises away any branches by using the
7320                  * fact that EXP_QUOTED (which is the only bit that
7321                  * can be set in quoted) is the same as EXP_FULL <<
7322                  * CHAR_BIT (which is the only bit that can be set
7323                  * in sep).
7324                  */
7325 #if EXP_QUOTED >> CHAR_BIT != EXP_FULL
7326 #error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
7327 #endif
7328                 c = !((quoted | ~sep) & EXP_QUOTED) - 1;
7329                 sep &= ~quoted;
7330                 sep |= ifsset() ? (unsigned char)(c & ifsval()[0]) : ' ';
7331  param:
7332                 sepc = sep;
7333                 ap = shellparam.p;
7334                 if (!ap)
7335                         return -1;
7336                 while ((p = *ap++) != NULL) {
7337                         len += strtodest(p, syntax, quotes);
7338
7339                         if (*ap && sep) {
7340                                 len++;
7341                                 memtodest(&sepc, 1, syntax, quotes);
7342                         }
7343                 }
7344                 break;
7345         } /* case '*' */
7346         case '0':
7347         case '1':
7348         case '2':
7349         case '3':
7350         case '4':
7351         case '5':
7352         case '6':
7353         case '7':
7354         case '8':
7355         case '9':
7356                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7357                 if (num < 0 || num > shellparam.nparam)
7358                         return -1;
7359                 p = num ? shellparam.p[num - 1] : arg0;
7360                 goto value;
7361         default:
7362                 /* NB: name has form "VAR=..." */
7363                 p = lookupvar(name);
7364  value:
7365                 if (!p)
7366                         return -1;
7367
7368                 len = strtodest(p, syntax, quotes);
7369 #if ENABLE_UNICODE_SUPPORT
7370                 if (subtype == VSLENGTH && len > 0) {
7371                         reinit_unicode_for_ash();
7372                         if (unicode_status == UNICODE_ON) {
7373                                 STADJUST(-len, expdest);
7374                                 discard = 0;
7375                                 len = unicode_strlen(p);
7376                         }
7377                 }
7378 #endif
7379                 break;
7380         }
7381
7382         if (discard)
7383                 STADJUST(-len, expdest);
7384         return len;
7385 }
7386
7387 /*
7388  * Expand a variable, and return a pointer to the next character in the
7389  * input string.
7390  */
7391 static char *
7392 evalvar(char *p, int flag)
7393 {
7394         char varflags;
7395         char subtype;
7396         int quoted;
7397         char *var;
7398         int patloc;
7399         int startloc;
7400         ssize_t varlen;
7401
7402         varflags = (unsigned char) *p++;
7403         subtype = varflags & VSTYPE;
7404
7405         if (!subtype)
7406                 raise_error_syntax("bad substitution");
7407
7408         quoted = flag & EXP_QUOTED;
7409         var = p;
7410         startloc = expdest - (char *)stackblock();
7411         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7412
7413  again:
7414         varlen = varvalue(var, varflags, flag, quoted);
7415         if (varflags & VSNUL)
7416                 varlen--;
7417
7418         if (subtype == VSPLUS) {
7419                 varlen = -1 - varlen;
7420                 goto vsplus;
7421         }
7422
7423         if (subtype == VSMINUS) {
7424  vsplus:
7425                 if (varlen < 0) {
7426                         argstr(
7427                                 p,
7428                                 flag | EXP_TILDE | EXP_WORD
7429                         );
7430                         goto end;
7431                 }
7432                 goto record;
7433         }
7434
7435         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7436                 if (varlen >= 0)
7437                         goto record;
7438
7439                 subevalvar(p, var, 0, subtype, startloc, varflags,
7440                            flag & ~QUOTES_ESC);
7441                 varflags &= ~VSNUL;
7442                 /*
7443                  * Remove any recorded regions beyond
7444                  * start of variable
7445                  */
7446                 removerecordregions(startloc);
7447                 goto again;
7448         }
7449
7450         if (varlen < 0 && uflag)
7451                 varunset(p, var, 0, 0);
7452
7453         if (subtype == VSLENGTH) {
7454                 cvtnum(varlen > 0 ? varlen : 0);
7455                 goto record;
7456         }
7457
7458         if (subtype == VSNORMAL) {
7459  record:
7460                 if (quoted) {
7461                         quoted = *var == '@' && shellparam.nparam;
7462                         if (!quoted)
7463                                 goto end;
7464                 }
7465                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7466                 goto end;
7467         }
7468
7469 #if DEBUG
7470         switch (subtype) {
7471         case VSTRIMLEFT:
7472         case VSTRIMLEFTMAX:
7473         case VSTRIMRIGHT:
7474         case VSTRIMRIGHTMAX:
7475 #if BASH_SUBSTR
7476         case VSSUBSTR:
7477 #endif
7478 #if BASH_PATTERN_SUBST
7479         case VSREPLACE:
7480         case VSREPLACEALL:
7481 #endif
7482                 break;
7483         default:
7484                 abort();
7485         }
7486 #endif
7487
7488         if (varlen >= 0) {
7489                 /*
7490                  * Terminate the string and start recording the pattern
7491                  * right after it
7492                  */
7493                 STPUTC('\0', expdest);
7494                 patloc = expdest - (char *)stackblock();
7495                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7496                                 startloc, varflags, flag)) {
7497                         int amount = expdest - (
7498                                 (char *)stackblock() + patloc - 1
7499                         );
7500                         STADJUST(-amount, expdest);
7501                 }
7502                 /* Remove any recorded regions beyond start of variable */
7503                 removerecordregions(startloc);
7504                 goto record;
7505         }
7506
7507  end:
7508         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7509                 int nesting = 1;
7510                 for (;;) {
7511                         unsigned char c = *p++;
7512                         if (c == CTLESC)
7513                                 p++;
7514                         else if (c == CTLBACKQ) {
7515                                 if (varlen >= 0)
7516                                         argbackq = argbackq->next;
7517                         } else if (c == CTLVAR) {
7518                                 if ((*p++ & VSTYPE) != VSNORMAL)
7519                                         nesting++;
7520                         } else if (c == CTLENDVAR) {
7521                                 if (--nesting == 0)
7522                                         break;
7523                         }
7524                 }
7525         }
7526         return p;
7527 }
7528
7529 /*
7530  * Add a file name to the list.
7531  */
7532 static void
7533 addfname(const char *name)
7534 {
7535         struct strlist *sp;
7536
7537         sp = stzalloc(sizeof(*sp));
7538         sp->text = sstrdup(name);
7539         *exparg.lastp = sp;
7540         exparg.lastp = &sp->next;
7541 }
7542
7543 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7544 static int
7545 hasmeta(const char *p)
7546 {
7547         static const char chars[] ALIGN1 = {
7548                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7549         };
7550
7551         for (;;) {
7552                 p = strpbrk(p, chars);
7553                 if (!p)
7554                         break;
7555                 switch ((unsigned char)*p) {
7556                 case CTLQUOTEMARK:
7557                         for (;;) {
7558                                 p++;
7559                                 if ((unsigned char)*p == CTLQUOTEMARK)
7560                                         break;
7561                                 if ((unsigned char)*p == CTLESC)
7562                                         p++;
7563                                 if (*p == '\0') /* huh? */
7564                                         return 0;
7565                         }
7566                         break;
7567                 case '\\':
7568                 case CTLESC:
7569                         p++;
7570                         if (*p == '\0')
7571                                 return 0;
7572                         break;
7573                 case '[':
7574                         if (!strchr(p + 1, ']')) {
7575                                 /* It's not a properly closed [] pattern,
7576                                  * but other metas may follow. Continue checking.
7577                                  * my[file* _is_ globbed by bash
7578                                  * and matches filenames like "my[file1".
7579                                  */
7580                                 break;
7581                         }
7582                         /* fallthrough */
7583                 default:
7584                 /* case '*': */
7585                 /* case '?': */
7586                         return 1;
7587                 }
7588                 p++;
7589         }
7590
7591         return 0;
7592 }
7593
7594 /* If we want to use glob() from libc... */
7595 #if !ENABLE_ASH_INTERNAL_GLOB
7596
7597 /* Add the result of glob() to the list */
7598 static void
7599 addglob(const glob_t *pglob)
7600 {
7601         char **p = pglob->gl_pathv;
7602
7603         do {
7604                 addfname(*p);
7605         } while (*++p);
7606 }
7607 static void
7608 expandmeta(struct strlist *str /*, int flag*/)
7609 {
7610         /* TODO - EXP_REDIR */
7611
7612         while (str) {
7613                 char *p;
7614                 glob_t pglob;
7615                 int i;
7616
7617                 if (fflag)
7618                         goto nometa;
7619
7620                 if (!hasmeta(str->text))
7621                         goto nometa;
7622
7623                 INT_OFF;
7624                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7625 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7626 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7627 //
7628 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7629 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7630 // Which means you need to unescape the string, right? Not so fast:
7631 // if there _is_ a file named "file\?" (with backslash), it is returned
7632 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7633 // You DON'T KNOW by looking at the result whether you need to unescape it.
7634 //
7635 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7636 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7637 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7638 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7639 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7640 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7641                 i = glob(p, 0, NULL, &pglob);
7642                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7643                 if (p != str->text)
7644                         free(p);
7645                 switch (i) {
7646                 case 0:
7647 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7648                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7649                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7650                                 goto nometa2;
7651 #endif
7652                         addglob(&pglob);
7653                         globfree(&pglob);
7654                         INT_ON;
7655                         break;
7656                 case GLOB_NOMATCH:
7657  //nometa2:
7658                         globfree(&pglob);
7659                         INT_ON;
7660  nometa:
7661                         *exparg.lastp = str;
7662                         rmescapes(str->text, 0, NULL);
7663                         exparg.lastp = &str->next;
7664                         break;
7665                 default:        /* GLOB_NOSPACE */
7666                         globfree(&pglob);
7667                         INT_ON;
7668                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7669                 }
7670                 str = str->next;
7671         }
7672 }
7673
7674 #else
7675 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7676
7677 /*
7678  * Do metacharacter (i.e. *, ?, [...]) expansion.
7679  */
7680 typedef struct exp_t {
7681         char *dir;
7682         unsigned dir_max;
7683 } exp_t;
7684 static void
7685 expmeta(exp_t *exp, char *name, unsigned name_len, unsigned expdir_len)
7686 {
7687 #define expdir exp->dir
7688 #define expdir_max exp->dir_max
7689         char *enddir = expdir + expdir_len;
7690         char *p;
7691         const char *cp;
7692         char *start;
7693         char *endname;
7694         int metaflag;
7695         struct stat statb;
7696         DIR *dirp;
7697         struct dirent *dp;
7698         int atend;
7699         int matchdot;
7700         int esc;
7701
7702         metaflag = 0;
7703         start = name;
7704         for (p = name; esc = 0, *p; p += esc + 1) {
7705                 if (*p == '*' || *p == '?')
7706                         metaflag = 1;
7707                 else if (*p == '[') {
7708                         char *q = p + 1;
7709                         if (*q == '!')
7710                                 q++;
7711                         for (;;) {
7712                                 if (*q == '\\')
7713                                         q++;
7714                                 if (*q == '/' || *q == '\0')
7715                                         break;
7716                                 if (*++q == ']') {
7717                                         metaflag = 1;
7718                                         break;
7719                                 }
7720                         }
7721                 } else {
7722                         if (*p == '\\' && p[1])
7723                                 esc++;
7724                         if (p[esc] == '/') {
7725                                 if (metaflag)
7726                                         break;
7727                                 start = p + esc + 1;
7728                         }
7729                 }
7730         }
7731         if (metaflag == 0) {    /* we've reached the end of the file name */
7732                 if (!expdir_len)
7733                         return;
7734                 p = name;
7735                 do {
7736                         if (*p == '\\' && p[1])
7737                                 p++;
7738                         *enddir++ = *p;
7739                 } while (*p++);
7740                 if (lstat(expdir, &statb) == 0)
7741                         addfname(expdir);
7742                 return;
7743         }
7744         endname = p;
7745         if (name < start) {
7746                 p = name;
7747                 do {
7748                         if (*p == '\\' && p[1])
7749                                 p++;
7750                         *enddir++ = *p++;
7751                 } while (p < start);
7752         }
7753         *enddir = '\0';
7754         cp = expdir;
7755         expdir_len = enddir - cp;
7756         if (!expdir_len)
7757                 cp = ".";
7758         dirp = opendir(cp);
7759         if (dirp == NULL)
7760                 return;
7761         if (*endname == 0) {
7762                 atend = 1;
7763         } else {
7764                 atend = 0;
7765                 *endname = '\0';
7766                 endname += esc + 1;
7767         }
7768         name_len -= endname - name;
7769         matchdot = 0;
7770         p = start;
7771         if (*p == '\\')
7772                 p++;
7773         if (*p == '.')
7774                 matchdot++;
7775         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7776                 if (dp->d_name[0] == '.' && !matchdot)
7777                         continue;
7778                 if (pmatch(start, dp->d_name)) {
7779                         if (atend) {
7780                                 strcpy(enddir, dp->d_name);
7781                                 addfname(expdir);
7782                         } else {
7783                                 unsigned offset;
7784                                 unsigned len;
7785
7786                                 p = stpcpy(enddir, dp->d_name);
7787                                 *p = '/';
7788
7789                                 offset = p - expdir + 1;
7790                                 len = offset + name_len + NAME_MAX;
7791                                 if (len > expdir_max) {
7792                                         len += PATH_MAX;
7793                                         expdir = ckrealloc(expdir, len);
7794                                         expdir_max = len;
7795                                 }
7796
7797                                 expmeta(exp, endname, name_len, offset);
7798                                 enddir = expdir + expdir_len;
7799                         }
7800                 }
7801         }
7802         closedir(dirp);
7803         if (!atend)
7804                 endname[-esc - 1] = esc ? '\\' : '/';
7805 #undef expdir
7806 #undef expdir_max
7807 }
7808
7809 static struct strlist *
7810 msort(struct strlist *list, int len)
7811 {
7812         struct strlist *p, *q = NULL;
7813         struct strlist **lpp;
7814         int half;
7815         int n;
7816
7817         if (len <= 1)
7818                 return list;
7819         half = len >> 1;
7820         p = list;
7821         for (n = half; --n >= 0;) {
7822                 q = p;
7823                 p = p->next;
7824         }
7825         q->next = NULL;                 /* terminate first half of list */
7826         q = msort(list, half);          /* sort first half of list */
7827         p = msort(p, len - half);               /* sort second half */
7828         lpp = &list;
7829         for (;;) {
7830 #if ENABLE_LOCALE_SUPPORT
7831                 if (strcoll(p->text, q->text) < 0)
7832 #else
7833                 if (strcmp(p->text, q->text) < 0)
7834 #endif
7835                                                 {
7836                         *lpp = p;
7837                         lpp = &p->next;
7838                         p = *lpp;
7839                         if (p == NULL) {
7840                                 *lpp = q;
7841                                 break;
7842                         }
7843                 } else {
7844                         *lpp = q;
7845                         lpp = &q->next;
7846                         q = *lpp;
7847                         if (q == NULL) {
7848                                 *lpp = p;
7849                                 break;
7850                         }
7851                 }
7852         }
7853         return list;
7854 }
7855
7856 /*
7857  * Sort the results of file name expansion.  It calculates the number of
7858  * strings to sort and then calls msort (short for merge sort) to do the
7859  * work.
7860  */
7861 static struct strlist *
7862 expsort(struct strlist *str)
7863 {
7864         int len;
7865         struct strlist *sp;
7866
7867         len = 0;
7868         for (sp = str; sp; sp = sp->next)
7869                 len++;
7870         return msort(str, len);
7871 }
7872
7873 static void
7874 expandmeta(struct strlist *str /*, int flag*/)
7875 {
7876         /* TODO - EXP_REDIR */
7877
7878         while (str) {
7879                 exp_t exp;
7880                 struct strlist **savelastp;
7881                 struct strlist *sp;
7882                 char *p;
7883                 unsigned len;
7884
7885                 if (fflag)
7886                         goto nometa;
7887                 if (!hasmeta(str->text))
7888                         goto nometa;
7889                 savelastp = exparg.lastp;
7890
7891                 INT_OFF;
7892                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7893                 len = strlen(p);
7894                 exp.dir_max = len + PATH_MAX;
7895                 exp.dir = ckmalloc(exp.dir_max);
7896
7897                 expmeta(&exp, p, len, 0);
7898                 free(exp.dir);
7899                 if (p != str->text)
7900                         free(p);
7901                 INT_ON;
7902                 if (exparg.lastp == savelastp) {
7903                         /*
7904                          * no matches
7905                          */
7906  nometa:
7907                         *exparg.lastp = str;
7908                         rmescapes(str->text, 0, NULL);
7909                         exparg.lastp = &str->next;
7910                 } else {
7911                         *exparg.lastp = NULL;
7912                         *savelastp = sp = expsort(*savelastp);
7913                         while (sp->next != NULL)
7914                                 sp = sp->next;
7915                         exparg.lastp = &sp->next;
7916                 }
7917                 str = str->next;
7918         }
7919 }
7920 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7921
7922 /*
7923  * Perform variable substitution and command substitution on an argument,
7924  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7925  * perform splitting and file name expansion.  When arglist is NULL, perform
7926  * here document expansion.
7927  */
7928 static void
7929 expandarg(union node *arg, struct arglist *arglist, int flag)
7930 {
7931         struct strlist *sp;
7932         char *p;
7933
7934         argbackq = arg->narg.backquote;
7935         STARTSTACKSTR(expdest);
7936         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7937         argstr(arg->narg.text, flag);
7938         p = _STPUTC('\0', expdest);
7939         expdest = p - 1;
7940         if (arglist == NULL) {
7941                 /* here document expanded */
7942                 goto out;
7943         }
7944         p = grabstackstr(p);
7945         TRACE(("expandarg: p:'%s'\n", p));
7946         exparg.lastp = &exparg.list;
7947         /*
7948          * TODO - EXP_REDIR
7949          */
7950         if (flag & EXP_FULL) {
7951                 ifsbreakup(p, &exparg);
7952                 *exparg.lastp = NULL;
7953                 exparg.lastp = &exparg.list;
7954                 expandmeta(exparg.list /*, flag*/);
7955         } else {
7956                 sp = stzalloc(sizeof(*sp));
7957                 sp->text = p;
7958                 *exparg.lastp = sp;
7959                 exparg.lastp = &sp->next;
7960         }
7961         *exparg.lastp = NULL;
7962         if (exparg.list) {
7963                 *arglist->lastp = exparg.list;
7964                 arglist->lastp = exparg.lastp;
7965         }
7966
7967  out:
7968         ifsfree();
7969 }
7970
7971 /*
7972  * Expand shell variables and backquotes inside a here document.
7973  */
7974 static void
7975 expandhere(union node *arg, int fd)
7976 {
7977         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7978         full_write(fd, stackblock(), expdest - (char *)stackblock());
7979 }
7980
7981 /*
7982  * Returns true if the pattern matches the string.
7983  */
7984 static int
7985 patmatch(char *pattern, const char *string)
7986 {
7987         char *p = preglob(pattern, 0);
7988         int r = pmatch(p, string);
7989         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7990         return r;
7991 }
7992
7993 /*
7994  * See if a pattern matches in a case statement.
7995  */
7996 static int
7997 casematch(union node *pattern, char *val)
7998 {
7999         struct stackmark smark;
8000         int result;
8001
8002         setstackmark(&smark);
8003         argbackq = pattern->narg.backquote;
8004         STARTSTACKSTR(expdest);
8005         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
8006         STACKSTRNUL(expdest);
8007         ifsfree();
8008         result = patmatch(stackblock(), val);
8009         popstackmark(&smark);
8010         return result;
8011 }
8012
8013
8014 /* ============ find_command */
8015
8016 struct builtincmd {
8017         const char *name;
8018         int (*builtin)(int, char **) FAST_FUNC;
8019         /* unsigned flags; */
8020 };
8021 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
8022 /* "regular" builtins always take precedence over commands,
8023  * regardless of PATH=....%builtin... position */
8024 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
8025 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
8026
8027 struct cmdentry {
8028         smallint cmdtype;       /* CMDxxx */
8029         union param {
8030                 int index;
8031                 /* index >= 0 for commands without path (slashes) */
8032                 /* (TODO: what exactly does the value mean? PATH position?) */
8033                 /* index == -1 for commands with slashes */
8034                 /* index == (-2 - applet_no) for NOFORK applets */
8035                 const struct builtincmd *cmd;
8036                 struct funcnode *func;
8037         } u;
8038 };
8039 /* values of cmdtype */
8040 #define CMDUNKNOWN      -1      /* no entry in table for command */
8041 #define CMDNORMAL       0       /* command is an executable program */
8042 #define CMDFUNCTION     1       /* command is a shell function */
8043 #define CMDBUILTIN      2       /* command is a shell builtin */
8044
8045 /* action to find_command() */
8046 #define DO_ERR          0x01    /* prints errors */
8047 #define DO_ABS          0x02    /* checks absolute paths */
8048 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
8049 #define DO_ALTPATH      0x08    /* using alternate path */
8050 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
8051
8052 static void find_command(char *, struct cmdentry *, int, const char *);
8053
8054
8055 /* ============ Hashing commands */
8056
8057 /*
8058  * When commands are first encountered, they are entered in a hash table.
8059  * This ensures that a full path search will not have to be done for them
8060  * on each invocation.
8061  *
8062  * We should investigate converting to a linear search, even though that
8063  * would make the command name "hash" a misnomer.
8064  */
8065
8066 struct tblentry {
8067         struct tblentry *next;  /* next entry in hash chain */
8068         union param param;      /* definition of builtin function */
8069         smallint cmdtype;       /* CMDxxx */
8070         char rehash;            /* if set, cd done since entry created */
8071         char cmdname[1];        /* name of command */
8072 };
8073
8074 static struct tblentry **cmdtable;
8075 #define INIT_G_cmdtable() do { \
8076         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
8077 } while (0)
8078
8079 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
8080
8081
8082 static void
8083 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
8084 {
8085 #if ENABLE_FEATURE_SH_STANDALONE
8086         if (applet_no >= 0) {
8087                 if (APPLET_IS_NOEXEC(applet_no)) {
8088                         clearenv();
8089                         while (*envp)
8090                                 putenv(*envp++);
8091                         popredir(/*drop:*/ 1);
8092                         run_noexec_applet_and_exit(applet_no, cmd, argv);
8093                 }
8094                 /* re-exec ourselves with the new arguments */
8095                 execve(bb_busybox_exec_path, argv, envp);
8096                 /* If they called chroot or otherwise made the binary no longer
8097                  * executable, fall through */
8098         }
8099 #endif
8100
8101  repeat:
8102 #ifdef SYSV
8103         do {
8104                 execve(cmd, argv, envp);
8105         } while (errno == EINTR);
8106 #else
8107         execve(cmd, argv, envp);
8108 #endif
8109
8110         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8111                 /* Run "cmd" as a shell script:
8112                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8113                  * "If the execve() function fails with ENOEXEC, the shell
8114                  * shall execute a command equivalent to having a shell invoked
8115                  * with the command name as its first operand,
8116                  * with any remaining arguments passed to the new shell"
8117                  *
8118                  * That is, do not use $SHELL, user's shell, or /bin/sh;
8119                  * just call ourselves.
8120                  *
8121                  * Note that bash reads ~80 chars of the file, and if it sees
8122                  * a zero byte before it sees newline, it doesn't try to
8123                  * interpret it, but fails with "cannot execute binary file"
8124                  * message and exit code 126. For one, this prevents attempts
8125                  * to interpret foreign ELF binaries as shell scripts.
8126                  */
8127                 argv[0] = (char*) cmd;
8128                 cmd = bb_busybox_exec_path;
8129                 /* NB: this is only possible because all callers of shellexec()
8130                  * ensure that the argv[-1] slot exists!
8131                  */
8132                 argv--;
8133                 argv[0] = (char*) "ash";
8134                 goto repeat;
8135         }
8136 }
8137
8138 /*
8139  * Exec a program.  Never returns.  If you change this routine, you may
8140  * have to change the find_command routine as well.
8141  * argv[-1] must exist and be writable! See tryexec() for why.
8142  */
8143 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8144 static void shellexec(char *prog, char **argv, const char *path, int idx)
8145 {
8146         char *cmdname;
8147         int e;
8148         char **envp;
8149         int exerrno;
8150         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8151
8152         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8153         if (strchr(prog, '/') != NULL
8154 #if ENABLE_FEATURE_SH_STANDALONE
8155          || (applet_no = find_applet_by_name(prog)) >= 0
8156 #endif
8157         ) {
8158                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8159                 if (applet_no >= 0) {
8160                         /* We tried execing ourself, but it didn't work.
8161                          * Maybe /proc/self/exe doesn't exist?
8162                          * Try $PATH search.
8163                          */
8164                         goto try_PATH;
8165                 }
8166                 e = errno;
8167         } else {
8168  try_PATH:
8169                 e = ENOENT;
8170                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8171                         if (--idx < 0 && pathopt == NULL) {
8172                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8173                                 if (errno != ENOENT && errno != ENOTDIR)
8174                                         e = errno;
8175                         }
8176                         stunalloc(cmdname);
8177                 }
8178         }
8179
8180         /* Map to POSIX errors */
8181         switch (e) {
8182         default:
8183                 exerrno = 126;
8184                 break;
8185         case ELOOP:
8186         case ENAMETOOLONG:
8187         case ENOENT:
8188         case ENOTDIR:
8189                 exerrno = 127;
8190                 break;
8191         }
8192         exitstatus = exerrno;
8193         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8194                 prog, e, suppress_int));
8195         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8196         /* NOTREACHED */
8197 }
8198
8199 static void
8200 printentry(struct tblentry *cmdp)
8201 {
8202         int idx;
8203         const char *path;
8204         char *name;
8205
8206         idx = cmdp->param.index;
8207         path = pathval();
8208         do {
8209                 name = path_advance(&path, cmdp->cmdname);
8210                 stunalloc(name);
8211         } while (--idx >= 0);
8212         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8213 }
8214
8215 /*
8216  * Clear out command entries.  The argument specifies the first entry in
8217  * PATH which has changed.
8218  */
8219 static void
8220 clearcmdentry(int firstchange)
8221 {
8222         struct tblentry **tblp;
8223         struct tblentry **pp;
8224         struct tblentry *cmdp;
8225
8226         INT_OFF;
8227         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8228                 pp = tblp;
8229                 while ((cmdp = *pp) != NULL) {
8230                         if ((cmdp->cmdtype == CMDNORMAL &&
8231                              cmdp->param.index >= firstchange)
8232                          || (cmdp->cmdtype == CMDBUILTIN &&
8233                              builtinloc >= firstchange)
8234                         ) {
8235                                 *pp = cmdp->next;
8236                                 free(cmdp);
8237                         } else {
8238                                 pp = &cmdp->next;
8239                         }
8240                 }
8241         }
8242         INT_ON;
8243 }
8244
8245 /*
8246  * Locate a command in the command hash table.  If "add" is nonzero,
8247  * add the command to the table if it is not already present.  The
8248  * variable "lastcmdentry" is set to point to the address of the link
8249  * pointing to the entry, so that delete_cmd_entry can delete the
8250  * entry.
8251  *
8252  * Interrupts must be off if called with add != 0.
8253  */
8254 static struct tblentry **lastcmdentry;
8255
8256 static struct tblentry *
8257 cmdlookup(const char *name, int add)
8258 {
8259         unsigned int hashval;
8260         const char *p;
8261         struct tblentry *cmdp;
8262         struct tblentry **pp;
8263
8264         p = name;
8265         hashval = (unsigned char)*p << 4;
8266         while (*p)
8267                 hashval += (unsigned char)*p++;
8268         hashval &= 0x7FFF;
8269         pp = &cmdtable[hashval % CMDTABLESIZE];
8270         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8271                 if (strcmp(cmdp->cmdname, name) == 0)
8272                         break;
8273                 pp = &cmdp->next;
8274         }
8275         if (add && cmdp == NULL) {
8276                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8277                                 + strlen(name)
8278                                 /* + 1 - already done because
8279                                  * tblentry::cmdname is char[1] */);
8280                 /*cmdp->next = NULL; - ckzalloc did it */
8281                 cmdp->cmdtype = CMDUNKNOWN;
8282                 strcpy(cmdp->cmdname, name);
8283         }
8284         lastcmdentry = pp;
8285         return cmdp;
8286 }
8287
8288 /*
8289  * Delete the command entry returned on the last lookup.
8290  */
8291 static void
8292 delete_cmd_entry(void)
8293 {
8294         struct tblentry *cmdp;
8295
8296         INT_OFF;
8297         cmdp = *lastcmdentry;
8298         *lastcmdentry = cmdp->next;
8299         if (cmdp->cmdtype == CMDFUNCTION)
8300                 freefunc(cmdp->param.func);
8301         free(cmdp);
8302         INT_ON;
8303 }
8304
8305 /*
8306  * Add a new command entry, replacing any existing command entry for
8307  * the same name - except special builtins.
8308  */
8309 static void
8310 addcmdentry(char *name, struct cmdentry *entry)
8311 {
8312         struct tblentry *cmdp;
8313
8314         cmdp = cmdlookup(name, 1);
8315         if (cmdp->cmdtype == CMDFUNCTION) {
8316                 freefunc(cmdp->param.func);
8317         }
8318         cmdp->cmdtype = entry->cmdtype;
8319         cmdp->param = entry->u;
8320         cmdp->rehash = 0;
8321 }
8322
8323 static int FAST_FUNC
8324 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8325 {
8326         struct tblentry **pp;
8327         struct tblentry *cmdp;
8328         int c;
8329         struct cmdentry entry;
8330         char *name;
8331
8332         if (nextopt("r") != '\0') {
8333                 clearcmdentry(0);
8334                 return 0;
8335         }
8336
8337         if (*argptr == NULL) {
8338                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8339                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8340                                 if (cmdp->cmdtype == CMDNORMAL)
8341                                         printentry(cmdp);
8342                         }
8343                 }
8344                 return 0;
8345         }
8346
8347         c = 0;
8348         while ((name = *argptr) != NULL) {
8349                 cmdp = cmdlookup(name, 0);
8350                 if (cmdp != NULL
8351                  && (cmdp->cmdtype == CMDNORMAL
8352                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8353                 ) {
8354                         delete_cmd_entry();
8355                 }
8356                 find_command(name, &entry, DO_ERR, pathval());
8357                 if (entry.cmdtype == CMDUNKNOWN)
8358                         c = 1;
8359                 argptr++;
8360         }
8361         return c;
8362 }
8363
8364 /*
8365  * Called when a cd is done.  Marks all commands so the next time they
8366  * are executed they will be rehashed.
8367  */
8368 static void
8369 hashcd(void)
8370 {
8371         struct tblentry **pp;
8372         struct tblentry *cmdp;
8373
8374         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8375                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8376                         if (cmdp->cmdtype == CMDNORMAL
8377                          || (cmdp->cmdtype == CMDBUILTIN
8378                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8379                              && builtinloc > 0)
8380                         ) {
8381                                 cmdp->rehash = 1;
8382                         }
8383                 }
8384         }
8385 }
8386
8387 /*
8388  * Fix command hash table when PATH changed.
8389  * Called before PATH is changed.  The argument is the new value of PATH;
8390  * pathval() still returns the old value at this point.
8391  * Called with interrupts off.
8392  */
8393 static void FAST_FUNC
8394 changepath(const char *new)
8395 {
8396         const char *old;
8397         int firstchange;
8398         int idx;
8399         int idx_bltin;
8400
8401         old = pathval();
8402         firstchange = 9999;     /* assume no change */
8403         idx = 0;
8404         idx_bltin = -1;
8405         for (;;) {
8406                 if (*old != *new) {
8407                         firstchange = idx;
8408                         if ((*old == '\0' && *new == ':')
8409                          || (*old == ':' && *new == '\0')
8410                         ) {
8411                                 firstchange++;
8412                         }
8413                         old = new;      /* ignore subsequent differences */
8414                 }
8415                 if (*new == '\0')
8416                         break;
8417                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8418                         idx_bltin = idx;
8419                 if (*new == ':')
8420                         idx++;
8421                 new++;
8422                 old++;
8423         }
8424         if (builtinloc < 0 && idx_bltin >= 0)
8425                 builtinloc = idx_bltin;             /* zap builtins */
8426         if (builtinloc >= 0 && idx_bltin < 0)
8427                 firstchange = 0;
8428         clearcmdentry(firstchange);
8429         builtinloc = idx_bltin;
8430 }
8431 enum {
8432         TEOF,
8433         TNL,
8434         TREDIR,
8435         TWORD,
8436         TSEMI,
8437         TBACKGND,
8438         TAND,
8439         TOR,
8440         TPIPE,
8441         TLP,
8442         TRP,
8443         TENDCASE,
8444         TENDBQUOTE,
8445         TNOT,
8446         TCASE,
8447         TDO,
8448         TDONE,
8449         TELIF,
8450         TELSE,
8451         TESAC,
8452         TFI,
8453         TFOR,
8454 #if BASH_FUNCTION
8455         TFUNCTION,
8456 #endif
8457         TIF,
8458         TIN,
8459         TTHEN,
8460         TUNTIL,
8461         TWHILE,
8462         TBEGIN,
8463         TEND
8464 };
8465 typedef smallint token_id_t;
8466
8467 /* Nth bit indicates if token marks the end of a list */
8468 enum {
8469         tokendlist = 0
8470         /*  0 */ | (1u << TEOF)
8471         /*  1 */ | (0u << TNL)
8472         /*  2 */ | (0u << TREDIR)
8473         /*  3 */ | (0u << TWORD)
8474         /*  4 */ | (0u << TSEMI)
8475         /*  5 */ | (0u << TBACKGND)
8476         /*  6 */ | (0u << TAND)
8477         /*  7 */ | (0u << TOR)
8478         /*  8 */ | (0u << TPIPE)
8479         /*  9 */ | (0u << TLP)
8480         /* 10 */ | (1u << TRP)
8481         /* 11 */ | (1u << TENDCASE)
8482         /* 12 */ | (1u << TENDBQUOTE)
8483         /* 13 */ | (0u << TNOT)
8484         /* 14 */ | (0u << TCASE)
8485         /* 15 */ | (1u << TDO)
8486         /* 16 */ | (1u << TDONE)
8487         /* 17 */ | (1u << TELIF)
8488         /* 18 */ | (1u << TELSE)
8489         /* 19 */ | (1u << TESAC)
8490         /* 20 */ | (1u << TFI)
8491         /* 21 */ | (0u << TFOR)
8492 #if BASH_FUNCTION
8493         /* 22 */ | (0u << TFUNCTION)
8494 #endif
8495         /* 23 */ | (0u << TIF)
8496         /* 24 */ | (0u << TIN)
8497         /* 25 */ | (1u << TTHEN)
8498         /* 26 */ | (0u << TUNTIL)
8499         /* 27 */ | (0u << TWHILE)
8500         /* 28 */ | (0u << TBEGIN)
8501         /* 29 */ | (1u << TEND)
8502         , /* thus far 29 bits used */
8503 };
8504
8505 static const char *const tokname_array[] = {
8506         "end of file",
8507         "newline",
8508         "redirection",
8509         "word",
8510         ";",
8511         "&",
8512         "&&",
8513         "||",
8514         "|",
8515         "(",
8516         ")",
8517         ";;",
8518         "`",
8519 #define KWDOFFSET 13
8520         /* the following are keywords */
8521         "!",
8522         "case",
8523         "do",
8524         "done",
8525         "elif",
8526         "else",
8527         "esac",
8528         "fi",
8529         "for",
8530 #if BASH_FUNCTION
8531         "function",
8532 #endif
8533         "if",
8534         "in",
8535         "then",
8536         "until",
8537         "while",
8538         "{",
8539         "}",
8540 };
8541
8542 /* Wrapper around strcmp for qsort/bsearch/... */
8543 static int
8544 pstrcmp(const void *a, const void *b)
8545 {
8546         return strcmp((char*)a, *(char**)b);
8547 }
8548
8549 static const char *const *
8550 findkwd(const char *s)
8551 {
8552         return bsearch(s, tokname_array + KWDOFFSET,
8553                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8554                         sizeof(tokname_array[0]), pstrcmp);
8555 }
8556
8557 /*
8558  * Locate and print what a word is...
8559  */
8560 static int
8561 describe_command(char *command, const char *path, int describe_command_verbose)
8562 {
8563         struct cmdentry entry;
8564 #if ENABLE_ASH_ALIAS
8565         const struct alias *ap;
8566 #endif
8567
8568         path = path ? path : pathval();
8569
8570         if (describe_command_verbose) {
8571                 out1str(command);
8572         }
8573
8574         /* First look at the keywords */
8575         if (findkwd(command)) {
8576                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8577                 goto out;
8578         }
8579
8580 #if ENABLE_ASH_ALIAS
8581         /* Then look at the aliases */
8582         ap = lookupalias(command, 0);
8583         if (ap != NULL) {
8584                 if (!describe_command_verbose) {
8585                         out1str("alias ");
8586                         printalias(ap);
8587                         return 0;
8588                 }
8589                 out1fmt(" is an alias for %s", ap->val);
8590                 goto out;
8591         }
8592 #endif
8593         /* Brute force */
8594         find_command(command, &entry, DO_ABS, path);
8595
8596         switch (entry.cmdtype) {
8597         case CMDNORMAL: {
8598                 int j = entry.u.index;
8599                 char *p;
8600                 if (j < 0) {
8601                         p = command;
8602                 } else {
8603                         do {
8604                                 p = path_advance(&path, command);
8605                                 stunalloc(p);
8606                         } while (--j >= 0);
8607                 }
8608                 if (describe_command_verbose) {
8609                         out1fmt(" is %s", p);
8610                 } else {
8611                         out1str(p);
8612                 }
8613                 break;
8614         }
8615
8616         case CMDFUNCTION:
8617                 if (describe_command_verbose) {
8618                         /*out1str(" is a shell function");*/
8619                         out1str(" is a function"); /* bash says this */
8620                 } else {
8621                         out1str(command);
8622                 }
8623                 break;
8624
8625         case CMDBUILTIN:
8626                 if (describe_command_verbose) {
8627                         out1fmt(" is a %sshell builtin",
8628                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8629                                         "special " : nullstr
8630                         );
8631                 } else {
8632                         out1str(command);
8633                 }
8634                 break;
8635
8636         default:
8637                 if (describe_command_verbose) {
8638                         out1str(": not found\n");
8639                 }
8640                 return 127;
8641         }
8642  out:
8643         out1str("\n");
8644         return 0;
8645 }
8646
8647 static int FAST_FUNC
8648 typecmd(int argc UNUSED_PARAM, char **argv)
8649 {
8650         int i = 1;
8651         int err = 0;
8652         int verbose = 1;
8653
8654         /* type -p ... ? (we don't bother checking for 'p') */
8655         if (argv[1] && argv[1][0] == '-') {
8656                 i++;
8657                 verbose = 0;
8658         }
8659         while (argv[i]) {
8660                 err |= describe_command(argv[i++], NULL, verbose);
8661         }
8662         return err;
8663 }
8664
8665 #if ENABLE_ASH_CMDCMD
8666 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8667 static char **
8668 parse_command_args(char **argv, const char **path)
8669 {
8670         char *cp, c;
8671
8672         for (;;) {
8673                 cp = *++argv;
8674                 if (!cp)
8675                         return NULL;
8676                 if (*cp++ != '-')
8677                         break;
8678                 c = *cp++;
8679                 if (!c)
8680                         break;
8681                 if (c == '-' && !*cp) {
8682                         if (!*++argv)
8683                                 return NULL;
8684                         break;
8685                 }
8686                 do {
8687                         switch (c) {
8688                         case 'p':
8689                                 *path = bb_default_path;
8690                                 break;
8691                         default:
8692                                 /* run 'typecmd' for other options */
8693                                 return NULL;
8694                         }
8695                         c = *cp++;
8696                 } while (c);
8697         }
8698         return argv;
8699 }
8700
8701 static int FAST_FUNC
8702 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8703 {
8704         char *cmd;
8705         int c;
8706         enum {
8707                 VERIFY_BRIEF = 1,
8708                 VERIFY_VERBOSE = 2,
8709         } verify = 0;
8710         const char *path = NULL;
8711
8712         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8713          * never reaches this function.
8714          */
8715
8716         while ((c = nextopt("pvV")) != '\0')
8717                 if (c == 'V')
8718                         verify |= VERIFY_VERBOSE;
8719                 else if (c == 'v')
8720                         /*verify |= VERIFY_BRIEF*/;
8721 #if DEBUG
8722                 else if (c != 'p')
8723                         abort();
8724 #endif
8725                 else
8726                         path = bb_default_path;
8727
8728         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8729         cmd = *argptr;
8730         if (/*verify && */ cmd)
8731                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8732
8733         return 0;
8734 }
8735 #endif
8736
8737
8738 /*static int funcblocksize;     // size of structures in function */
8739 /*static int funcstringsize;    // size of strings in node */
8740 static void *funcblock;         /* block to allocate function from */
8741 static char *funcstring_end;    /* end of block to allocate strings from */
8742
8743 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8744         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8745         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8746         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8747         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8748         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8749         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8750         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8751         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8752         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8753         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8754         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8755         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8756         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8757         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8758         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8759         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8760         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8761 #if BASH_REDIR_OUTPUT
8762         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8763 #endif
8764         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8765         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8766         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8767         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8768         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8769         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8770         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8771         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8772         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8773 };
8774
8775 static int calcsize(int funcblocksize, union node *n);
8776
8777 static int
8778 sizenodelist(int funcblocksize, struct nodelist *lp)
8779 {
8780         while (lp) {
8781                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8782                 funcblocksize = calcsize(funcblocksize, lp->n);
8783                 lp = lp->next;
8784         }
8785         return funcblocksize;
8786 }
8787
8788 static int
8789 calcsize(int funcblocksize, union node *n)
8790 {
8791         if (n == NULL)
8792                 return funcblocksize;
8793         funcblocksize += nodesize[n->type];
8794         switch (n->type) {
8795         case NCMD:
8796                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8797                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8798                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8799                 break;
8800         case NPIPE:
8801                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8802                 break;
8803         case NREDIR:
8804         case NBACKGND:
8805         case NSUBSHELL:
8806                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8807                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8808                 break;
8809         case NAND:
8810         case NOR:
8811         case NSEMI:
8812         case NWHILE:
8813         case NUNTIL:
8814                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8815                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8816                 break;
8817         case NIF:
8818                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8819                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8820                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8821                 break;
8822         case NFOR:
8823                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8824                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8825                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8826                 break;
8827         case NCASE:
8828                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8829                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8830                 break;
8831         case NCLIST:
8832                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8833                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8834                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8835                 break;
8836         case NDEFUN:
8837                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8838                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8839                 break;
8840         case NARG:
8841                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8842                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8843                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8844                 break;
8845         case NTO:
8846 #if BASH_REDIR_OUTPUT
8847         case NTO2:
8848 #endif
8849         case NCLOBBER:
8850         case NFROM:
8851         case NFROMTO:
8852         case NAPPEND:
8853                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8854                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8855                 break;
8856         case NTOFD:
8857         case NFROMFD:
8858                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8859                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8860         break;
8861         case NHERE:
8862         case NXHERE:
8863                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8864                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8865                 break;
8866         case NNOT:
8867                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8868                 break;
8869         };
8870         return funcblocksize;
8871 }
8872
8873 static char *
8874 nodeckstrdup(char *s)
8875 {
8876         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8877         return strcpy(funcstring_end, s);
8878 }
8879
8880 static union node *copynode(union node *);
8881
8882 static struct nodelist *
8883 copynodelist(struct nodelist *lp)
8884 {
8885         struct nodelist *start;
8886         struct nodelist **lpp;
8887
8888         lpp = &start;
8889         while (lp) {
8890                 *lpp = funcblock;
8891                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8892                 (*lpp)->n = copynode(lp->n);
8893                 lp = lp->next;
8894                 lpp = &(*lpp)->next;
8895         }
8896         *lpp = NULL;
8897         return start;
8898 }
8899
8900 static union node *
8901 copynode(union node *n)
8902 {
8903         union node *new;
8904
8905         if (n == NULL)
8906                 return NULL;
8907         new = funcblock;
8908         funcblock = (char *) funcblock + nodesize[n->type];
8909
8910         switch (n->type) {
8911         case NCMD:
8912                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8913                 new->ncmd.args = copynode(n->ncmd.args);
8914                 new->ncmd.assign = copynode(n->ncmd.assign);
8915                 new->ncmd.linno = n->ncmd.linno;
8916                 break;
8917         case NPIPE:
8918                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8919                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8920                 break;
8921         case NREDIR:
8922         case NBACKGND:
8923         case NSUBSHELL:
8924                 new->nredir.redirect = copynode(n->nredir.redirect);
8925                 new->nredir.n = copynode(n->nredir.n);
8926                 new->nredir.linno = n->nredir.linno;
8927                 break;
8928         case NAND:
8929         case NOR:
8930         case NSEMI:
8931         case NWHILE:
8932         case NUNTIL:
8933                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8934                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8935                 break;
8936         case NIF:
8937                 new->nif.elsepart = copynode(n->nif.elsepart);
8938                 new->nif.ifpart = copynode(n->nif.ifpart);
8939                 new->nif.test = copynode(n->nif.test);
8940                 break;
8941         case NFOR:
8942                 new->nfor.var = nodeckstrdup(n->nfor.var);
8943                 new->nfor.body = copynode(n->nfor.body);
8944                 new->nfor.args = copynode(n->nfor.args);
8945                 new->nfor.linno = n->nfor.linno;
8946                 break;
8947         case NCASE:
8948                 new->ncase.cases = copynode(n->ncase.cases);
8949                 new->ncase.expr = copynode(n->ncase.expr);
8950                 new->ncase.linno = n->ncase.linno;
8951                 break;
8952         case NCLIST:
8953                 new->nclist.body = copynode(n->nclist.body);
8954                 new->nclist.pattern = copynode(n->nclist.pattern);
8955                 new->nclist.next = copynode(n->nclist.next);
8956                 break;
8957         case NDEFUN:
8958                 new->ndefun.body = copynode(n->ndefun.body);
8959                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8960                 new->ndefun.linno = n->ndefun.linno;
8961                 break;
8962         case NARG:
8963                 new->narg.backquote = copynodelist(n->narg.backquote);
8964                 new->narg.text = nodeckstrdup(n->narg.text);
8965                 new->narg.next = copynode(n->narg.next);
8966                 break;
8967         case NTO:
8968 #if BASH_REDIR_OUTPUT
8969         case NTO2:
8970 #endif
8971         case NCLOBBER:
8972         case NFROM:
8973         case NFROMTO:
8974         case NAPPEND:
8975                 new->nfile.fname = copynode(n->nfile.fname);
8976                 new->nfile.fd = n->nfile.fd;
8977                 new->nfile.next = copynode(n->nfile.next);
8978                 break;
8979         case NTOFD:
8980         case NFROMFD:
8981                 new->ndup.vname = copynode(n->ndup.vname);
8982                 new->ndup.dupfd = n->ndup.dupfd;
8983                 new->ndup.fd = n->ndup.fd;
8984                 new->ndup.next = copynode(n->ndup.next);
8985                 break;
8986         case NHERE:
8987         case NXHERE:
8988                 new->nhere.doc = copynode(n->nhere.doc);
8989                 new->nhere.fd = n->nhere.fd;
8990                 new->nhere.next = copynode(n->nhere.next);
8991                 break;
8992         case NNOT:
8993                 new->nnot.com = copynode(n->nnot.com);
8994                 break;
8995         };
8996         new->type = n->type;
8997         return new;
8998 }
8999
9000 /*
9001  * Make a copy of a parse tree.
9002  */
9003 static struct funcnode *
9004 copyfunc(union node *n)
9005 {
9006         struct funcnode *f;
9007         size_t blocksize;
9008
9009         /*funcstringsize = 0;*/
9010         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
9011         f = ckzalloc(blocksize /* + funcstringsize */);
9012         funcblock = (char *) f + offsetof(struct funcnode, n);
9013         funcstring_end = (char *) f + blocksize;
9014         copynode(n);
9015         /* f->count = 0; - ckzalloc did it */
9016         return f;
9017 }
9018
9019 /*
9020  * Define a shell function.
9021  */
9022 static void
9023 defun(union node *func)
9024 {
9025         struct cmdentry entry;
9026
9027         INT_OFF;
9028         entry.cmdtype = CMDFUNCTION;
9029         entry.u.func = copyfunc(func);
9030         addcmdentry(func->ndefun.text, &entry);
9031         INT_ON;
9032 }
9033
9034 /* Reasons for skipping commands (see comment on breakcmd routine) */
9035 #define SKIPBREAK      (1 << 0)
9036 #define SKIPCONT       (1 << 1)
9037 #define SKIPFUNC       (1 << 2)
9038 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
9039 static int skipcount;           /* number of levels to skip */
9040 static int loopnest;            /* current loop nesting level */
9041 static int funcline;            /* starting line number of current function, or 0 if not in a function */
9042
9043 /* Forward decl way out to parsing code - dotrap needs it */
9044 static int evalstring(char *s, int flags);
9045
9046 /* Called to execute a trap.
9047  * Single callsite - at the end of evaltree().
9048  * If we return non-zero, evaltree raises EXEXIT exception.
9049  *
9050  * Perhaps we should avoid entering new trap handlers
9051  * while we are executing a trap handler. [is it a TODO?]
9052  */
9053 static void
9054 dotrap(void)
9055 {
9056         uint8_t *g;
9057         int sig;
9058         uint8_t last_status;
9059
9060         if (!pending_sig)
9061                 return;
9062
9063         last_status = exitstatus;
9064         pending_sig = 0;
9065         barrier();
9066
9067         TRACE(("dotrap entered\n"));
9068         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
9069                 char *p;
9070
9071                 if (!*g)
9072                         continue;
9073
9074                 if (evalskip) {
9075                         pending_sig = sig;
9076                         break;
9077                 }
9078
9079                 p = trap[sig];
9080                 /* non-trapped SIGINT is handled separately by raise_interrupt,
9081                  * don't upset it by resetting gotsig[SIGINT-1] */
9082                 if (sig == SIGINT && !p)
9083                         continue;
9084
9085                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
9086                 *g = 0;
9087                 if (!p)
9088                         continue;
9089                 evalstring(p, 0);
9090         }
9091         exitstatus = last_status;
9092         TRACE(("dotrap returns\n"));
9093 }
9094
9095 /* forward declarations - evaluation is fairly recursive business... */
9096 static int evalloop(union node *, int);
9097 static int evalfor(union node *, int);
9098 static int evalcase(union node *, int);
9099 static int evalsubshell(union node *, int);
9100 static void expredir(union node *);
9101 static int evalpipe(union node *, int);
9102 static int evalcommand(union node *, int);
9103 static int evalbltin(const struct builtincmd *, int, char **, int);
9104 static void prehash(union node *);
9105
9106 /*
9107  * Evaluate a parse tree.  The value is left in the global variable
9108  * exitstatus.
9109  */
9110 static int
9111 evaltree(union node *n, int flags)
9112 {
9113         int checkexit = 0;
9114         int (*evalfn)(union node *, int);
9115         struct stackmark smark;
9116         int status = 0;
9117
9118         setstackmark(&smark);
9119
9120         if (n == NULL) {
9121                 TRACE(("evaltree(NULL) called\n"));
9122                 goto out;
9123         }
9124         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
9125
9126         dotrap();
9127
9128         switch (n->type) {
9129         default:
9130 #if DEBUG
9131                 out1fmt("Node type = %d\n", n->type);
9132                 fflush_all();
9133                 break;
9134 #endif
9135         case NNOT:
9136                 status = !evaltree(n->nnot.com, EV_TESTED);
9137                 goto setstatus;
9138         case NREDIR:
9139                 errlinno = lineno = n->nredir.linno;
9140                 if (funcline)
9141                         lineno -= funcline - 1;
9142                 expredir(n->nredir.redirect);
9143                 pushredir(n->nredir.redirect);
9144                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9145                 if (!status) {
9146                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9147                 }
9148                 if (n->nredir.redirect)
9149                         popredir(/*drop:*/ 0);
9150                 goto setstatus;
9151         case NCMD:
9152                 evalfn = evalcommand;
9153  checkexit:
9154                 if (eflag && !(flags & EV_TESTED))
9155                         checkexit = ~0;
9156                 goto calleval;
9157         case NFOR:
9158                 evalfn = evalfor;
9159                 goto calleval;
9160         case NWHILE:
9161         case NUNTIL:
9162                 evalfn = evalloop;
9163                 goto calleval;
9164         case NSUBSHELL:
9165         case NBACKGND:
9166                 evalfn = evalsubshell;
9167                 goto checkexit;
9168         case NPIPE:
9169                 evalfn = evalpipe;
9170                 goto checkexit;
9171         case NCASE:
9172                 evalfn = evalcase;
9173                 goto calleval;
9174         case NAND:
9175         case NOR:
9176         case NSEMI: {
9177
9178 #if NAND + 1 != NOR
9179 #error NAND + 1 != NOR
9180 #endif
9181 #if NOR + 1 != NSEMI
9182 #error NOR + 1 != NSEMI
9183 #endif
9184                 unsigned is_or = n->type - NAND;
9185                 status = evaltree(
9186                         n->nbinary.ch1,
9187                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9188                 );
9189                 if ((!status) == is_or || evalskip)
9190                         break;
9191                 n = n->nbinary.ch2;
9192  evaln:
9193                 evalfn = evaltree;
9194  calleval:
9195                 status = evalfn(n, flags);
9196                 goto setstatus;
9197         }
9198         case NIF:
9199                 status = evaltree(n->nif.test, EV_TESTED);
9200                 if (evalskip)
9201                         break;
9202                 if (!status) {
9203                         n = n->nif.ifpart;
9204                         goto evaln;
9205                 }
9206                 if (n->nif.elsepart) {
9207                         n = n->nif.elsepart;
9208                         goto evaln;
9209                 }
9210                 status = 0;
9211                 goto setstatus;
9212         case NDEFUN:
9213                 defun(n);
9214                 /* Not necessary. To test it:
9215                  * "false; f() { qwerty; }; echo $?" should print 0.
9216                  */
9217                 /* status = 0; */
9218  setstatus:
9219                 exitstatus = status;
9220                 break;
9221         }
9222  out:
9223         /* Order of checks below is important:
9224          * signal handlers trigger before exit caused by "set -e".
9225          */
9226         dotrap();
9227
9228         if (checkexit & status)
9229                 raise_exception(EXEXIT);
9230         if (flags & EV_EXIT)
9231                 raise_exception(EXEXIT);
9232
9233         popstackmark(&smark);
9234         TRACE(("leaving evaltree (no interrupts)\n"));
9235         return exitstatus;
9236 }
9237
9238 static int
9239 skiploop(void)
9240 {
9241         int skip = evalskip;
9242
9243         switch (skip) {
9244         case 0:
9245                 break;
9246         case SKIPBREAK:
9247         case SKIPCONT:
9248                 if (--skipcount <= 0) {
9249                         evalskip = 0;
9250                         break;
9251                 }
9252                 skip = SKIPBREAK;
9253                 break;
9254         }
9255         return skip;
9256 }
9257
9258 static int
9259 evalloop(union node *n, int flags)
9260 {
9261         int skip;
9262         int status;
9263
9264         loopnest++;
9265         status = 0;
9266         flags &= EV_TESTED;
9267         do {
9268                 int i;
9269
9270                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9271                 skip = skiploop();
9272                 if (skip == SKIPFUNC)
9273                         status = i;
9274                 if (skip)
9275                         continue;
9276                 if (n->type != NWHILE)
9277                         i = !i;
9278                 if (i != 0)
9279                         break;
9280                 status = evaltree(n->nbinary.ch2, flags);
9281                 skip = skiploop();
9282         } while (!(skip & ~SKIPCONT));
9283         loopnest--;
9284
9285         return status;
9286 }
9287
9288 static int
9289 evalfor(union node *n, int flags)
9290 {
9291         struct arglist arglist;
9292         union node *argp;
9293         struct strlist *sp;
9294         int status = 0;
9295
9296         errlinno = lineno = n->ncase.linno;
9297         if (funcline)
9298                 lineno -= funcline - 1;
9299
9300         arglist.list = NULL;
9301         arglist.lastp = &arglist.list;
9302         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9303                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9304         }
9305         *arglist.lastp = NULL;
9306
9307         loopnest++;
9308         flags &= EV_TESTED;
9309         for (sp = arglist.list; sp; sp = sp->next) {
9310                 setvar0(n->nfor.var, sp->text);
9311                 status = evaltree(n->nfor.body, flags);
9312                 if (skiploop() & ~SKIPCONT)
9313                         break;
9314         }
9315         loopnest--;
9316
9317         return status;
9318 }
9319
9320 static int
9321 evalcase(union node *n, int flags)
9322 {
9323         union node *cp;
9324         union node *patp;
9325         struct arglist arglist;
9326         int status = 0;
9327
9328         errlinno = lineno = n->ncase.linno;
9329         if (funcline)
9330                 lineno -= funcline - 1;
9331
9332         arglist.list = NULL;
9333         arglist.lastp = &arglist.list;
9334         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9335         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9336                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9337                         if (casematch(patp, arglist.list->text)) {
9338                                 /* Ensure body is non-empty as otherwise
9339                                  * EV_EXIT may prevent us from setting the
9340                                  * exit status.
9341                                  */
9342                                 if (evalskip == 0 && cp->nclist.body) {
9343                                         status = evaltree(cp->nclist.body, flags);
9344                                 }
9345                                 goto out;
9346                         }
9347                 }
9348         }
9349  out:
9350         return status;
9351 }
9352
9353 /*
9354  * Kick off a subshell to evaluate a tree.
9355  */
9356 static int
9357 evalsubshell(union node *n, int flags)
9358 {
9359         struct job *jp;
9360         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9361         int status;
9362
9363         errlinno = lineno = n->nredir.linno;
9364         if (funcline)
9365                 lineno -= funcline - 1;
9366
9367         expredir(n->nredir.redirect);
9368         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9369                 goto nofork;
9370         INT_OFF;
9371         if (backgnd == FORK_FG)
9372                 get_tty_state();
9373         jp = makejob(/*n,*/ 1);
9374         if (forkshell(jp, n, backgnd) == 0) {
9375                 /* child */
9376                 INT_ON;
9377                 flags |= EV_EXIT;
9378                 if (backgnd)
9379                         flags &= ~EV_TESTED;
9380  nofork:
9381                 redirect(n->nredir.redirect, 0);
9382                 evaltreenr(n->nredir.n, flags);
9383                 /* never returns */
9384         }
9385         /* parent */
9386         status = 0;
9387         if (backgnd == FORK_FG)
9388                 status = waitforjob(jp);
9389         INT_ON;
9390         return status;
9391 }
9392
9393 /*
9394  * Compute the names of the files in a redirection list.
9395  */
9396 static void fixredir(union node *, const char *, int);
9397 static void
9398 expredir(union node *n)
9399 {
9400         union node *redir;
9401
9402         for (redir = n; redir; redir = redir->nfile.next) {
9403                 struct arglist fn;
9404
9405                 fn.list = NULL;
9406                 fn.lastp = &fn.list;
9407                 switch (redir->type) {
9408                 case NFROMTO:
9409                 case NFROM:
9410                 case NTO:
9411 #if BASH_REDIR_OUTPUT
9412                 case NTO2:
9413 #endif
9414                 case NCLOBBER:
9415                 case NAPPEND:
9416                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9417                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9418 #if BASH_REDIR_OUTPUT
9419  store_expfname:
9420 #endif
9421 #if 0
9422 // By the design of stack allocator, the loop of this kind:
9423 //      while true; do while true; do break; done </dev/null; done
9424 // will look like a memory leak: ash plans to free expfname's
9425 // of "/dev/null" as soon as it finishes running the loop
9426 // (in this case, never).
9427 // This "fix" is wrong:
9428                         if (redir->nfile.expfname)
9429                                 stunalloc(redir->nfile.expfname);
9430 // It results in corrupted state of stacked allocations.
9431 #endif
9432                         redir->nfile.expfname = fn.list->text;
9433                         break;
9434                 case NFROMFD:
9435                 case NTOFD: /* >& */
9436                         if (redir->ndup.vname) {
9437                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9438                                 if (fn.list == NULL)
9439                                         ash_msg_and_raise_error("redir error");
9440 #if BASH_REDIR_OUTPUT
9441 //FIXME: we used expandarg with different args!
9442                                 if (!isdigit_str9(fn.list->text)) {
9443                                         /* >&file, not >&fd */
9444                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9445                                                 ash_msg_and_raise_error("redir error");
9446                                         redir->type = NTO2;
9447                                         goto store_expfname;
9448                                 }
9449 #endif
9450                                 fixredir(redir, fn.list->text, 1);
9451                         }
9452                         break;
9453                 }
9454         }
9455 }
9456
9457 /*
9458  * Evaluate a pipeline.  All the processes in the pipeline are children
9459  * of the process creating the pipeline.  (This differs from some versions
9460  * of the shell, which make the last process in a pipeline the parent
9461  * of all the rest.)
9462  */
9463 static int
9464 evalpipe(union node *n, int flags)
9465 {
9466         struct job *jp;
9467         struct nodelist *lp;
9468         int pipelen;
9469         int prevfd;
9470         int pip[2];
9471         int status = 0;
9472
9473         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9474         pipelen = 0;
9475         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9476                 pipelen++;
9477         flags |= EV_EXIT;
9478         INT_OFF;
9479         if (n->npipe.pipe_backgnd == 0)
9480                 get_tty_state();
9481         jp = makejob(/*n,*/ pipelen);
9482         prevfd = -1;
9483         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9484                 prehash(lp->n);
9485                 pip[1] = -1;
9486                 if (lp->next) {
9487                         if (pipe(pip) < 0) {
9488                                 close(prevfd);
9489                                 ash_msg_and_raise_perror("can't create pipe");
9490                         }
9491                 }
9492                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9493                         /* child */
9494                         INT_ON;
9495                         if (pip[1] >= 0) {
9496                                 close(pip[0]);
9497                         }
9498                         if (prevfd > 0) {
9499                                 dup2(prevfd, 0);
9500                                 close(prevfd);
9501                         }
9502                         if (pip[1] > 1) {
9503                                 dup2(pip[1], 1);
9504                                 close(pip[1]);
9505                         }
9506                         evaltreenr(lp->n, flags);
9507                         /* never returns */
9508                 }
9509                 /* parent */
9510                 if (prevfd >= 0)
9511                         close(prevfd);
9512                 prevfd = pip[0];
9513                 /* Don't want to trigger debugging */
9514                 if (pip[1] != -1)
9515                         close(pip[1]);
9516         }
9517         if (n->npipe.pipe_backgnd == 0) {
9518                 status = waitforjob(jp);
9519                 TRACE(("evalpipe:  job done exit status %d\n", status));
9520         }
9521         INT_ON;
9522
9523         return status;
9524 }
9525
9526 /* setinteractive needs this forward reference */
9527 #if EDITING_HAS_get_exe_name
9528 static const char *get_builtin_name(int i) FAST_FUNC;
9529 #endif
9530
9531 /*
9532  * Controls whether the shell is interactive or not.
9533  */
9534 static void
9535 setinteractive(int on)
9536 {
9537         static smallint is_interactive;
9538
9539         if (++on == is_interactive)
9540                 return;
9541         is_interactive = on;
9542         setsignal(SIGINT);
9543         setsignal(SIGQUIT);
9544         setsignal(SIGTERM);
9545         if (is_interactive > 1) {
9546 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9547                 /* Looks like they want an interactive shell */
9548                 static smallint did_banner;
9549
9550                 if (!did_banner) {
9551                         /* note: ash and hush share this string */
9552                         out1fmt("\n\n%s %s\n"
9553                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9554                                 "\n",
9555                                 bb_banner,
9556                                 "built-in shell (ash)"
9557                         );
9558                         did_banner = 1;
9559                 }
9560 #endif
9561 #if ENABLE_FEATURE_EDITING
9562                 if (!line_input_state) {
9563                         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
9564 # if EDITING_HAS_get_exe_name
9565                         line_input_state->get_exe_name = get_builtin_name;
9566 # endif
9567                 }
9568 #endif
9569         }
9570 }
9571
9572 static void
9573 optschanged(void)
9574 {
9575 #if DEBUG
9576         opentrace();
9577 #endif
9578         setinteractive(iflag);
9579         setjobctl(mflag);
9580 #if ENABLE_FEATURE_EDITING_VI
9581         if (line_input_state) {
9582                 if (viflag)
9583                         line_input_state->flags |= VI_MODE;
9584                 else
9585                         line_input_state->flags &= ~VI_MODE;
9586         }
9587 #else
9588         viflag = 0; /* forcibly keep the option off */
9589 #endif
9590 }
9591
9592 struct localvar_list {
9593         struct localvar_list *next;
9594         struct localvar *lv;
9595 };
9596
9597 static struct localvar_list *localvar_stack;
9598
9599 /*
9600  * Called after a function returns.
9601  * Interrupts must be off.
9602  */
9603 static void
9604 poplocalvars(int keep)
9605 {
9606         struct localvar_list *ll;
9607         struct localvar *lvp, *next;
9608         struct var *vp;
9609
9610         INT_OFF;
9611         ll = localvar_stack;
9612         localvar_stack = ll->next;
9613
9614         next = ll->lv;
9615         free(ll);
9616
9617         while ((lvp = next) != NULL) {
9618                 next = lvp->next;
9619                 vp = lvp->vp;
9620                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9621                 if (keep) {
9622                         int bits = VSTRFIXED;
9623
9624                         if (lvp->flags != VUNSET) {
9625                                 if (vp->var_text == lvp->text)
9626                                         bits |= VTEXTFIXED;
9627                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9628                                         free((char*)lvp->text);
9629                         }
9630
9631                         vp->flags &= ~bits;
9632                         vp->flags |= (lvp->flags & bits);
9633
9634                         if ((vp->flags &
9635                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9636                                 unsetvar(vp->var_text);
9637                 } else if (vp == NULL) {        /* $- saved */
9638                         memcpy(optlist, lvp->text, sizeof(optlist));
9639                         free((char*)lvp->text);
9640                         optschanged();
9641                 } else if (lvp->flags == VUNSET) {
9642                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9643                         unsetvar(vp->var_text);
9644                 } else {
9645                         if (vp->var_func)
9646                                 vp->var_func(var_end(lvp->text));
9647                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9648                                 free((char*)vp->var_text);
9649                         vp->flags = lvp->flags;
9650                         vp->var_text = lvp->text;
9651                 }
9652                 free(lvp);
9653         }
9654         INT_ON;
9655 }
9656
9657 /*
9658  * Create a new localvar environment.
9659  */
9660 static struct localvar_list *
9661 pushlocalvars(void)
9662 {
9663         struct localvar_list *ll;
9664
9665         INT_OFF;
9666         ll = ckzalloc(sizeof(*ll));
9667         /*ll->lv = NULL; - zalloc did it */
9668         ll->next = localvar_stack;
9669         localvar_stack = ll;
9670         INT_ON;
9671
9672         return ll->next;
9673 }
9674
9675 static void
9676 unwindlocalvars(struct localvar_list *stop)
9677 {
9678         while (localvar_stack != stop)
9679                 poplocalvars(0);
9680 }
9681
9682 static int
9683 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9684 {
9685         volatile struct shparam saveparam;
9686         struct jmploc *volatile savehandler;
9687         struct jmploc jmploc;
9688         int e;
9689         int savefuncline;
9690
9691         saveparam = shellparam;
9692         savefuncline = funcline;
9693         savehandler = exception_handler;
9694         e = setjmp(jmploc.loc);
9695         if (e) {
9696                 goto funcdone;
9697         }
9698         INT_OFF;
9699         exception_handler = &jmploc;
9700         shellparam.malloced = 0;
9701         func->count++;
9702         funcline = func->n.ndefun.linno;
9703         INT_ON;
9704         shellparam.nparam = argc - 1;
9705         shellparam.p = argv + 1;
9706 #if ENABLE_ASH_GETOPTS
9707         shellparam.optind = 1;
9708         shellparam.optoff = -1;
9709 #endif
9710         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9711  funcdone:
9712         INT_OFF;
9713         funcline = savefuncline;
9714         freefunc(func);
9715         freeparam(&shellparam);
9716         shellparam = saveparam;
9717         exception_handler = savehandler;
9718         INT_ON;
9719         evalskip &= ~SKIPFUNC;
9720         return e;
9721 }
9722
9723 /*
9724  * Make a variable a local variable.  When a variable is made local, it's
9725  * value and flags are saved in a localvar structure.  The saved values
9726  * will be restored when the shell function returns.  We handle the name
9727  * "-" as a special case: it makes changes to "set +-options" local
9728  * (options will be restored on return from the function).
9729  */
9730 static void
9731 mklocal(char *name)
9732 {
9733         struct localvar *lvp;
9734         struct var **vpp;
9735         struct var *vp;
9736         char *eq = strchr(name, '=');
9737
9738         INT_OFF;
9739         /* Cater for duplicate "local". Examples:
9740          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9741          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9742          */
9743         lvp = localvar_stack->lv;
9744         while (lvp) {
9745                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9746                         if (eq)
9747                                 setvareq(name, 0);
9748                         /* else:
9749                          * it's a duplicate "local VAR" declaration, do nothing
9750                          */
9751                         goto ret;
9752                 }
9753                 lvp = lvp->next;
9754         }
9755
9756         lvp = ckzalloc(sizeof(*lvp));
9757         if (LONE_DASH(name)) {
9758                 char *p;
9759                 p = ckmalloc(sizeof(optlist));
9760                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9761                 vp = NULL;
9762         } else {
9763                 vpp = hashvar(name);
9764                 vp = *findvar(vpp, name);
9765                 if (vp == NULL) {
9766                         /* variable did not exist yet */
9767                         if (eq)
9768                                 vp = setvareq(name, VSTRFIXED);
9769                         else
9770                                 vp = setvar(name, NULL, VSTRFIXED);
9771                         lvp->flags = VUNSET;
9772                 } else {
9773                         lvp->text = vp->var_text;
9774                         lvp->flags = vp->flags;
9775                         /* make sure neither "struct var" nor string gets freed
9776                          * during (un)setting:
9777                          */
9778                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9779                         if (eq)
9780                                 setvareq(name, 0);
9781                         else
9782                                 /* "local VAR" unsets VAR: */
9783                                 setvar0(name, NULL);
9784                 }
9785         }
9786         lvp->vp = vp;
9787         lvp->next = localvar_stack->lv;
9788         localvar_stack->lv = lvp;
9789  ret:
9790         INT_ON;
9791 }
9792
9793 /*
9794  * The "local" command.
9795  */
9796 static int FAST_FUNC
9797 localcmd(int argc UNUSED_PARAM, char **argv)
9798 {
9799         char *name;
9800
9801         if (!localvar_stack)
9802                 ash_msg_and_raise_error("not in a function");
9803
9804         argv = argptr;
9805         while ((name = *argv++) != NULL) {
9806                 mklocal(name);
9807         }
9808         return 0;
9809 }
9810
9811 static int FAST_FUNC
9812 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9813 {
9814         return 1;
9815 }
9816
9817 static int FAST_FUNC
9818 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9819 {
9820         return 0;
9821 }
9822
9823 static int FAST_FUNC
9824 execcmd(int argc UNUSED_PARAM, char **argv)
9825 {
9826         optionarg = NULL;
9827         while (nextopt("a:") != '\0')
9828                 /* nextopt() sets optionarg to "-a ARGV0" */;
9829
9830         argv = argptr;
9831         if (argv[0]) {
9832                 char *prog;
9833
9834                 iflag = 0;              /* exit on error */
9835                 mflag = 0;
9836                 optschanged();
9837                 /* We should set up signals for "exec CMD"
9838                  * the same way as for "CMD" without "exec".
9839                  * But optschanged->setinteractive->setsignal
9840                  * still thought we are a root shell. Therefore, for example,
9841                  * SIGQUIT is still set to IGN. Fix it:
9842                  */
9843                 shlvl++;
9844                 setsignal(SIGQUIT);
9845                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9846                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9847                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9848
9849                 prog = argv[0];
9850                 if (optionarg)
9851                         argv[0] = optionarg;
9852                 shellexec(prog, argv, pathval(), 0);
9853                 /* NOTREACHED */
9854         }
9855         return 0;
9856 }
9857
9858 /*
9859  * The return command.
9860  */
9861 static int FAST_FUNC
9862 returncmd(int argc UNUSED_PARAM, char **argv)
9863 {
9864         /*
9865          * If called outside a function, do what ksh does;
9866          * skip the rest of the file.
9867          */
9868         evalskip = SKIPFUNC;
9869         return argv[1] ? number(argv[1]) : exitstatus;
9870 }
9871
9872 /* Forward declarations for builtintab[] */
9873 static int breakcmd(int, char **) FAST_FUNC;
9874 static int dotcmd(int, char **) FAST_FUNC;
9875 static int evalcmd(int, char **, int) FAST_FUNC;
9876 static int exitcmd(int, char **) FAST_FUNC;
9877 static int exportcmd(int, char **) FAST_FUNC;
9878 #if ENABLE_ASH_GETOPTS
9879 static int getoptscmd(int, char **) FAST_FUNC;
9880 #endif
9881 #if ENABLE_ASH_HELP
9882 static int helpcmd(int, char **) FAST_FUNC;
9883 #endif
9884 #if MAX_HISTORY
9885 static int historycmd(int, char **) FAST_FUNC;
9886 #endif
9887 #if ENABLE_FEATURE_SH_MATH
9888 static int letcmd(int, char **) FAST_FUNC;
9889 #endif
9890 static int readcmd(int, char **) FAST_FUNC;
9891 static int setcmd(int, char **) FAST_FUNC;
9892 static int shiftcmd(int, char **) FAST_FUNC;
9893 static int timescmd(int, char **) FAST_FUNC;
9894 static int trapcmd(int, char **) FAST_FUNC;
9895 static int umaskcmd(int, char **) FAST_FUNC;
9896 static int unsetcmd(int, char **) FAST_FUNC;
9897 static int ulimitcmd(int, char **) FAST_FUNC;
9898
9899 #define BUILTIN_NOSPEC          "0"
9900 #define BUILTIN_SPECIAL         "1"
9901 #define BUILTIN_REGULAR         "2"
9902 #define BUILTIN_SPEC_REG        "3"
9903 #define BUILTIN_ASSIGN          "4"
9904 #define BUILTIN_SPEC_ASSG       "5"
9905 #define BUILTIN_REG_ASSG        "6"
9906 #define BUILTIN_SPEC_REG_ASSG   "7"
9907
9908 /* Stubs for calling non-FAST_FUNC's */
9909 #if ENABLE_ASH_ECHO
9910 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9911 #endif
9912 #if ENABLE_ASH_PRINTF
9913 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9914 #endif
9915 #if ENABLE_ASH_TEST || BASH_TEST2
9916 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9917 #endif
9918
9919 /* Keep these in proper order since it is searched via bsearch() */
9920 static const struct builtincmd builtintab[] = {
9921         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9922         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9923 #if ENABLE_ASH_TEST
9924         { BUILTIN_REGULAR       "["       , testcmd    },
9925 #endif
9926 #if BASH_TEST2
9927         { BUILTIN_REGULAR       "[["      , testcmd    },
9928 #endif
9929 #if ENABLE_ASH_ALIAS
9930         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9931 #endif
9932 #if JOBS
9933         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9934 #endif
9935         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9936         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9937         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9938 #if ENABLE_ASH_CMDCMD
9939         { BUILTIN_REGULAR       "command" , commandcmd },
9940 #endif
9941         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9942 #if ENABLE_ASH_ECHO
9943         { BUILTIN_REGULAR       "echo"    , echocmd    },
9944 #endif
9945         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9946         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9947         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9948         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9949         { BUILTIN_REGULAR       "false"   , falsecmd   },
9950 #if JOBS
9951         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9952 #endif
9953 #if ENABLE_ASH_GETOPTS
9954         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9955 #endif
9956         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9957 #if ENABLE_ASH_HELP
9958         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9959 #endif
9960 #if MAX_HISTORY
9961         { BUILTIN_NOSPEC        "history" , historycmd },
9962 #endif
9963 #if JOBS
9964         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9965         { BUILTIN_REGULAR       "kill"    , killcmd    },
9966 #endif
9967 #if ENABLE_FEATURE_SH_MATH
9968         { BUILTIN_NOSPEC        "let"     , letcmd     },
9969 #endif
9970         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9971 #if ENABLE_ASH_PRINTF
9972         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9973 #endif
9974         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9975         { BUILTIN_REGULAR       "read"    , readcmd    },
9976         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9977         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9978         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9979         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9980 #if BASH_SOURCE
9981         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9982 #endif
9983 #if ENABLE_ASH_TEST
9984         { BUILTIN_REGULAR       "test"    , testcmd    },
9985 #endif
9986         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9987         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9988         { BUILTIN_REGULAR       "true"    , truecmd    },
9989         { BUILTIN_NOSPEC        "type"    , typecmd    },
9990         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9991         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9992 #if ENABLE_ASH_ALIAS
9993         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9994 #endif
9995         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9996         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9997 };
9998
9999 /* Should match the above table! */
10000 #define COMMANDCMD (builtintab + \
10001         /* . : */       2 + \
10002         /* [ */         1 * ENABLE_ASH_TEST + \
10003         /* [[ */        1 * BASH_TEST2 + \
10004         /* alias */     1 * ENABLE_ASH_ALIAS + \
10005         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
10006         /* break cd cddir  */   3)
10007 #define EVALCMD (COMMANDCMD + \
10008         /* command */   1 * ENABLE_ASH_CMDCMD + \
10009         /* continue */  1 + \
10010         /* echo */      1 * ENABLE_ASH_ECHO + \
10011         0)
10012 #define EXECCMD (EVALCMD + \
10013         /* eval */      1)
10014
10015 /*
10016  * Search the table of builtin commands.
10017  */
10018 static int
10019 pstrcmp1(const void *a, const void *b)
10020 {
10021         return strcmp((char*)a, *(char**)b + 1);
10022 }
10023 static struct builtincmd *
10024 find_builtin(const char *name)
10025 {
10026         struct builtincmd *bp;
10027
10028         bp = bsearch(
10029                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
10030                 pstrcmp1
10031         );
10032         return bp;
10033 }
10034
10035 #if EDITING_HAS_get_exe_name
10036 static const char * FAST_FUNC
10037 get_builtin_name(int i)
10038 {
10039         return /*i >= 0 &&*/ i < ARRAY_SIZE(builtintab) ? builtintab[i].name + 1 : NULL;
10040 }
10041 #endif
10042
10043 /*
10044  * Execute a simple command.
10045  */
10046 static void unwindfiles(struct parsefile *stop);
10047 static int
10048 isassignment(const char *p)
10049 {
10050         const char *q = endofname(p);
10051         if (p == q)
10052                 return 0;
10053         return *q == '=';
10054 }
10055 static int FAST_FUNC
10056 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10057 {
10058         /* Preserve exitstatus of a previous possible redirection
10059          * as POSIX mandates */
10060         return back_exitstatus;
10061 }
10062 static int
10063 evalcommand(union node *cmd, int flags)
10064 {
10065         static const struct builtincmd null_bltin = {
10066                 "\0\0", bltincmd /* why three NULs? */
10067         };
10068         struct localvar_list *localvar_stop;
10069         struct parsefile *file_stop;
10070         struct redirtab *redir_stop;
10071         union node *argp;
10072         struct arglist arglist;
10073         struct arglist varlist;
10074         char **argv;
10075         int argc;
10076         const struct strlist *sp;
10077         struct cmdentry cmdentry;
10078         struct job *jp;
10079         char *lastarg;
10080         const char *path;
10081         int spclbltin;
10082         int status;
10083         char **nargv;
10084         smallint cmd_is_exec;
10085
10086         errlinno = lineno = cmd->ncmd.linno;
10087         if (funcline)
10088                 lineno -= funcline - 1;
10089
10090         /* First expand the arguments. */
10091         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
10092         localvar_stop = pushlocalvars();
10093         file_stop = g_parsefile;
10094         back_exitstatus = 0;
10095
10096         cmdentry.cmdtype = CMDBUILTIN;
10097         cmdentry.u.cmd = &null_bltin;
10098         varlist.lastp = &varlist.list;
10099         *varlist.lastp = NULL;
10100         arglist.lastp = &arglist.list;
10101         *arglist.lastp = NULL;
10102
10103         argc = 0;
10104         if (cmd->ncmd.args) {
10105                 struct builtincmd *bcmd;
10106                 smallint pseudovarflag;
10107
10108                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
10109                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
10110
10111                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
10112                         struct strlist **spp;
10113
10114                         spp = arglist.lastp;
10115                         if (pseudovarflag && isassignment(argp->narg.text))
10116                                 expandarg(argp, &arglist, EXP_VARTILDE);
10117                         else
10118                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
10119
10120                         for (sp = *spp; sp; sp = sp->next)
10121                                 argc++;
10122                 }
10123         }
10124
10125         /* Reserve one extra spot at the front for shellexec. */
10126         nargv = stalloc(sizeof(char *) * (argc + 2));
10127         argv = ++nargv;
10128         for (sp = arglist.list; sp; sp = sp->next) {
10129                 TRACE(("evalcommand arg: %s\n", sp->text));
10130                 *nargv++ = sp->text;
10131         }
10132         *nargv = NULL;
10133
10134         lastarg = NULL;
10135         if (iflag && funcline == 0 && argc > 0)
10136                 lastarg = nargv[-1];
10137
10138         expredir(cmd->ncmd.redirect);
10139         redir_stop = pushredir(cmd->ncmd.redirect);
10140         preverrout_fd = 2;
10141         if (BASH_XTRACEFD && xflag) {
10142                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10143                  * we do not emulate this. We only use its value.
10144                  */
10145                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
10146                 if (xtracefd && is_number(xtracefd))
10147                         preverrout_fd = atoi(xtracefd);
10148
10149         }
10150         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10151
10152         path = vpath.var_text;
10153         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10154                 struct strlist **spp;
10155                 char *p;
10156
10157                 spp = varlist.lastp;
10158                 expandarg(argp, &varlist, EXP_VARTILDE);
10159
10160                 mklocal((*spp)->text);
10161
10162                 /*
10163                  * Modify the command lookup path, if a PATH= assignment
10164                  * is present
10165                  */
10166                 p = (*spp)->text;
10167                 if (varcmp(p, path) == 0)
10168                         path = p;
10169         }
10170
10171         /* Print the command if xflag is set. */
10172         if (xflag) {
10173                 const char *pfx = "";
10174
10175                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10176
10177                 sp = varlist.list;
10178                 while (sp) {
10179                         char *varval = sp->text;
10180                         char *eq = strchrnul(varval, '=');
10181                         if (*eq)
10182                                 eq++;
10183                         fdprintf(preverrout_fd, "%s%.*s%s",
10184                                 pfx,
10185                                 (int)(eq - varval), varval,
10186                                 maybe_single_quote(eq)
10187                         );
10188                         sp = sp->next;
10189                         pfx = " ";
10190                 }
10191
10192                 sp = arglist.list;
10193                 while (sp) {
10194                         fdprintf(preverrout_fd, "%s%s",
10195                                 pfx,
10196                                 /* always quote if matches reserved word: */
10197                                 findkwd(sp->text)
10198                                 ? single_quote(sp->text)
10199                                 : maybe_single_quote(sp->text)
10200                         );
10201                         sp = sp->next;
10202                         pfx = " ";
10203                 }
10204                 safe_write(preverrout_fd, "\n", 1);
10205         }
10206
10207         cmd_is_exec = 0;
10208         spclbltin = -1;
10209
10210         /* Now locate the command. */
10211         if (argc) {
10212                 int cmd_flag = DO_ERR;
10213 #if ENABLE_ASH_CMDCMD
10214                 const char *oldpath = path + 5;
10215 #endif
10216                 path += 5;
10217                 for (;;) {
10218                         find_command(argv[0], &cmdentry, cmd_flag, path);
10219                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10220                                 flush_stdout_stderr();
10221                                 status = 127;
10222                                 goto bail;
10223                         }
10224
10225                         /* implement bltin and command here */
10226                         if (cmdentry.cmdtype != CMDBUILTIN)
10227                                 break;
10228                         if (spclbltin < 0)
10229                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10230                         if (cmdentry.u.cmd == EXECCMD)
10231                                 cmd_is_exec = 1;
10232 #if ENABLE_ASH_CMDCMD
10233                         if (cmdentry.u.cmd == COMMANDCMD) {
10234                                 path = oldpath;
10235                                 nargv = parse_command_args(argv, &path);
10236                                 if (!nargv)
10237                                         break;
10238                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10239                                  * nargv => "PROG". path is updated if -p.
10240                                  */
10241                                 argc -= nargv - argv;
10242                                 argv = nargv;
10243                                 cmd_flag |= DO_NOFUNC;
10244                         } else
10245 #endif
10246                                 break;
10247                 }
10248         }
10249
10250         if (status) {
10251  bail:
10252                 exitstatus = status;
10253
10254                 /* We have a redirection error. */
10255                 if (spclbltin > 0)
10256                         raise_exception(EXERROR);
10257
10258                 goto out;
10259         }
10260
10261         /* Execute the command. */
10262         switch (cmdentry.cmdtype) {
10263         default: {
10264
10265 #if ENABLE_FEATURE_SH_STANDALONE \
10266  && ENABLE_FEATURE_SH_NOFORK \
10267  && NUM_APPLETS > 1
10268 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10269  *     around run_nofork_applet() call.
10270  * (2) Should this check also be done in forkshell()?
10271  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10272  */
10273                 /* find_command() encodes applet_no as (-2 - applet_no) */
10274                 int applet_no = (- cmdentry.u.index - 2);
10275                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10276                         char **sv_environ;
10277
10278                         INT_OFF;
10279                         sv_environ = environ;
10280                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10281                         /*
10282                          * Run <applet>_main().
10283                          * Signals (^C) can't interrupt here.
10284                          * Otherwise we can mangle stdio or malloc internal state.
10285                          * This makes applets which can run for a long time
10286                          * and/or wait for user input ineligible for NOFORK:
10287                          * for example, "yes" or "rm" (rm -i waits for input).
10288                          */
10289                         status = run_nofork_applet(applet_no, argv);
10290                         environ = sv_environ;
10291                         /*
10292                          * Try enabling NOFORK for "yes" applet.
10293                          * ^C _will_ stop it (write returns EINTR),
10294                          * but this causes stdout FILE to be stuck
10295                          * and needing clearerr(). What if other applets
10296                          * also can get EINTRs? Do we need to switch
10297                          * our signals to SA_RESTART?
10298                          */
10299                         /*clearerr(stdout);*/
10300                         INT_ON;
10301                         break;
10302                 }
10303 #endif
10304                 /* Can we avoid forking? For example, very last command
10305                  * in a script or a subshell does not need forking,
10306                  * we can just exec it.
10307                  */
10308                 if (!(flags & EV_EXIT) || may_have_traps) {
10309                         /* No, forking off a child is necessary */
10310                         INT_OFF;
10311                         get_tty_state();
10312                         jp = makejob(/*cmd,*/ 1);
10313                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10314                                 /* parent */
10315                                 status = waitforjob(jp);
10316                                 INT_ON;
10317                                 TRACE(("forked child exited with %d\n", status));
10318                                 break;
10319                         }
10320                         /* child */
10321                         FORCE_INT_ON;
10322                         /* fall through to exec'ing external program */
10323                 }
10324                 listsetvar(varlist.list, VEXPORT|VSTACK);
10325                 shellexec(argv[0], argv, path, cmdentry.u.index);
10326                 /* NOTREACHED */
10327         } /* default */
10328         case CMDBUILTIN:
10329                 if (spclbltin > 0 || argc == 0) {
10330                         poplocalvars(1);
10331                         if (cmd_is_exec && argc > 1)
10332                                 listsetvar(varlist.list, VEXPORT);
10333                 }
10334
10335                 /* Tight loop with builtins only:
10336                  * "while kill -0 $child; do true; done"
10337                  * will never exit even if $child died, unless we do this
10338                  * to reap the zombie and make kill detect that it's gone: */
10339                 dowait(DOWAIT_NONBLOCK, NULL);
10340
10341                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10342                         if (exception_type == EXERROR && spclbltin <= 0) {
10343                                 FORCE_INT_ON;
10344                                 goto readstatus;
10345                         }
10346  raise:
10347                         longjmp(exception_handler->loc, 1);
10348                 }
10349                 goto readstatus;
10350
10351         case CMDFUNCTION:
10352                 /* See above for the rationale */
10353                 dowait(DOWAIT_NONBLOCK, NULL);
10354                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10355                         goto raise;
10356  readstatus:
10357                 status = exitstatus;
10358                 break;
10359         } /* switch */
10360
10361  out:
10362         if (cmd->ncmd.redirect)
10363                 popredir(/*drop:*/ cmd_is_exec);
10364         unwindredir(redir_stop);
10365         unwindfiles(file_stop);
10366         unwindlocalvars(localvar_stop);
10367         if (lastarg) {
10368                 /* dsl: I think this is intended to be used to support
10369                  * '_' in 'vi' command mode during line editing...
10370                  * However I implemented that within libedit itself.
10371                  */
10372                 setvar0("_", lastarg);
10373         }
10374
10375         return status;
10376 }
10377
10378 static int
10379 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10380 {
10381         char *volatile savecmdname;
10382         struct jmploc *volatile savehandler;
10383         struct jmploc jmploc;
10384         int status;
10385         int i;
10386
10387         savecmdname = commandname;
10388         savehandler = exception_handler;
10389         i = setjmp(jmploc.loc);
10390         if (i)
10391                 goto cmddone;
10392         exception_handler = &jmploc;
10393         commandname = argv[0];
10394         argptr = argv + 1;
10395         optptr = NULL;                  /* initialize nextopt */
10396         if (cmd == EVALCMD)
10397                 status = evalcmd(argc, argv, flags);
10398         else
10399                 status = (*cmd->builtin)(argc, argv);
10400         flush_stdout_stderr();
10401         status |= ferror(stdout);
10402         exitstatus = status;
10403  cmddone:
10404         clearerr(stdout);
10405         commandname = savecmdname;
10406         exception_handler = savehandler;
10407
10408         return i;
10409 }
10410
10411 static int
10412 goodname(const char *p)
10413 {
10414         return endofname(p)[0] == '\0';
10415 }
10416
10417
10418 /*
10419  * Search for a command.  This is called before we fork so that the
10420  * location of the command will be available in the parent as well as
10421  * the child.  The check for "goodname" is an overly conservative
10422  * check that the name will not be subject to expansion.
10423  */
10424 static void
10425 prehash(union node *n)
10426 {
10427         struct cmdentry entry;
10428
10429         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10430                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10431 }
10432
10433
10434 /* ============ Builtin commands
10435  *
10436  * Builtin commands whose functions are closely tied to evaluation
10437  * are implemented here.
10438  */
10439
10440 /*
10441  * Handle break and continue commands.  Break, continue, and return are
10442  * all handled by setting the evalskip flag.  The evaluation routines
10443  * above all check this flag, and if it is set they start skipping
10444  * commands rather than executing them.  The variable skipcount is
10445  * the number of loops to break/continue, or the number of function
10446  * levels to return.  (The latter is always 1.)  It should probably
10447  * be an error to break out of more loops than exist, but it isn't
10448  * in the standard shell so we don't make it one here.
10449  */
10450 static int FAST_FUNC
10451 breakcmd(int argc UNUSED_PARAM, char **argv)
10452 {
10453         int n = argv[1] ? number(argv[1]) : 1;
10454
10455         if (n <= 0)
10456                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10457         if (n > loopnest)
10458                 n = loopnest;
10459         if (n > 0) {
10460                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10461                 skipcount = n;
10462         }
10463         return 0;
10464 }
10465
10466
10467 /*
10468  * This implements the input routines used by the parser.
10469  */
10470
10471 enum {
10472         INPUT_PUSH_FILE = 1,
10473         INPUT_NOFILE_OK = 2,
10474 };
10475
10476 static smallint checkkwd;
10477 /* values of checkkwd variable */
10478 #define CHKALIAS        0x1
10479 #define CHKKWD          0x2
10480 #define CHKNL           0x4
10481 #define CHKEOFMARK      0x8
10482
10483 /*
10484  * Push a string back onto the input at this current parsefile level.
10485  * We handle aliases this way.
10486  */
10487 #if !ENABLE_ASH_ALIAS
10488 #define pushstring(s, ap) pushstring(s)
10489 #endif
10490 static void
10491 pushstring(char *s, struct alias *ap)
10492 {
10493         struct strpush *sp;
10494         int len;
10495
10496         len = strlen(s);
10497         INT_OFF;
10498         if (g_parsefile->strpush) {
10499                 sp = ckzalloc(sizeof(*sp));
10500                 sp->prev = g_parsefile->strpush;
10501         } else {
10502                 sp = &(g_parsefile->basestrpush);
10503         }
10504         g_parsefile->strpush = sp;
10505         sp->prev_string = g_parsefile->next_to_pgetc;
10506         sp->prev_left_in_line = g_parsefile->left_in_line;
10507         sp->unget = g_parsefile->unget;
10508         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10509 #if ENABLE_ASH_ALIAS
10510         sp->ap = ap;
10511         if (ap) {
10512                 ap->flag |= ALIASINUSE;
10513                 sp->string = s;
10514         }
10515 #endif
10516         g_parsefile->next_to_pgetc = s;
10517         g_parsefile->left_in_line = len;
10518         g_parsefile->unget = 0;
10519         INT_ON;
10520 }
10521
10522 static void
10523 popstring(void)
10524 {
10525         struct strpush *sp = g_parsefile->strpush;
10526
10527         INT_OFF;
10528 #if ENABLE_ASH_ALIAS
10529         if (sp->ap) {
10530                 if (g_parsefile->next_to_pgetc[-1] == ' '
10531                  || g_parsefile->next_to_pgetc[-1] == '\t'
10532                 ) {
10533                         checkkwd |= CHKALIAS;
10534                 }
10535                 if (sp->string != sp->ap->val) {
10536                         free(sp->string);
10537                 }
10538                 sp->ap->flag &= ~ALIASINUSE;
10539                 if (sp->ap->flag & ALIASDEAD) {
10540                         unalias(sp->ap->name);
10541                 }
10542         }
10543 #endif
10544         g_parsefile->next_to_pgetc = sp->prev_string;
10545         g_parsefile->left_in_line = sp->prev_left_in_line;
10546         g_parsefile->unget = sp->unget;
10547         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10548         g_parsefile->strpush = sp->prev;
10549         if (sp != &(g_parsefile->basestrpush))
10550                 free(sp);
10551         INT_ON;
10552 }
10553
10554 static int
10555 preadfd(void)
10556 {
10557         int nr;
10558         char *buf = g_parsefile->buf;
10559
10560         g_parsefile->next_to_pgetc = buf;
10561 #if ENABLE_FEATURE_EDITING
10562  retry:
10563         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10564                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10565         else {
10566 # if ENABLE_ASH_IDLE_TIMEOUT
10567                 int timeout = -1;
10568                 const char *tmout_var = lookupvar("TMOUT");
10569                 if (tmout_var) {
10570                         timeout = atoi(tmout_var) * 1000;
10571                         if (timeout <= 0)
10572                                 timeout = -1;
10573                 }
10574                 line_input_state->timeout = timeout;
10575 # endif
10576 # if ENABLE_FEATURE_TAB_COMPLETION
10577                 line_input_state->path_lookup = pathval();
10578 # endif
10579                 reinit_unicode_for_ash();
10580                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10581                 if (nr == 0) {
10582                         /* ^C pressed, "convert" to SIGINT */
10583                         write(STDOUT_FILENO, "^C", 2);
10584                         if (trap[SIGINT]) {
10585                                 buf[0] = '\n';
10586                                 buf[1] = '\0';
10587                                 raise(SIGINT);
10588                                 return 1;
10589                         }
10590                         exitstatus = 128 + SIGINT;
10591                         bb_putchar('\n');
10592                         goto retry;
10593                 }
10594                 if (nr < 0) {
10595                         if (errno == 0) {
10596                                 /* Ctrl+D pressed */
10597                                 nr = 0;
10598                         }
10599 # if ENABLE_ASH_IDLE_TIMEOUT
10600                         else if (errno == EAGAIN && timeout > 0) {
10601                                 puts("\007timed out waiting for input: auto-logout");
10602                                 exitshell();
10603                         }
10604 # endif
10605                 }
10606         }
10607 #else
10608         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10609 #endif
10610
10611 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10612         if (nr < 0) {
10613                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10614                         int flags = fcntl(0, F_GETFL);
10615                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10616                                 flags &= ~O_NONBLOCK;
10617                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10618                                         out2str("sh: turning off NDELAY mode\n");
10619                                         goto retry;
10620                                 }
10621                         }
10622                 }
10623         }
10624 #endif
10625         return nr;
10626 }
10627
10628 /*
10629  * Refill the input buffer and return the next input character:
10630  *
10631  * 1) If a string was pushed back on the input, pop it;
10632  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10633  *    or we are reading from a string so we can't refill the buffer,
10634  *    return EOF.
10635  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10636  * 4) Process input up to the next newline, deleting nul characters.
10637  */
10638 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10639 #define pgetc_debug(...) ((void)0)
10640 static int pgetc(void);
10641 static int
10642 preadbuffer(void)
10643 {
10644         char *q;
10645         int more;
10646
10647         if (g_parsefile->strpush) {
10648 #if ENABLE_ASH_ALIAS
10649                 if (g_parsefile->left_in_line == -1
10650                  && g_parsefile->strpush->ap
10651                  && g_parsefile->next_to_pgetc[-1] != ' '
10652                  && g_parsefile->next_to_pgetc[-1] != '\t'
10653                 ) {
10654                         pgetc_debug("preadbuffer PEOA");
10655                         return PEOA;
10656                 }
10657 #endif
10658                 popstring();
10659                 return pgetc();
10660         }
10661         /* on both branches above g_parsefile->left_in_line < 0.
10662          * "pgetc" needs refilling.
10663          */
10664
10665         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10666          * pungetc() may increment it a few times.
10667          * Assuming it won't increment it to less than -90.
10668          */
10669         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10670                 pgetc_debug("preadbuffer PEOF1");
10671                 /* even in failure keep left_in_line and next_to_pgetc
10672                  * in lock step, for correct multi-layer pungetc.
10673                  * left_in_line was decremented before preadbuffer(),
10674                  * must inc next_to_pgetc: */
10675                 g_parsefile->next_to_pgetc++;
10676                 return PEOF;
10677         }
10678
10679         more = g_parsefile->left_in_buffer;
10680         if (more <= 0) {
10681                 flush_stdout_stderr();
10682  again:
10683                 more = preadfd();
10684                 if (more <= 0) {
10685                         /* don't try reading again */
10686                         g_parsefile->left_in_line = -99;
10687                         pgetc_debug("preadbuffer PEOF2");
10688                         g_parsefile->next_to_pgetc++;
10689                         return PEOF;
10690                 }
10691         }
10692
10693         /* Find out where's the end of line.
10694          * Set g_parsefile->left_in_line
10695          * and g_parsefile->left_in_buffer acordingly.
10696          * NUL chars are deleted.
10697          */
10698         q = g_parsefile->next_to_pgetc;
10699         for (;;) {
10700                 char c;
10701
10702                 more--;
10703
10704                 c = *q;
10705                 if (c == '\0') {
10706                         memmove(q, q + 1, more);
10707                 } else {
10708                         q++;
10709                         if (c == '\n') {
10710                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10711                                 break;
10712                         }
10713                 }
10714
10715                 if (more <= 0) {
10716                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10717                         if (g_parsefile->left_in_line < 0)
10718                                 goto again;
10719                         break;
10720                 }
10721         }
10722         g_parsefile->left_in_buffer = more;
10723
10724         if (vflag) {
10725                 char save = *q;
10726                 *q = '\0';
10727                 out2str(g_parsefile->next_to_pgetc);
10728                 *q = save;
10729         }
10730
10731         pgetc_debug("preadbuffer at %d:%p'%s'",
10732                         g_parsefile->left_in_line,
10733                         g_parsefile->next_to_pgetc,
10734                         g_parsefile->next_to_pgetc);
10735         return (unsigned char)*g_parsefile->next_to_pgetc++;
10736 }
10737
10738 static void
10739 nlprompt(void)
10740 {
10741         g_parsefile->linno++;
10742         setprompt_if(doprompt, 2);
10743 }
10744 static void
10745 nlnoprompt(void)
10746 {
10747         g_parsefile->linno++;
10748         needprompt = doprompt;
10749 }
10750
10751 static int
10752 pgetc(void)
10753 {
10754         int c;
10755
10756         pgetc_debug("pgetc at %d:%p'%s'",
10757                         g_parsefile->left_in_line,
10758                         g_parsefile->next_to_pgetc,
10759                         g_parsefile->next_to_pgetc);
10760         if (g_parsefile->unget)
10761                 return g_parsefile->lastc[--g_parsefile->unget];
10762
10763         if (--g_parsefile->left_in_line >= 0)
10764                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10765         else
10766                 c = preadbuffer();
10767
10768         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10769         g_parsefile->lastc[0] = c;
10770
10771         return c;
10772 }
10773
10774 #if ENABLE_ASH_ALIAS
10775 static int
10776 pgetc_without_PEOA(void)
10777 {
10778         int c;
10779         do {
10780                 pgetc_debug("pgetc at %d:%p'%s'",
10781                                 g_parsefile->left_in_line,
10782                                 g_parsefile->next_to_pgetc,
10783                                 g_parsefile->next_to_pgetc);
10784                 c = pgetc();
10785         } while (c == PEOA);
10786         return c;
10787 }
10788 #else
10789 # define pgetc_without_PEOA() pgetc()
10790 #endif
10791
10792 /*
10793  * Undo a call to pgetc.  Only two characters may be pushed back.
10794  * PEOF may be pushed back.
10795  */
10796 static void
10797 pungetc(void)
10798 {
10799         g_parsefile->unget++;
10800 }
10801
10802 /* This one eats backslash+newline */
10803 static int
10804 pgetc_eatbnl(void)
10805 {
10806         int c;
10807
10808         while ((c = pgetc()) == '\\') {
10809                 if (pgetc() != '\n') {
10810                         pungetc();
10811                         break;
10812                 }
10813
10814                 nlprompt();
10815         }
10816
10817         return c;
10818 }
10819
10820 struct synstack {
10821         smalluint syntax;
10822         uint8_t innerdq   :1;
10823         uint8_t varpushed :1;
10824         uint8_t dblquote  :1;
10825         int varnest;            /* levels of variables expansion */
10826         int dqvarnest;          /* levels of variables expansion within double quotes */
10827         int parenlevel;         /* levels of parens in arithmetic */
10828         struct synstack *prev;
10829         struct synstack *next;
10830 };
10831
10832 static void
10833 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10834 {
10835         memset(next, 0, sizeof(*next));
10836         next->syntax = syntax;
10837         next->next = *stack;
10838         (*stack)->prev = next;
10839         *stack = next;
10840 }
10841
10842 static ALWAYS_INLINE void
10843 synstack_pop(struct synstack **stack)
10844 {
10845         *stack = (*stack)->next;
10846 }
10847
10848 /*
10849  * To handle the "." command, a stack of input files is used.  Pushfile
10850  * adds a new entry to the stack and popfile restores the previous level.
10851  */
10852 static void
10853 pushfile(void)
10854 {
10855         struct parsefile *pf;
10856
10857         pf = ckzalloc(sizeof(*pf));
10858         pf->prev = g_parsefile;
10859         pf->pf_fd = -1;
10860         /*pf->strpush = NULL; - ckzalloc did it */
10861         /*pf->basestrpush.prev = NULL;*/
10862         /*pf->unget = 0;*/
10863         g_parsefile = pf;
10864 }
10865
10866 static void
10867 popfile(void)
10868 {
10869         struct parsefile *pf = g_parsefile;
10870
10871         if (pf == &basepf)
10872                 return;
10873
10874         INT_OFF;
10875         if (pf->pf_fd >= 0)
10876                 close(pf->pf_fd);
10877         free(pf->buf);
10878         while (pf->strpush)
10879                 popstring();
10880         g_parsefile = pf->prev;
10881         free(pf);
10882         INT_ON;
10883 }
10884
10885 static void
10886 unwindfiles(struct parsefile *stop)
10887 {
10888         while (g_parsefile != stop)
10889                 popfile();
10890 }
10891
10892 /*
10893  * Return to top level.
10894  */
10895 static void
10896 popallfiles(void)
10897 {
10898         unwindfiles(&basepf);
10899 }
10900
10901 /*
10902  * Close the file(s) that the shell is reading commands from.  Called
10903  * after a fork is done.
10904  */
10905 static void
10906 closescript(void)
10907 {
10908         popallfiles();
10909         if (g_parsefile->pf_fd > 0) {
10910                 close(g_parsefile->pf_fd);
10911                 g_parsefile->pf_fd = 0;
10912         }
10913 }
10914
10915 /*
10916  * Like setinputfile, but takes an open file descriptor.  Call this with
10917  * interrupts off.
10918  */
10919 static void
10920 setinputfd(int fd, int push)
10921 {
10922         if (push) {
10923                 pushfile();
10924                 g_parsefile->buf = NULL;
10925         }
10926         g_parsefile->pf_fd = fd;
10927         if (g_parsefile->buf == NULL)
10928                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10929         g_parsefile->left_in_buffer = 0;
10930         g_parsefile->left_in_line = 0;
10931         g_parsefile->linno = 1;
10932 }
10933
10934 /*
10935  * Set the input to take input from a file.  If push is set, push the
10936  * old input onto the stack first.
10937  */
10938 static int
10939 setinputfile(const char *fname, int flags)
10940 {
10941         int fd;
10942
10943         INT_OFF;
10944         fd = open(fname, O_RDONLY | O_CLOEXEC);
10945         if (fd < 0) {
10946                 if (flags & INPUT_NOFILE_OK)
10947                         goto out;
10948                 exitstatus = 127;
10949                 ash_msg_and_raise_perror("can't open '%s'", fname);
10950         }
10951         if (fd < 10)
10952                 fd = savefd(fd);
10953         else if (O_CLOEXEC == 0) /* old libc */
10954                 close_on_exec_on(fd);
10955
10956         setinputfd(fd, flags & INPUT_PUSH_FILE);
10957  out:
10958         INT_ON;
10959         return fd;
10960 }
10961
10962 /*
10963  * Like setinputfile, but takes input from a string.
10964  */
10965 static void
10966 setinputstring(char *string)
10967 {
10968         INT_OFF;
10969         pushfile();
10970         g_parsefile->next_to_pgetc = string;
10971         g_parsefile->left_in_line = strlen(string);
10972         g_parsefile->buf = NULL;
10973         g_parsefile->linno = 1;
10974         INT_ON;
10975 }
10976
10977
10978 /*
10979  * Routines to check for mail.
10980  */
10981
10982 #if ENABLE_ASH_MAIL
10983
10984 /* Hash of mtimes of mailboxes */
10985 static unsigned mailtime_hash;
10986 /* Set if MAIL or MAILPATH is changed. */
10987 static smallint mail_var_path_changed;
10988
10989 /*
10990  * Print appropriate message(s) if mail has arrived.
10991  * If mail_var_path_changed is set,
10992  * then the value of MAIL has mail_var_path_changed,
10993  * so we just update the values.
10994  */
10995 static void
10996 chkmail(void)
10997 {
10998         const char *mpath;
10999         char *p;
11000         char *q;
11001         unsigned new_hash;
11002         struct stackmark smark;
11003         struct stat statb;
11004
11005         setstackmark(&smark);
11006         mpath = mpathset() ? mpathval() : mailval();
11007         new_hash = 0;
11008         for (;;) {
11009                 p = path_advance(&mpath, nullstr);
11010                 if (p == NULL)
11011                         break;
11012                 if (*p == '\0')
11013                         continue;
11014                 for (q = p; *q; q++)
11015                         continue;
11016 #if DEBUG
11017                 if (q[-1] != '/')
11018                         abort();
11019 #endif
11020                 q[-1] = '\0';                   /* delete trailing '/' */
11021                 if (stat(p, &statb) < 0) {
11022                         continue;
11023                 }
11024                 /* Very simplistic "hash": just a sum of all mtimes */
11025                 new_hash += (unsigned)statb.st_mtime;
11026         }
11027         if (!mail_var_path_changed && mailtime_hash != new_hash) {
11028                 if (mailtime_hash != 0)
11029                         out2str("you have mail\n");
11030                 mailtime_hash = new_hash;
11031         }
11032         mail_var_path_changed = 0;
11033         popstackmark(&smark);
11034 }
11035
11036 static void FAST_FUNC
11037 changemail(const char *val UNUSED_PARAM)
11038 {
11039         mail_var_path_changed = 1;
11040 }
11041
11042 #endif /* ASH_MAIL */
11043
11044
11045 /* ============ ??? */
11046
11047 /*
11048  * Set the shell parameters.
11049  */
11050 static void
11051 setparam(char **argv)
11052 {
11053         char **newparam;
11054         char **ap;
11055         int nparam;
11056
11057         for (nparam = 0; argv[nparam]; nparam++)
11058                 continue;
11059         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
11060         while (*argv) {
11061                 *ap++ = ckstrdup(*argv++);
11062         }
11063         *ap = NULL;
11064         freeparam(&shellparam);
11065         shellparam.malloced = 1;
11066         shellparam.nparam = nparam;
11067         shellparam.p = newparam;
11068 #if ENABLE_ASH_GETOPTS
11069         shellparam.optind = 1;
11070         shellparam.optoff = -1;
11071 #endif
11072 }
11073
11074 /*
11075  * Process shell options.  The global variable argptr contains a pointer
11076  * to the argument list; we advance it past the options.
11077  *
11078  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
11079  * For a non-interactive shell, an error condition encountered
11080  * by a special built-in ... shall cause the shell to write a diagnostic message
11081  * to standard error and exit as shown in the following table:
11082  * Error                                           Special Built-In
11083  * ...
11084  * Utility syntax error (option or operand error)  Shall exit
11085  * ...
11086  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
11087  * we see that bash does not do that (set "finishes" with error code 1 instead,
11088  * and shell continues), and people rely on this behavior!
11089  * Testcase:
11090  * set -o barfoo 2>/dev/null
11091  * echo $?
11092  *
11093  * Oh well. Let's mimic that.
11094  */
11095 static int
11096 plus_minus_o(char *name, int val)
11097 {
11098         int i;
11099
11100         if (name) {
11101                 for (i = 0; i < NOPTS; i++) {
11102                         if (strcmp(name, optnames(i)) == 0) {
11103                                 optlist[i] = val;
11104                                 return 0;
11105                         }
11106                 }
11107                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
11108                 return 1;
11109         }
11110         for (i = 0; i < NOPTS; i++) {
11111                 if (optnames(i)[0] == '\0')
11112                         continue;
11113                 if (val) {
11114                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
11115                 } else {
11116                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
11117                 }
11118         }
11119         return 0;
11120 }
11121 static void
11122 setoption(int flag, int val)
11123 {
11124         int i;
11125
11126         for (i = 0; i < NOPTS; i++) {
11127                 if (optletters(i) == flag && optnames(i)[0] != '\0') {
11128                         optlist[i] = val;
11129                         return;
11130                 }
11131         }
11132         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
11133         /* NOTREACHED */
11134 }
11135 /* If login_sh is not NULL, we are called to parse command line opts,
11136  * not "set -opts"
11137  */
11138 static int
11139 options(int *login_sh)
11140 {
11141         char *p;
11142         int val;
11143         int c;
11144
11145         if (login_sh)
11146                 minusc = NULL;
11147         while ((p = *argptr) != NULL) {
11148                 c = *p++;
11149                 if (c != '-' && c != '+')
11150                         break;
11151                 argptr++;
11152                 val = 0; /* val = 0 if c == '+' */
11153                 if (c == '-') {
11154                         val = 1;
11155                         if (p[0] == '\0' || LONE_DASH(p)) {
11156                                 if (!login_sh) {
11157                                         /* "-" means turn off -x and -v */
11158                                         if (p[0] == '\0')
11159                                                 xflag = vflag = 0;
11160                                         /* "--" means reset params */
11161                                         else if (*argptr == NULL)
11162                                                 setparam(argptr);
11163                                 }
11164                                 break;    /* "-" or "--" terminates options */
11165                         }
11166                 }
11167                 /* first char was + or - */
11168                 while ((c = *p++) != '\0') {
11169                         if (login_sh) {
11170                                 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11171                                 if (c == 'c') {
11172                                         minusc = p; /* command is after shell args */
11173                                         cflag = 1;
11174                                         continue;
11175                                 }
11176                                 if (c == 's') { /* -s, +s */
11177                                         sflag = 1;
11178                                         continue;
11179                                 }
11180                                 if (c == 'i') { /* -i, +i */
11181                                         iflag = 1;
11182                                         continue;
11183                                 }
11184                                 if (c == 'l') {
11185                                         *login_sh = 1; /* -l or +l == --login */
11186                                         continue;
11187                                 }
11188                                 /* bash does not accept +-login, we also won't */
11189                                 if (val && (c == '-')) { /* long options */
11190                                         if (strcmp(p, "login") == 0) {
11191                                                 *login_sh = 1;
11192                                         }
11193                                         break;
11194                                 }
11195                         }
11196                         if (c == 'o') {
11197                                 if (plus_minus_o(*argptr, val)) {
11198                                         /* it already printed err message */
11199                                         return 1; /* error */
11200                                 }
11201                                 if (*argptr)
11202                                         argptr++;
11203                         } else {
11204                                 setoption(c, val);
11205                         }
11206                 }
11207         }
11208         return 0;
11209 }
11210
11211 /*
11212  * The shift builtin command.
11213  */
11214 static int FAST_FUNC
11215 shiftcmd(int argc UNUSED_PARAM, char **argv)
11216 {
11217         int n;
11218         char **ap1, **ap2;
11219
11220         n = 1;
11221         if (argv[1])
11222                 n = number(argv[1]);
11223         if (n > shellparam.nparam)
11224                 return 1;
11225         INT_OFF;
11226         shellparam.nparam -= n;
11227         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11228                 if (shellparam.malloced)
11229                         free(*ap1);
11230         }
11231         ap2 = shellparam.p;
11232         while ((*ap2++ = *ap1++) != NULL)
11233                 continue;
11234 #if ENABLE_ASH_GETOPTS
11235         shellparam.optind = 1;
11236         shellparam.optoff = -1;
11237 #endif
11238         INT_ON;
11239         return 0;
11240 }
11241
11242 /*
11243  * POSIX requires that 'set' (but not export or readonly) output the
11244  * variables in lexicographic order - by the locale's collating order (sigh).
11245  * Maybe we could keep them in an ordered balanced binary tree
11246  * instead of hashed lists.
11247  * For now just roll 'em through qsort for printing...
11248  */
11249 static int
11250 showvars(const char *sep_prefix, int on, int off)
11251 {
11252         const char *sep;
11253         char **ep, **epend;
11254
11255         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11256         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11257
11258         sep = *sep_prefix ? " " : sep_prefix;
11259
11260         for (; ep < epend; ep++) {
11261                 const char *p;
11262                 const char *q;
11263
11264                 p = endofname(*ep);
11265 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11266  * makes "export -p" to have output not suitable for "eval":
11267  * import os
11268  * os.environ["test-test"]="test"
11269  * if os.fork() == 0:
11270  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11271  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11272  */
11273                 q = nullstr;
11274                 if (*p == '=')
11275                         q = single_quote(++p);
11276                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11277         }
11278         return 0;
11279 }
11280
11281 /*
11282  * The set command builtin.
11283  */
11284 static int FAST_FUNC
11285 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11286 {
11287         int retval;
11288
11289         if (!argv[1])
11290                 return showvars(nullstr, 0, VUNSET);
11291
11292         INT_OFF;
11293         retval = options(/*login_sh:*/ NULL);
11294         if (retval == 0) { /* if no parse error... */
11295                 optschanged();
11296                 if (*argptr != NULL) {
11297                         setparam(argptr);
11298                 }
11299         }
11300         INT_ON;
11301         return retval;
11302 }
11303
11304 #if ENABLE_ASH_RANDOM_SUPPORT
11305 static void FAST_FUNC
11306 change_random(const char *value)
11307 {
11308         uint32_t t;
11309
11310         if (value == NULL) {
11311                 /* "get", generate */
11312                 t = next_random(&random_gen);
11313                 /* set without recursion */
11314                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11315                 vrandom.flags &= ~VNOFUNC;
11316         } else {
11317                 /* set/reset */
11318                 t = strtoul(value, NULL, 10);
11319                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11320         }
11321 }
11322 #endif
11323
11324 #if BASH_EPOCH_VARS
11325 static void FAST_FUNC
11326 change_epoch(struct var *vepoch, const char *fmt)
11327 {
11328         struct timeval tv;
11329         char buffer[sizeof("%lu.nnnnnn") + sizeof(long)*3];
11330
11331         gettimeofday(&tv, NULL);
11332         sprintf(buffer, fmt, (unsigned long)tv.tv_sec, (unsigned)tv.tv_usec);
11333         setvar(vepoch->var_text, buffer, VNOFUNC);
11334         vepoch->flags &= ~VNOFUNC;
11335 }
11336
11337 static void FAST_FUNC
11338 change_seconds(const char *value UNUSED_PARAM)
11339 {
11340         change_epoch(&vepochs, "%lu");
11341 }
11342
11343 static void FAST_FUNC
11344 change_realtime(const char *value UNUSED_PARAM)
11345 {
11346         change_epoch(&vepochr, "%lu.%06u");
11347 }
11348 #endif
11349
11350 #if ENABLE_ASH_GETOPTS
11351 static int
11352 getopts(char *optstr, char *optvar, char **optfirst)
11353 {
11354         char *p, *q;
11355         char c = '?';
11356         int done = 0;
11357         char sbuf[2];
11358         char **optnext;
11359         int ind = shellparam.optind;
11360         int off = shellparam.optoff;
11361
11362         sbuf[1] = '\0';
11363
11364         shellparam.optind = -1;
11365         optnext = optfirst + ind - 1;
11366
11367         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11368                 p = NULL;
11369         else
11370                 p = optnext[-1] + off;
11371         if (p == NULL || *p == '\0') {
11372                 /* Current word is done, advance */
11373                 p = *optnext;
11374                 if (p == NULL || *p != '-' || *++p == '\0') {
11375  atend:
11376                         unsetvar("OPTARG");
11377                         p = NULL;
11378                         done = 1;
11379                         goto out;
11380                 }
11381                 optnext++;
11382                 if (LONE_DASH(p))        /* check for "--" */
11383                         goto atend;
11384         }
11385
11386         c = *p++;
11387         for (q = optstr; *q != c;) {
11388                 if (*q == '\0') {
11389                         /* OPTERR is a bashism */
11390                         const char *cp = lookupvar("OPTERR");
11391                         if ((cp && LONE_CHAR(cp, '0'))
11392                          || (optstr[0] == ':')
11393                         ) {
11394                                 sbuf[0] = c;
11395                                 /*sbuf[1] = '\0'; - already is */
11396                                 setvar0("OPTARG", sbuf);
11397                         } else {
11398                                 fprintf(stderr, "Illegal option -%c\n", c);
11399                                 unsetvar("OPTARG");
11400                         }
11401                         c = '?';
11402                         goto out;
11403                 }
11404                 if (*++q == ':')
11405                         q++;
11406         }
11407
11408         if (*++q == ':') {
11409                 if (*p == '\0' && (p = *optnext) == NULL) {
11410                         /* OPTERR is a bashism */
11411                         const char *cp = lookupvar("OPTERR");
11412                         if ((cp && LONE_CHAR(cp, '0'))
11413                          || (optstr[0] == ':')
11414                         ) {
11415                                 sbuf[0] = c;
11416                                 /*sbuf[1] = '\0'; - already is */
11417                                 setvar0("OPTARG", sbuf);
11418                                 c = ':';
11419                         } else {
11420                                 fprintf(stderr, "No arg for -%c option\n", c);
11421                                 unsetvar("OPTARG");
11422                                 c = '?';
11423                         }
11424                         goto out;
11425                 }
11426
11427                 if (p == *optnext)
11428                         optnext++;
11429                 setvar0("OPTARG", p);
11430                 p = NULL;
11431         } else
11432                 setvar0("OPTARG", nullstr);
11433  out:
11434         ind = optnext - optfirst + 1;
11435         setvar("OPTIND", itoa(ind), VNOFUNC);
11436         sbuf[0] = c;
11437         /*sbuf[1] = '\0'; - already is */
11438         setvar0(optvar, sbuf);
11439
11440         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11441         shellparam.optind = ind;
11442
11443         return done;
11444 }
11445
11446 /*
11447  * The getopts builtin.  Shellparam.optnext points to the next argument
11448  * to be processed.  Shellparam.optptr points to the next character to
11449  * be processed in the current argument.  If shellparam.optnext is NULL,
11450  * then it's the first time getopts has been called.
11451  */
11452 static int FAST_FUNC
11453 getoptscmd(int argc, char **argv)
11454 {
11455         char **optbase;
11456
11457         if (argc < 3)
11458                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11459         if (argc == 3) {
11460                 optbase = shellparam.p;
11461                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11462                         shellparam.optind = 1;
11463                         shellparam.optoff = -1;
11464                 }
11465         } else {
11466                 optbase = &argv[3];
11467                 if ((unsigned)shellparam.optind > argc - 2) {
11468                         shellparam.optind = 1;
11469                         shellparam.optoff = -1;
11470                 }
11471         }
11472
11473         return getopts(argv[1], argv[2], optbase);
11474 }
11475 #endif /* ASH_GETOPTS */
11476
11477
11478 /* ============ Shell parser */
11479
11480 struct heredoc {
11481         struct heredoc *next;   /* next here document in list */
11482         union node *here;       /* redirection node */
11483         char *eofmark;          /* string indicating end of input */
11484         smallint striptabs;     /* if set, strip leading tabs */
11485 };
11486
11487 static smallint tokpushback;           /* last token pushed back */
11488 static smallint quoteflag;             /* set if (part of) last token was quoted */
11489 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11490 static struct heredoc *heredoclist;    /* list of here documents to read */
11491 static char *wordtext;                 /* text of last word returned by readtoken */
11492 static struct nodelist *backquotelist;
11493 static union node *redirnode;
11494 static struct heredoc *heredoc;
11495
11496 static const char *
11497 tokname(char *buf, int tok)
11498 {
11499         if (tok < TSEMI)
11500                 return tokname_array[tok];
11501         sprintf(buf, "\"%s\"", tokname_array[tok]);
11502         return buf;
11503 }
11504
11505 /* raise_error_unexpected_syntax:
11506  * Called when an unexpected token is read during the parse.  The argument
11507  * is the token that is expected, or -1 if more than one type of token can
11508  * occur at this point.
11509  */
11510 static void raise_error_unexpected_syntax(int) NORETURN;
11511 static void
11512 raise_error_unexpected_syntax(int token)
11513 {
11514         char msg[64];
11515         char buf[16];
11516         int l;
11517
11518         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11519         if (token >= 0)
11520                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11521         raise_error_syntax(msg);
11522         /* NOTREACHED */
11523 }
11524
11525 /* parsing is heavily cross-recursive, need these forward decls */
11526 static union node *andor(void);
11527 static union node *pipeline(void);
11528 static union node *parse_command(void);
11529 static void parseheredoc(void);
11530 static int peektoken(void);
11531 static int readtoken(void);
11532
11533 static union node *
11534 list(int nlflag)
11535 {
11536         union node *n1, *n2, *n3;
11537         int tok;
11538
11539         n1 = NULL;
11540         for (;;) {
11541                 switch (peektoken()) {
11542                 case TNL:
11543                         if (!(nlflag & 1))
11544                                 break;
11545                         parseheredoc();
11546                         return n1;
11547
11548                 case TEOF:
11549                         if (!n1 && (nlflag & 1))
11550                                 n1 = NODE_EOF;
11551                         parseheredoc();
11552                         return n1;
11553                 }
11554
11555                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11556                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11557                         return n1;
11558                 nlflag |= 2;
11559
11560                 n2 = andor();
11561                 tok = readtoken();
11562                 if (tok == TBACKGND) {
11563                         if (n2->type == NPIPE) {
11564                                 n2->npipe.pipe_backgnd = 1;
11565                         } else {
11566                                 if (n2->type != NREDIR) {
11567                                         n3 = stzalloc(sizeof(struct nredir));
11568                                         n3->nredir.n = n2;
11569                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11570                                         n2 = n3;
11571                                 }
11572                                 n2->type = NBACKGND;
11573                         }
11574                 }
11575                 if (n1 == NULL) {
11576                         n1 = n2;
11577                 } else {
11578                         n3 = stzalloc(sizeof(struct nbinary));
11579                         n3->type = NSEMI;
11580                         n3->nbinary.ch1 = n1;
11581                         n3->nbinary.ch2 = n2;
11582                         n1 = n3;
11583                 }
11584                 switch (tok) {
11585                 case TNL:
11586                 case TEOF:
11587                         tokpushback = 1;
11588                         /* fall through */
11589                 case TBACKGND:
11590                 case TSEMI:
11591                         break;
11592                 default:
11593                         if ((nlflag & 1))
11594                                 raise_error_unexpected_syntax(-1);
11595                         tokpushback = 1;
11596                         return n1;
11597                 }
11598         }
11599 }
11600
11601 static union node *
11602 andor(void)
11603 {
11604         union node *n1, *n2, *n3;
11605         int t;
11606
11607         n1 = pipeline();
11608         for (;;) {
11609                 t = readtoken();
11610                 if (t == TAND) {
11611                         t = NAND;
11612                 } else if (t == TOR) {
11613                         t = NOR;
11614                 } else {
11615                         tokpushback = 1;
11616                         return n1;
11617                 }
11618                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11619                 n2 = pipeline();
11620                 n3 = stzalloc(sizeof(struct nbinary));
11621                 n3->type = t;
11622                 n3->nbinary.ch1 = n1;
11623                 n3->nbinary.ch2 = n2;
11624                 n1 = n3;
11625         }
11626 }
11627
11628 static union node *
11629 pipeline(void)
11630 {
11631         union node *n1, *n2, *pipenode;
11632         struct nodelist *lp, *prev;
11633         int negate;
11634
11635         negate = 0;
11636         TRACE(("pipeline: entered\n"));
11637         if (readtoken() == TNOT) {
11638                 negate = !negate;
11639                 checkkwd = CHKKWD | CHKALIAS;
11640         } else
11641                 tokpushback = 1;
11642         n1 = parse_command();
11643         if (readtoken() == TPIPE) {
11644                 pipenode = stzalloc(sizeof(struct npipe));
11645                 pipenode->type = NPIPE;
11646                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11647                 lp = stzalloc(sizeof(struct nodelist));
11648                 pipenode->npipe.cmdlist = lp;
11649                 lp->n = n1;
11650                 do {
11651                         prev = lp;
11652                         lp = stzalloc(sizeof(struct nodelist));
11653                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11654                         lp->n = parse_command();
11655                         prev->next = lp;
11656                 } while (readtoken() == TPIPE);
11657                 lp->next = NULL;
11658                 n1 = pipenode;
11659         }
11660         tokpushback = 1;
11661         if (negate) {
11662                 n2 = stzalloc(sizeof(struct nnot));
11663                 n2->type = NNOT;
11664                 n2->nnot.com = n1;
11665                 return n2;
11666         }
11667         return n1;
11668 }
11669
11670 static union node *
11671 makename(void)
11672 {
11673         union node *n;
11674
11675         n = stzalloc(sizeof(struct narg));
11676         n->type = NARG;
11677         /*n->narg.next = NULL; - stzalloc did it */
11678         n->narg.text = wordtext;
11679         n->narg.backquote = backquotelist;
11680         return n;
11681 }
11682
11683 static void
11684 fixredir(union node *n, const char *text, int err)
11685 {
11686         int fd;
11687
11688         TRACE(("Fix redir %s %d\n", text, err));
11689         if (!err)
11690                 n->ndup.vname = NULL;
11691
11692         fd = bb_strtou(text, NULL, 10);
11693         if (!errno && fd >= 0)
11694                 n->ndup.dupfd = fd;
11695         else if (LONE_DASH(text))
11696                 n->ndup.dupfd = -1;
11697         else {
11698                 if (err)
11699                         raise_error_syntax("bad fd number");
11700                 n->ndup.vname = makename();
11701         }
11702 }
11703
11704 static void
11705 parsefname(void)
11706 {
11707         union node *n = redirnode;
11708
11709         if (n->type == NHERE)
11710                 checkkwd = CHKEOFMARK;
11711         if (readtoken() != TWORD)
11712                 raise_error_unexpected_syntax(-1);
11713         if (n->type == NHERE) {
11714                 struct heredoc *here = heredoc;
11715                 struct heredoc *p;
11716
11717                 if (quoteflag == 0)
11718                         n->type = NXHERE;
11719                 TRACE(("Here document %d\n", n->type));
11720                 rmescapes(wordtext, 0, NULL);
11721                 here->eofmark = wordtext;
11722                 here->next = NULL;
11723                 if (heredoclist == NULL)
11724                         heredoclist = here;
11725                 else {
11726                         for (p = heredoclist; p->next; p = p->next)
11727                                 continue;
11728                         p->next = here;
11729                 }
11730         } else if (n->type == NTOFD || n->type == NFROMFD) {
11731                 fixredir(n, wordtext, 0);
11732         } else {
11733                 n->nfile.fname = makename();
11734         }
11735 }
11736
11737 static union node *
11738 simplecmd(void)
11739 {
11740         union node *args, **app;
11741         union node *n = NULL;
11742         union node *vars, **vpp;
11743         union node **rpp, *redir;
11744         int savecheckkwd;
11745         int savelinno;
11746 #if BASH_TEST2
11747         smallint double_brackets_flag = 0;
11748 #endif
11749         IF_BASH_FUNCTION(smallint function_flag = 0;)
11750
11751         args = NULL;
11752         app = &args;
11753         vars = NULL;
11754         vpp = &vars;
11755         redir = NULL;
11756         rpp = &redir;
11757
11758         savecheckkwd = CHKALIAS;
11759         savelinno = g_parsefile->linno;
11760         for (;;) {
11761                 int t;
11762                 checkkwd = savecheckkwd;
11763                 t = readtoken();
11764                 switch (t) {
11765 #if BASH_FUNCTION
11766                 case TFUNCTION:
11767                         if (peektoken() != TWORD)
11768                                 raise_error_unexpected_syntax(TWORD);
11769                         function_flag = 1;
11770                         break;
11771 #endif
11772 #if BASH_TEST2
11773                 case TAND: /* "&&" */
11774                 case TOR: /* "||" */
11775                         if (!double_brackets_flag) {
11776                                 tokpushback = 1;
11777                                 goto out;
11778                         }
11779                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11780 #endif
11781                 case TWORD:
11782                         n = stzalloc(sizeof(struct narg));
11783                         n->type = NARG;
11784                         /*n->narg.next = NULL; - stzalloc did it */
11785                         n->narg.text = wordtext;
11786 #if BASH_TEST2
11787                         if (strcmp("[[", wordtext) == 0)
11788                                 double_brackets_flag = 1;
11789                         else if (strcmp("]]", wordtext) == 0)
11790                                 double_brackets_flag = 0;
11791 #endif
11792                         n->narg.backquote = backquotelist;
11793                         if (savecheckkwd && isassignment(wordtext)) {
11794                                 *vpp = n;
11795                                 vpp = &n->narg.next;
11796                         } else {
11797                                 *app = n;
11798                                 app = &n->narg.next;
11799                                 savecheckkwd = 0;
11800                         }
11801 #if BASH_FUNCTION
11802                         if (function_flag) {
11803                                 checkkwd = CHKNL | CHKKWD;
11804                                 switch (peektoken()) {
11805                                 case TBEGIN:
11806                                 case TIF:
11807                                 case TCASE:
11808                                 case TUNTIL:
11809                                 case TWHILE:
11810                                 case TFOR:
11811                                         goto do_func;
11812                                 case TLP:
11813                                         function_flag = 0;
11814                                         break;
11815 # if BASH_TEST2
11816                                 case TWORD:
11817                                         if (strcmp("[[", wordtext) == 0)
11818                                                 goto do_func;
11819                                         /* fall through */
11820 # endif
11821                                 default:
11822                                         raise_error_unexpected_syntax(-1);
11823                                 }
11824                         }
11825 #endif
11826                         break;
11827                 case TREDIR:
11828                         *rpp = n = redirnode;
11829                         rpp = &n->nfile.next;
11830                         parsefname();   /* read name of redirection file */
11831                         break;
11832                 case TLP:
11833  IF_BASH_FUNCTION(do_func:)
11834                         if (args && app == &args->narg.next
11835                          && !vars && !redir
11836                         ) {
11837                                 struct builtincmd *bcmd;
11838                                 const char *name;
11839
11840                                 /* We have a function */
11841                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11842                                         raise_error_unexpected_syntax(TRP);
11843                                 name = n->narg.text;
11844                                 if (!goodname(name)
11845                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11846                                 ) {
11847                                         raise_error_syntax("bad function name");
11848                                 }
11849                                 n->type = NDEFUN;
11850                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11851                                 n->ndefun.text = n->narg.text;
11852                                 n->ndefun.linno = g_parsefile->linno;
11853                                 n->ndefun.body = parse_command();
11854                                 return n;
11855                         }
11856                         IF_BASH_FUNCTION(function_flag = 0;)
11857                         /* fall through */
11858                 default:
11859                         tokpushback = 1;
11860                         goto out;
11861                 }
11862         }
11863  out:
11864         *app = NULL;
11865         *vpp = NULL;
11866         *rpp = NULL;
11867         n = stzalloc(sizeof(struct ncmd));
11868         if (NCMD != 0)
11869                 n->type = NCMD;
11870         n->ncmd.linno = savelinno;
11871         n->ncmd.args = args;
11872         n->ncmd.assign = vars;
11873         n->ncmd.redirect = redir;
11874         return n;
11875 }
11876
11877 static union node *
11878 parse_command(void)
11879 {
11880         union node *n1, *n2;
11881         union node *ap, **app;
11882         union node *cp, **cpp;
11883         union node *redir, **rpp;
11884         union node **rpp2;
11885         int t;
11886         int savelinno;
11887
11888         redir = NULL;
11889         rpp2 = &redir;
11890
11891         savelinno = g_parsefile->linno;
11892
11893         switch (readtoken()) {
11894         default:
11895                 raise_error_unexpected_syntax(-1);
11896                 /* NOTREACHED */
11897         case TIF:
11898                 n1 = stzalloc(sizeof(struct nif));
11899                 n1->type = NIF;
11900                 n1->nif.test = list(0);
11901                 if (readtoken() != TTHEN)
11902                         raise_error_unexpected_syntax(TTHEN);
11903                 n1->nif.ifpart = list(0);
11904                 n2 = n1;
11905                 while (readtoken() == TELIF) {
11906                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11907                         n2 = n2->nif.elsepart;
11908                         n2->type = NIF;
11909                         n2->nif.test = list(0);
11910                         if (readtoken() != TTHEN)
11911                                 raise_error_unexpected_syntax(TTHEN);
11912                         n2->nif.ifpart = list(0);
11913                 }
11914                 if (lasttoken == TELSE)
11915                         n2->nif.elsepart = list(0);
11916                 else {
11917                         n2->nif.elsepart = NULL;
11918                         tokpushback = 1;
11919                 }
11920                 t = TFI;
11921                 break;
11922         case TWHILE:
11923         case TUNTIL: {
11924                 int got;
11925                 n1 = stzalloc(sizeof(struct nbinary));
11926                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11927                 n1->nbinary.ch1 = list(0);
11928                 got = readtoken();
11929                 if (got != TDO) {
11930                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11931                                         got == TWORD ? wordtext : ""));
11932                         raise_error_unexpected_syntax(TDO);
11933                 }
11934                 n1->nbinary.ch2 = list(0);
11935                 t = TDONE;
11936                 break;
11937         }
11938         case TFOR:
11939                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11940                         raise_error_syntax("bad for loop variable");
11941                 n1 = stzalloc(sizeof(struct nfor));
11942                 n1->type = NFOR;
11943                 n1->nfor.linno = savelinno;
11944                 n1->nfor.var = wordtext;
11945                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11946                 if (readtoken() == TIN) {
11947                         app = &ap;
11948                         while (readtoken() == TWORD) {
11949                                 n2 = stzalloc(sizeof(struct narg));
11950                                 n2->type = NARG;
11951                                 /*n2->narg.next = NULL; - stzalloc did it */
11952                                 n2->narg.text = wordtext;
11953                                 n2->narg.backquote = backquotelist;
11954                                 *app = n2;
11955                                 app = &n2->narg.next;
11956                         }
11957                         *app = NULL;
11958                         n1->nfor.args = ap;
11959                         if (lasttoken != TNL && lasttoken != TSEMI)
11960                                 raise_error_unexpected_syntax(-1);
11961                 } else {
11962                         n2 = stzalloc(sizeof(struct narg));
11963                         n2->type = NARG;
11964                         /*n2->narg.next = NULL; - stzalloc did it */
11965                         n2->narg.text = (char *)dolatstr;
11966                         /*n2->narg.backquote = NULL;*/
11967                         n1->nfor.args = n2;
11968                         /*
11969                          * Newline or semicolon here is optional (but note
11970                          * that the original Bourne shell only allowed NL).
11971                          */
11972                         if (lasttoken != TSEMI)
11973                                 tokpushback = 1;
11974                 }
11975                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11976                 if (readtoken() != TDO)
11977                         raise_error_unexpected_syntax(TDO);
11978                 n1->nfor.body = list(0);
11979                 t = TDONE;
11980                 break;
11981         case TCASE:
11982                 n1 = stzalloc(sizeof(struct ncase));
11983                 n1->type = NCASE;
11984                 n1->ncase.linno = savelinno;
11985                 if (readtoken() != TWORD)
11986                         raise_error_unexpected_syntax(TWORD);
11987                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11988                 n2->type = NARG;
11989                 /*n2->narg.next = NULL; - stzalloc did it */
11990                 n2->narg.text = wordtext;
11991                 n2->narg.backquote = backquotelist;
11992                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11993                 if (readtoken() != TIN)
11994                         raise_error_unexpected_syntax(TIN);
11995                 cpp = &n1->ncase.cases;
11996  next_case:
11997                 checkkwd = CHKNL | CHKKWD;
11998                 t = readtoken();
11999                 while (t != TESAC) {
12000                         if (lasttoken == TLP)
12001                                 readtoken();
12002                         *cpp = cp = stzalloc(sizeof(struct nclist));
12003                         cp->type = NCLIST;
12004                         app = &cp->nclist.pattern;
12005                         for (;;) {
12006                                 *app = ap = stzalloc(sizeof(struct narg));
12007                                 ap->type = NARG;
12008                                 /*ap->narg.next = NULL; - stzalloc did it */
12009                                 ap->narg.text = wordtext;
12010                                 ap->narg.backquote = backquotelist;
12011                                 if (readtoken() != TPIPE)
12012                                         break;
12013                                 app = &ap->narg.next;
12014                                 readtoken();
12015                         }
12016                         //ap->narg.next = NULL;
12017                         if (lasttoken != TRP)
12018                                 raise_error_unexpected_syntax(TRP);
12019                         cp->nclist.body = list(2);
12020
12021                         cpp = &cp->nclist.next;
12022
12023                         checkkwd = CHKNL | CHKKWD;
12024                         t = readtoken();
12025                         if (t != TESAC) {
12026                                 if (t != TENDCASE)
12027                                         raise_error_unexpected_syntax(TENDCASE);
12028                                 goto next_case;
12029                         }
12030                 }
12031                 *cpp = NULL;
12032                 goto redir;
12033         case TLP:
12034                 n1 = stzalloc(sizeof(struct nredir));
12035                 n1->type = NSUBSHELL;
12036                 n1->nredir.linno = savelinno;
12037                 n1->nredir.n = list(0);
12038                 /*n1->nredir.redirect = NULL; - stzalloc did it */
12039                 t = TRP;
12040                 break;
12041         case TBEGIN:
12042                 n1 = list(0);
12043                 t = TEND;
12044                 break;
12045         IF_BASH_FUNCTION(case TFUNCTION:)
12046         case TWORD:
12047         case TREDIR:
12048                 tokpushback = 1;
12049                 return simplecmd();
12050         }
12051
12052         if (readtoken() != t)
12053                 raise_error_unexpected_syntax(t);
12054
12055  redir:
12056         /* Now check for redirection which may follow command */
12057         checkkwd = CHKKWD | CHKALIAS;
12058         rpp = rpp2;
12059         while (readtoken() == TREDIR) {
12060                 *rpp = n2 = redirnode;
12061                 rpp = &n2->nfile.next;
12062                 parsefname();
12063         }
12064         tokpushback = 1;
12065         *rpp = NULL;
12066         if (redir) {
12067                 if (n1->type != NSUBSHELL) {
12068                         n2 = stzalloc(sizeof(struct nredir));
12069                         n2->type = NREDIR;
12070                         n2->nredir.linno = savelinno;
12071                         n2->nredir.n = n1;
12072                         n1 = n2;
12073                 }
12074                 n1->nredir.redirect = redir;
12075         }
12076         return n1;
12077 }
12078
12079 #if BASH_DOLLAR_SQUOTE
12080 static int
12081 decode_dollar_squote(void)
12082 {
12083         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
12084         int c, cnt;
12085         char *p;
12086         char buf[4];
12087
12088         c = pgetc();
12089         p = strchr(C_escapes, c);
12090         if (p) {
12091                 buf[0] = c;
12092                 p = buf;
12093                 cnt = 3;
12094                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
12095                         do {
12096                                 c = pgetc();
12097                                 *++p = c;
12098                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
12099                         pungetc();
12100                 } else if (c == 'x') { /* \xHH */
12101                         do {
12102                                 c = pgetc();
12103                                 *++p = c;
12104                         } while (isxdigit(c) && --cnt);
12105                         pungetc();
12106                         if (cnt == 3) { /* \x but next char is "bad" */
12107                                 c = 'x';
12108                                 goto unrecognized;
12109                         }
12110                 } else { /* simple seq like \\ or \t */
12111                         p++;
12112                 }
12113                 *p = '\0';
12114                 p = buf;
12115                 c = bb_process_escape_sequence((void*)&p);
12116         } else { /* unrecognized "\z": print both chars unless ' or " */
12117                 if (c != '\'' && c != '"') {
12118  unrecognized:
12119                         c |= 0x100; /* "please encode \, then me" */
12120                 }
12121         }
12122         return c;
12123 }
12124 #endif
12125
12126 /* Used by expandstr to get here-doc like behaviour. */
12127 #define FAKEEOFMARK ((char*)(uintptr_t)1)
12128
12129 static ALWAYS_INLINE int
12130 realeofmark(const char *eofmark)
12131 {
12132         return eofmark && eofmark != FAKEEOFMARK;
12133 }
12134
12135 /*
12136  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
12137  * is not NULL, read a here document.  In the latter case, eofmark is the
12138  * word which marks the end of the document and striptabs is true if
12139  * leading tabs should be stripped from the document.  The argument c
12140  * is the first character of the input token or document.
12141  *
12142  * Because C does not have internal subroutines, I have simulated them
12143  * using goto's to implement the subroutine linkage.  The following macros
12144  * will run code that appears at the end of readtoken1.
12145  */
12146 #define CHECKEND()      {goto checkend; checkend_return:;}
12147 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
12148 #define PARSESUB()      {goto parsesub; parsesub_return:;}
12149 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
12150 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
12151 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
12152 static int
12153 readtoken1(int c, int syntax, char *eofmark, int striptabs)
12154 {
12155         /* NB: syntax parameter fits into smallint */
12156         /* c parameter is an unsigned char or PEOF or PEOA */
12157         char *out;
12158         size_t len;
12159         struct nodelist *bqlist;
12160         smallint quotef;
12161         smallint oldstyle;
12162         smallint pssyntax;   /* we are expanding a prompt string */
12163         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
12164         /* syntax stack */
12165         struct synstack synbase = { };
12166         struct synstack *synstack = &synbase;
12167
12168 #if ENABLE_ASH_EXPAND_PRMT
12169         pssyntax = (syntax == PSSYNTAX);
12170         if (pssyntax)
12171                 syntax = DQSYNTAX;
12172 #else
12173         pssyntax = 0; /* constant */
12174 #endif
12175         synstack->syntax = syntax;
12176
12177         if (syntax == DQSYNTAX)
12178                 synstack->dblquote = 1;
12179         quotef = 0;
12180         bqlist = NULL;
12181
12182         STARTSTACKSTR(out);
12183  loop:
12184         /* For each line, until end of word */
12185         CHECKEND();     /* set c to PEOF if at end of here document */
12186         for (;;) {      /* until end of line or end of word */
12187                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12188                 switch (SIT(c, synstack->syntax)) {
12189                 case CNL:       /* '\n' */
12190                         if (synstack->syntax == BASESYNTAX
12191                          && !synstack->varnest
12192                         ) {
12193                                 goto endword;   /* exit outer loop */
12194                         }
12195                         USTPUTC(c, out);
12196                         nlprompt();
12197                         c = synstack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
12198                         goto loop;              /* continue outer loop */
12199                 case CWORD:
12200                         USTPUTC(c, out);
12201                         break;
12202                 case CCTL:
12203 #if BASH_DOLLAR_SQUOTE
12204                         if (c == '\\' && bash_dollar_squote) {
12205                                 c = decode_dollar_squote();
12206                                 if (c == '\0') {
12207                                         /* skip $'\000', $'\x00' (like bash) */
12208                                         break;
12209                                 }
12210                                 if (c & 0x100) {
12211                                         /* Unknown escape. Encode as '\z' */
12212                                         c = (unsigned char)c;
12213                                         if (eofmark == NULL || synstack->dblquote)
12214                                                 USTPUTC(CTLESC, out);
12215                                         USTPUTC('\\', out);
12216                                 }
12217                         }
12218 #endif
12219                         if (!eofmark || synstack->dblquote || synstack->varnest)
12220                                 USTPUTC(CTLESC, out);
12221                         USTPUTC(c, out);
12222                         break;
12223                 case CBACK:     /* backslash */
12224                         c = pgetc_without_PEOA();
12225                         if (c == PEOF) {
12226                                 USTPUTC(CTLESC, out);
12227                                 USTPUTC('\\', out);
12228                                 pungetc();
12229                         } else {
12230                                 if (pssyntax && c == '$') {
12231                                         USTPUTC(CTLESC, out);
12232                                         USTPUTC('\\', out);
12233                                 }
12234                                 /* Backslash is retained if we are in "str"
12235                                  * and next char isn't dquote-special.
12236                                  */
12237                                 if (synstack->dblquote
12238                                  && c != '\\'
12239                                  && c != '`'
12240                                  && c != '$'
12241                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12242                                  && (c != '}' || !synstack->varnest)
12243                                 ) {
12244                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12245                                         USTPUTC('\\', out);
12246                                 }
12247                                 USTPUTC(CTLESC, out);
12248                                 USTPUTC(c, out);
12249                                 quotef = 1;
12250                         }
12251                         break;
12252                 case CSQUOTE:
12253                         synstack->syntax = SQSYNTAX;
12254  quotemark:
12255                         if (eofmark == NULL) {
12256                                 USTPUTC(CTLQUOTEMARK, out);
12257                         }
12258                         break;
12259                 case CDQUOTE:
12260                         synstack->syntax = DQSYNTAX;
12261                         synstack->dblquote = 1;
12262  toggledq:
12263                         if (synstack->varnest)
12264                                 synstack->innerdq ^= 1;
12265                         goto quotemark;
12266                 case CENDQUOTE:
12267                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12268                         if (eofmark != NULL && synstack->varnest == 0) {
12269                                 USTPUTC(c, out);
12270                                 break;
12271                         }
12272
12273                         if (synstack->dqvarnest == 0) {
12274                                 synstack->syntax = BASESYNTAX;
12275                                 synstack->dblquote = 0;
12276                         }
12277
12278                         quotef = 1;
12279
12280                         if (c == '"')
12281                                 goto toggledq;
12282
12283                         goto quotemark;
12284                 case CVAR:      /* '$' */
12285                         PARSESUB();             /* parse substitution */
12286                         break;
12287                 case CENDVAR:   /* '}' */
12288                         if (!synstack->innerdq && synstack->varnest > 0) {
12289                                 if (!--synstack->varnest && synstack->varpushed)
12290                                         synstack_pop(&synstack);
12291                                 else if (synstack->dqvarnest > 0)
12292                                         synstack->dqvarnest--;
12293                                 c = CTLENDVAR;
12294                         }
12295                         USTPUTC(c, out);
12296                         break;
12297 #if ENABLE_FEATURE_SH_MATH
12298                 case CLP:       /* '(' in arithmetic */
12299                         synstack->parenlevel++;
12300                         USTPUTC(c, out);
12301                         break;
12302                 case CRP:       /* ')' in arithmetic */
12303                         if (synstack->parenlevel > 0) {
12304                                 synstack->parenlevel--;
12305                         } else {
12306                                 if (pgetc_eatbnl() == ')') {
12307                                         c = CTLENDARI;
12308                                         synstack_pop(&synstack);
12309                                 } else {
12310                                         /*
12311                                          * unbalanced parens
12312                                          * (don't 2nd guess - no error)
12313                                          */
12314                                         pungetc();
12315                                 }
12316                         }
12317                         USTPUTC(c, out);
12318                         break;
12319 #endif
12320                 case CBQUOTE:   /* '`' */
12321                         if (checkkwd & CHKEOFMARK) {
12322                                 quotef = 1;
12323                                 USTPUTC('`', out);
12324                                 break;
12325                         }
12326
12327                         PARSEBACKQOLD();
12328                         break;
12329                 case CENDFILE:
12330                         goto endword;           /* exit outer loop */
12331                 case CIGN:
12332                         break;
12333                 default:
12334                         if (synstack->varnest == 0) {
12335 #if BASH_REDIR_OUTPUT
12336                                 if (c == '&') {
12337 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12338                                         if (pgetc() == '>')
12339                                                 c = 0x100 + '>'; /* flag &> */
12340                                         pungetc();
12341                                 }
12342 #endif
12343                                 goto endword;   /* exit outer loop */
12344                         }
12345                         IF_ASH_ALIAS(if (c != PEOA))
12346                                 USTPUTC(c, out);
12347                 }
12348                 c = synstack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
12349         } /* for (;;) */
12350  endword:
12351
12352 #if ENABLE_FEATURE_SH_MATH
12353         if (synstack->syntax == ARISYNTAX)
12354                 raise_error_syntax("missing '))'");
12355 #endif
12356         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12357                 raise_error_syntax("unterminated quoted string");
12358         if (synstack->varnest != 0) {
12359                 /* { */
12360                 raise_error_syntax("missing '}'");
12361         }
12362         USTPUTC('\0', out);
12363         len = out - (char *)stackblock();
12364         out = stackblock();
12365         if (eofmark == NULL) {
12366                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12367                  && quotef == 0
12368                 ) {
12369                         if (isdigit_str9(out)) {
12370                                 PARSEREDIR(); /* passed as params: out, c */
12371                                 lasttoken = TREDIR;
12372                                 return lasttoken;
12373                         }
12374                         /* else: non-number X seen, interpret it
12375                          * as "NNNX>file" = "NNNX >file" */
12376                 }
12377                 pungetc();
12378         }
12379         quoteflag = quotef;
12380         backquotelist = bqlist;
12381         grabstackblock(len);
12382         wordtext = out;
12383         lasttoken = TWORD;
12384         return lasttoken;
12385 /* end of readtoken routine */
12386
12387 /*
12388  * Check to see whether we are at the end of the here document.  When this
12389  * is called, c is set to the first character of the next input line.  If
12390  * we are at the end of the here document, this routine sets the c to PEOF.
12391  */
12392 checkend: {
12393         if (realeofmark(eofmark)) {
12394                 int markloc;
12395                 char *p;
12396
12397 #if ENABLE_ASH_ALIAS
12398                 if (c == PEOA)
12399                         c = pgetc_without_PEOA();
12400 #endif
12401                 if (striptabs) {
12402                         while (c == '\t') {
12403                                 c = pgetc_without_PEOA();
12404                         }
12405                 }
12406
12407                 markloc = out - (char *)stackblock();
12408                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12409                         if (c != *p)
12410                                 goto more_heredoc;
12411                         /* FIXME: fails for backslash-newlined terminator:
12412                          * cat <<EOF
12413                          * ...
12414                          * EO\
12415                          * F
12416                          * (see heredoc_bkslash_newline2.tests)
12417                          */
12418                         c = pgetc_without_PEOA();
12419                 }
12420
12421                 if (c == '\n' || c == PEOF) {
12422                         c = PEOF;
12423                         g_parsefile->linno++;
12424                         needprompt = doprompt;
12425                 } else {
12426                         int len_here;
12427
12428  more_heredoc:
12429                         p = (char *)stackblock() + markloc + 1;
12430                         len_here = out - p;
12431
12432                         if (len_here) {
12433                                 len_here -= (c >= PEOF);
12434                                 c = p[-1];
12435
12436                                 if (len_here) {
12437                                         char *str;
12438
12439                                         str = alloca(len_here + 1);
12440                                         *(char *)mempcpy(str, p, len_here) = '\0';
12441
12442                                         pushstring(str, NULL);
12443                                 }
12444                         }
12445                 }
12446
12447                 STADJUST((char *)stackblock() + markloc - out, out);
12448         }
12449         goto checkend_return;
12450 }
12451
12452 /*
12453  * Parse a redirection operator.  The variable "out" points to a string
12454  * specifying the fd to be redirected.  The variable "c" contains the
12455  * first character of the redirection operator.
12456  */
12457 parseredir: {
12458         /* out is already checked to be a valid number or "" */
12459         int fd = (*out == '\0' ? -1 : atoi(out));
12460         union node *np;
12461
12462         np = stzalloc(sizeof(struct nfile));
12463         if (c == '>') {
12464                 np->nfile.fd = 1;
12465                 c = pgetc_eatbnl();
12466                 if (c == '>')
12467                         np->type = NAPPEND;
12468                 else if (c == '|')
12469                         np->type = NCLOBBER;
12470                 else if (c == '&')
12471                         np->type = NTOFD;
12472                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12473                 else {
12474                         np->type = NTO;
12475                         pungetc();
12476                 }
12477         }
12478 #if BASH_REDIR_OUTPUT
12479         else if (c == 0x100 + '>') { /* this flags &> redirection */
12480                 np->nfile.fd = 1;
12481                 pgetc(); /* this is '>', no need to check */
12482                 np->type = NTO2;
12483         }
12484 #endif
12485         else { /* c == '<' */
12486                 /*np->nfile.fd = 0; - stzalloc did it */
12487                 c = pgetc_eatbnl();
12488                 switch (c) {
12489                 case '<':
12490                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12491                                 np = stzalloc(sizeof(struct nhere));
12492                                 /*np->nfile.fd = 0; - stzalloc did it */
12493                         }
12494                         np->type = NHERE;
12495                         heredoc = stzalloc(sizeof(struct heredoc));
12496                         heredoc->here = np;
12497                         c = pgetc_eatbnl();
12498                         if (c == '-') {
12499                                 heredoc->striptabs = 1;
12500                         } else {
12501                                 /*heredoc->striptabs = 0; - stzalloc did it */
12502                                 pungetc();
12503                         }
12504                         break;
12505
12506                 case '&':
12507                         np->type = NFROMFD;
12508                         break;
12509
12510                 case '>':
12511                         np->type = NFROMTO;
12512                         break;
12513
12514                 default:
12515                         np->type = NFROM;
12516                         pungetc();
12517                         break;
12518                 }
12519         }
12520         if (fd >= 0)
12521                 np->nfile.fd = fd;
12522         redirnode = np;
12523         goto parseredir_return;
12524 }
12525
12526 /*
12527  * Parse a substitution.  At this point, we have read the dollar sign
12528  * and nothing else.
12529  */
12530
12531 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12532  * (assuming ascii char codes, as the original implementation did) */
12533 #define is_special(c) \
12534         (((unsigned)(c) - 33 < 32) \
12535                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12536 parsesub: {
12537         unsigned char subtype;
12538         int typeloc;
12539
12540         c = pgetc_eatbnl();
12541         if ((checkkwd & CHKEOFMARK)
12542          || c > 255 /* PEOA or PEOF */
12543          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12544         ) {
12545 #if BASH_DOLLAR_SQUOTE
12546                 if (synstack->syntax != DQSYNTAX && c == '\'')
12547                         bash_dollar_squote = 1;
12548                 else
12549 #endif
12550                         USTPUTC('$', out);
12551                 pungetc();
12552         } else if (c == '(') {
12553                 /* $(command) or $((arith)) */
12554                 if (pgetc_eatbnl() == '(') {
12555 #if ENABLE_FEATURE_SH_MATH
12556                         PARSEARITH();
12557 #else
12558                         raise_error_syntax("support for $((arith)) is disabled");
12559 #endif
12560                 } else {
12561                         pungetc();
12562                         PARSEBACKQNEW();
12563                 }
12564         } else {
12565                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12566                 smalluint newsyn = synstack->syntax;
12567
12568                 USTPUTC(CTLVAR, out);
12569                 typeloc = out - (char *)stackblock();
12570                 STADJUST(1, out);
12571                 subtype = VSNORMAL;
12572                 if (c == '{') {
12573                         c = pgetc_eatbnl();
12574                         subtype = 0;
12575                 }
12576  varname:
12577                 if (is_name(c)) {
12578                         /* $[{[#]]NAME[}] */
12579                         do {
12580                                 STPUTC(c, out);
12581                                 c = pgetc_eatbnl();
12582                         } while (is_in_name(c));
12583                 } else if (isdigit(c)) {
12584                         /* $[{[#]]NUM[}] */
12585                         do {
12586                                 STPUTC(c, out);
12587                                 c = pgetc_eatbnl();
12588                         } while (isdigit(c));
12589                 } else if (c != '}') {
12590                         /* $[{[#]]<specialchar>[}] */
12591                         int cc = c;
12592
12593                         c = pgetc_eatbnl();
12594                         if (!subtype && cc == '#') {
12595                                 subtype = VSLENGTH;
12596                                 if (c == '_' || isalnum(c))
12597                                         goto varname;
12598                                 cc = c;
12599                                 c = pgetc_eatbnl();
12600                                 if (cc == '}' || c != '}') {
12601                                         pungetc();
12602                                         subtype = 0;
12603                                         c = cc;
12604                                         cc = '#';
12605                                 }
12606                         }
12607
12608                         if (!is_special(cc)) {
12609                                 if (subtype == VSLENGTH)
12610                                         subtype = 0;
12611                                 goto badsub;
12612                         }
12613
12614                         USTPUTC(cc, out);
12615                 } else
12616                         goto badsub;
12617
12618                 if (c != '}' && subtype == VSLENGTH) {
12619                         /* ${#VAR didn't end with } */
12620                         goto badsub;
12621                 }
12622
12623                 if (subtype == 0) {
12624                         static const char types[] ALIGN1 = "}-+?=";
12625                         /* ${VAR...} but not $VAR or ${#VAR} */
12626                         /* c == first char after VAR */
12627                         int cc = c;
12628
12629                         switch (c) {
12630                         case ':':
12631                                 c = pgetc_eatbnl();
12632 #if BASH_SUBSTR
12633                                 /* This check is only needed to not misinterpret
12634                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12635                                  * constructs.
12636                                  */
12637                                 if (!strchr(types, c)) {
12638                                         subtype = VSSUBSTR;
12639                                         pungetc();
12640                                         break; /* "goto badsub" is bigger (!) */
12641                                 }
12642 #endif
12643                                 subtype = VSNUL;
12644                                 /*FALLTHROUGH*/
12645                         default: {
12646                                 const char *p = strchr(types, c);
12647                                 if (p == NULL)
12648                                         break;
12649                                 subtype |= p - types + VSNORMAL;
12650                                 break;
12651                         }
12652                         case '%':
12653                         case '#':
12654                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12655                                 c = pgetc_eatbnl();
12656                                 if (c == cc)
12657                                         subtype++;
12658                                 else
12659                                         pungetc();
12660
12661                                 newsyn = BASESYNTAX;
12662                                 break;
12663 #if BASH_PATTERN_SUBST
12664                         case '/':
12665                                 /* ${v/[/]pattern/repl} */
12666 //TODO: encode pattern and repl separately.
12667 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12668 // are broken (should print "ONE")
12669                                 subtype = VSREPLACE;
12670                                 newsyn = BASESYNTAX;
12671                                 c = pgetc_eatbnl();
12672                                 if (c != '/')
12673                                         goto badsub;
12674                                 subtype++; /* VSREPLACEALL */
12675                                 break;
12676 #endif
12677                         }
12678                 } else {
12679  badsub:
12680                         pungetc();
12681                 }
12682
12683                 if (newsyn == ARISYNTAX)
12684                         newsyn = DQSYNTAX;
12685
12686                 if ((newsyn != synstack->syntax || synstack->innerdq)
12687                  && subtype != VSNORMAL
12688                 ) {
12689                         synstack_push(&synstack,
12690                                 synstack->prev ?: alloca(sizeof(*synstack)),
12691                                 newsyn);
12692
12693                         synstack->varpushed = 1;
12694                         synstack->dblquote = newsyn != BASESYNTAX;
12695                 }
12696
12697                 ((unsigned char *)stackblock())[typeloc] = subtype;
12698                 if (subtype != VSNORMAL) {
12699                         synstack->varnest++;
12700                         if (synstack->dblquote)
12701                                 synstack->dqvarnest++;
12702                 }
12703                 STPUTC('=', out);
12704         }
12705         goto parsesub_return;
12706 }
12707
12708 /*
12709  * Called to parse command substitutions.  Newstyle is set if the command
12710  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12711  * list of commands (passed by reference), and savelen is the number of
12712  * characters on the top of the stack which must be preserved.
12713  */
12714 parsebackq: {
12715         struct nodelist **nlpp;
12716         union node *n;
12717         char *str;
12718         size_t savelen;
12719         smallint saveprompt = 0;
12720
12721         str = NULL;
12722         savelen = out - (char *)stackblock();
12723         if (savelen > 0) {
12724                 /*
12725                  * FIXME: this can allocate very large block on stack and SEGV.
12726                  * Example:
12727                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12728                  * allocates 100kb for every command subst. With about
12729                  * a hundred command substitutions stack overflows.
12730                  * With larger prepended string, SEGV happens sooner.
12731                  */
12732                 str = alloca(savelen);
12733                 memcpy(str, stackblock(), savelen);
12734         }
12735
12736         if (oldstyle) {
12737                 /* We must read until the closing backquote, giving special
12738                  * treatment to some slashes, and then push the string and
12739                  * reread it as input, interpreting it normally.
12740                  */
12741                 char *pout;
12742                 size_t psavelen;
12743                 char *pstr;
12744
12745                 STARTSTACKSTR(pout);
12746                 for (;;) {
12747                         int pc;
12748
12749                         setprompt_if(needprompt, 2);
12750                         pc = pgetc_eatbnl();
12751                         switch (pc) {
12752                         case '`':
12753                                 goto done;
12754
12755                         case '\\':
12756                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12757                                 if (pc != '\\' && pc != '`' && pc != '$'
12758                                  && (!synstack->dblquote || pc != '"')
12759                                 ) {
12760                                         STPUTC('\\', pout);
12761                                 }
12762                                 if (pc <= 255 /* not PEOA or PEOF */) {
12763                                         break;
12764                                 }
12765                                 /* fall through */
12766
12767                         case PEOF:
12768                         IF_ASH_ALIAS(case PEOA:)
12769                                 raise_error_syntax("EOF in backquote substitution");
12770
12771                         case '\n':
12772                                 nlnoprompt();
12773                                 break;
12774
12775                         default:
12776                                 break;
12777                         }
12778                         STPUTC(pc, pout);
12779                 }
12780  done:
12781                 STPUTC('\0', pout);
12782                 psavelen = pout - (char *)stackblock();
12783                 if (psavelen > 0) {
12784                         pstr = grabstackstr(pout);
12785                         setinputstring(pstr);
12786                 }
12787         }
12788         nlpp = &bqlist;
12789         while (*nlpp)
12790                 nlpp = &(*nlpp)->next;
12791         *nlpp = stzalloc(sizeof(**nlpp));
12792         /* (*nlpp)->next = NULL; - stzalloc did it */
12793
12794         if (oldstyle) {
12795                 saveprompt = doprompt;
12796                 doprompt = 0;
12797         }
12798
12799         n = list(2);
12800
12801         if (oldstyle)
12802                 doprompt = saveprompt;
12803         else if (readtoken() != TRP)
12804                 raise_error_unexpected_syntax(TRP);
12805
12806         (*nlpp)->n = n;
12807         if (oldstyle) {
12808                 /*
12809                  * Start reading from old file again, ignoring any pushed back
12810                  * tokens left from the backquote parsing
12811                  */
12812                 popfile();
12813                 tokpushback = 0;
12814         }
12815         while (stackblocksize() <= savelen)
12816                 growstackblock();
12817         STARTSTACKSTR(out);
12818         if (str) {
12819                 memcpy(out, str, savelen);
12820                 STADJUST(savelen, out);
12821         }
12822         USTPUTC(CTLBACKQ, out);
12823         if (oldstyle)
12824                 goto parsebackq_oldreturn;
12825         goto parsebackq_newreturn;
12826 }
12827
12828 #if ENABLE_FEATURE_SH_MATH
12829 /*
12830  * Parse an arithmetic expansion (indicate start of one and set state)
12831  */
12832 parsearith: {
12833
12834         synstack_push(&synstack,
12835                         synstack->prev ?: alloca(sizeof(*synstack)),
12836                         ARISYNTAX);
12837         synstack->dblquote = 1;
12838         USTPUTC(CTLARI, out);
12839         goto parsearith_return;
12840 }
12841 #endif
12842 } /* end of readtoken */
12843
12844 /*
12845  * Read the next input token.
12846  * If the token is a word, we set backquotelist to the list of cmds in
12847  *      backquotes.  We set quoteflag to true if any part of the word was
12848  *      quoted.
12849  * If the token is TREDIR, then we set redirnode to a structure containing
12850  *      the redirection.
12851  *
12852  * [Change comment:  here documents and internal procedures]
12853  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12854  *  word parsing code into a separate routine.  In this case, readtoken
12855  *  doesn't need to have any internal procedures, but parseword does.
12856  *  We could also make parseoperator in essence the main routine, and
12857  *  have parseword (readtoken1?) handle both words and redirection.]
12858  */
12859 #define NEW_xxreadtoken
12860 #ifdef NEW_xxreadtoken
12861 /* singles must be first! */
12862 static const char xxreadtoken_chars[7] ALIGN1 = {
12863         '\n', '(', ')', /* singles */
12864         '&', '|', ';',  /* doubles */
12865         0
12866 };
12867
12868 #define xxreadtoken_singles 3
12869 #define xxreadtoken_doubles 3
12870
12871 static const char xxreadtoken_tokens[] ALIGN1 = {
12872         TNL, TLP, TRP,          /* only single occurrence allowed */
12873         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12874         TEOF,                   /* corresponds to trailing nul */
12875         TAND, TOR, TENDCASE     /* if double occurrence */
12876 };
12877
12878 static int
12879 xxreadtoken(void)
12880 {
12881         int c;
12882
12883         if (tokpushback) {
12884                 tokpushback = 0;
12885                 return lasttoken;
12886         }
12887         setprompt_if(needprompt, 2);
12888         for (;;) {                      /* until token or start of word found */
12889                 c = pgetc_eatbnl();
12890                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12891                         continue;
12892
12893                 if (c == '#') {
12894                         while ((c = pgetc()) != '\n' && c != PEOF)
12895                                 continue;
12896                         pungetc();
12897                 } else if (c == '\\') {
12898                         break; /* return readtoken1(...) */
12899                 } else {
12900                         const char *p;
12901
12902                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12903                         if (c != PEOF) {
12904                                 if (c == '\n') {
12905                                         nlnoprompt();
12906                                 }
12907
12908                                 p = strchr(xxreadtoken_chars, c);
12909                                 if (p == NULL)
12910                                         break; /* return readtoken1(...) */
12911
12912                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12913                                         int cc = pgetc_eatbnl();
12914                                         if (cc == c) {    /* double occurrence? */
12915                                                 p += xxreadtoken_doubles + 1;
12916                                         } else {
12917                                                 pungetc();
12918 #if BASH_REDIR_OUTPUT
12919                                                 if (c == '&' && cc == '>') /* &> */
12920                                                         break; /* return readtoken1(...) */
12921 #endif
12922                                         }
12923                                 }
12924                         }
12925                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12926                         return lasttoken;
12927                 }
12928         } /* for (;;) */
12929
12930         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12931 }
12932 #else /* old xxreadtoken */
12933 #define RETURN(token)   return lasttoken = token
12934 static int
12935 xxreadtoken(void)
12936 {
12937         int c;
12938
12939         if (tokpushback) {
12940                 tokpushback = 0;
12941                 return lasttoken;
12942         }
12943         setprompt_if(needprompt, 2);
12944         for (;;) {      /* until token or start of word found */
12945                 c = pgetc_eatbnl();
12946                 switch (c) {
12947                 case ' ': case '\t':
12948                 IF_ASH_ALIAS(case PEOA:)
12949                         continue;
12950                 case '#':
12951                         while ((c = pgetc()) != '\n' && c != PEOF)
12952                                 continue;
12953                         pungetc();
12954                         continue;
12955                 case '\n':
12956                         nlnoprompt();
12957                         RETURN(TNL);
12958                 case PEOF:
12959                         RETURN(TEOF);
12960                 case '&':
12961                         if (pgetc_eatbnl() == '&')
12962                                 RETURN(TAND);
12963                         pungetc();
12964                         RETURN(TBACKGND);
12965                 case '|':
12966                         if (pgetc_eatbnl() == '|')
12967                                 RETURN(TOR);
12968                         pungetc();
12969                         RETURN(TPIPE);
12970                 case ';':
12971                         if (pgetc_eatbnl() == ';')
12972                                 RETURN(TENDCASE);
12973                         pungetc();
12974                         RETURN(TSEMI);
12975                 case '(':
12976                         RETURN(TLP);
12977                 case ')':
12978                         RETURN(TRP);
12979                 }
12980                 break;
12981         }
12982         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12983 #undef RETURN
12984 }
12985 #endif /* old xxreadtoken */
12986
12987 static int
12988 readtoken(void)
12989 {
12990         int t;
12991         int kwd = checkkwd;
12992 #if DEBUG
12993         smallint alreadyseen = tokpushback;
12994 #endif
12995
12996 #if ENABLE_ASH_ALIAS
12997  top:
12998 #endif
12999
13000         t = xxreadtoken();
13001
13002         /*
13003          * eat newlines
13004          */
13005         if (kwd & CHKNL) {
13006                 while (t == TNL) {
13007                         parseheredoc();
13008                         t = xxreadtoken();
13009                 }
13010         }
13011
13012         if (t != TWORD || quoteflag) {
13013                 goto out;
13014         }
13015
13016         /*
13017          * check for keywords
13018          */
13019         if (kwd & CHKKWD) {
13020                 const char *const *pp;
13021
13022                 pp = findkwd(wordtext);
13023                 if (pp) {
13024                         lasttoken = t = pp - tokname_array;
13025                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
13026                         goto out;
13027                 }
13028         }
13029
13030         if (checkkwd & CHKALIAS) {
13031 #if ENABLE_ASH_ALIAS
13032                 struct alias *ap;
13033                 ap = lookupalias(wordtext, 1);
13034                 if (ap != NULL) {
13035                         if (*ap->val) {
13036                                 pushstring(ap->val, ap);
13037                         }
13038                         goto top;
13039                 }
13040 #endif
13041         }
13042  out:
13043         checkkwd = 0;
13044 #if DEBUG
13045         if (!alreadyseen)
13046                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13047         else
13048                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13049 #endif
13050         return t;
13051 }
13052
13053 static int
13054 peektoken(void)
13055 {
13056         int t;
13057
13058         t = readtoken();
13059         tokpushback = 1;
13060         return t;
13061 }
13062
13063 /*
13064  * Read and parse a command.  Returns NODE_EOF on end of file.
13065  * (NULL is a valid parse tree indicating a blank line.)
13066  */
13067 static union node *
13068 parsecmd(int interact)
13069 {
13070         tokpushback = 0;
13071         checkkwd = 0;
13072         heredoclist = 0;
13073         doprompt = interact;
13074         setprompt_if(doprompt, doprompt);
13075         needprompt = 0;
13076         return list(1);
13077 }
13078
13079 /*
13080  * Input any here documents.
13081  */
13082 static void
13083 parseheredoc(void)
13084 {
13085         struct heredoc *here;
13086         union node *n;
13087
13088         here = heredoclist;
13089         heredoclist = NULL;
13090
13091         while (here) {
13092                 tokpushback = 0;
13093                 setprompt_if(needprompt, 2);
13094                 if (here->here->type == NHERE)
13095                         readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
13096                 else
13097                         readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
13098                 n = stzalloc(sizeof(struct narg));
13099                 n->narg.type = NARG;
13100                 /*n->narg.next = NULL; - stzalloc did it */
13101                 n->narg.text = wordtext;
13102                 n->narg.backquote = backquotelist;
13103                 here->here->nhere.doc = n;
13104                 here = here->next;
13105         }
13106 }
13107
13108
13109 static const char *
13110 expandstr(const char *ps, int syntax_type)
13111 {
13112         union node n;
13113         int saveprompt;
13114         struct parsefile *file_stop = g_parsefile;
13115         volatile int saveint;
13116         struct jmploc *volatile savehandler = exception_handler;
13117         struct jmploc jmploc;
13118         const char *volatile result;
13119         int err;
13120
13121         /* XXX Fix (char *) cast. */
13122         setinputstring((char *)ps);
13123
13124         saveprompt = doprompt;
13125         doprompt = 0;
13126         result = ps;
13127
13128         SAVE_INT(saveint);
13129         err = setjmp(jmploc.loc);
13130         if (err)
13131                 goto out;
13132
13133         /* readtoken1() might die horribly.
13134          * Try a prompt with syntactically wrong command:
13135          * PS1='$(date "+%H:%M:%S) > '
13136          */
13137         exception_handler = &jmploc;
13138         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
13139
13140         n.narg.type = NARG;
13141         n.narg.next = NULL;
13142         n.narg.text = wordtext;
13143         n.narg.backquote = backquotelist;
13144
13145         /* expandarg() might fail too:
13146          * PS1='$((123+))'
13147          */
13148         expandarg(&n, NULL, EXP_QUOTED);
13149         result = stackblock();
13150
13151 out:
13152         exception_handler = savehandler;
13153         if (err && exception_type != EXERROR)
13154                 longjmp(exception_handler->loc, 1);
13155         RESTORE_INT(saveint);
13156
13157         doprompt = saveprompt;
13158         /* Try: PS1='`xxx(`' */
13159         unwindfiles(file_stop);
13160
13161         return result;
13162 }
13163
13164 static inline int
13165 parser_eof(void)
13166 {
13167         return tokpushback && lasttoken == TEOF;
13168 }
13169
13170 /*
13171  * Execute a command or commands contained in a string.
13172  */
13173 static int
13174 evalstring(char *s, int flags)
13175 {
13176         struct jmploc *volatile savehandler;
13177         struct jmploc jmploc;
13178         int ex;
13179
13180         union node *n;
13181         struct stackmark smark;
13182         int status;
13183
13184         s = sstrdup(s);
13185         setinputstring(s);
13186         setstackmark(&smark);
13187
13188         status = 0;
13189         /* On exception inside execution loop, we must popfile().
13190          * Try interactively:
13191          *      readonly a=a
13192          *      command eval "a=b"  # throws "is read only" error
13193          * "command BLTIN" is not supposed to abort (even in non-interactive use).
13194          * But if we skip popfile(), we hit EOF in eval's string, and exit.
13195          */
13196         savehandler = exception_handler;
13197         ex = setjmp(jmploc.loc);
13198         if (ex)
13199                 goto out;
13200         exception_handler = &jmploc;
13201
13202         while ((n = parsecmd(0)) != NODE_EOF) {
13203                 int i;
13204
13205                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13206                 if (n)
13207                         status = i;
13208                 popstackmark(&smark);
13209                 if (evalskip)
13210                         break;
13211         }
13212  out:
13213         popstackmark(&smark);
13214         popfile();
13215         stunalloc(s);
13216
13217         exception_handler = savehandler;
13218         if (ex)
13219                 longjmp(exception_handler->loc, ex);
13220
13221         return status;
13222 }
13223
13224 /*
13225  * The eval command.
13226  */
13227 static int FAST_FUNC
13228 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13229 {
13230         char *p;
13231         char *concat;
13232
13233         if (argv[1]) {
13234                 p = argv[1];
13235                 argv += 2;
13236                 if (argv[0]) {
13237                         STARTSTACKSTR(concat);
13238                         for (;;) {
13239                                 concat = stack_putstr(p, concat);
13240                                 p = *argv++;
13241                                 if (p == NULL)
13242                                         break;
13243                                 STPUTC(' ', concat);
13244                         }
13245                         STPUTC('\0', concat);
13246                         p = grabstackstr(concat);
13247                 }
13248                 return evalstring(p, flags & EV_TESTED);
13249         }
13250         return 0;
13251 }
13252
13253 /*
13254  * Read and execute commands.
13255  * "Top" is nonzero for the top level command loop;
13256  * it turns on prompting if the shell is interactive.
13257  */
13258 static int
13259 cmdloop(int top)
13260 {
13261         union node *n;
13262         struct stackmark smark;
13263         int inter;
13264         int status = 0;
13265         int numeof = 0;
13266
13267         TRACE(("cmdloop(%d) called\n", top));
13268         for (;;) {
13269                 int skip;
13270
13271                 setstackmark(&smark);
13272 #if JOBS
13273                 if (doing_jobctl)
13274                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13275 #endif
13276                 inter = 0;
13277                 if (iflag && top) {
13278                         inter++;
13279                         chkmail();
13280                 }
13281                 n = parsecmd(inter);
13282 #if DEBUG
13283                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13284                         showtree(n);
13285 #endif
13286                 if (n == NODE_EOF) {
13287                         if (!top || numeof >= 50)
13288                                 break;
13289                         if (!stoppedjobs()) {
13290                                 if (!Iflag)
13291                                         break;
13292                                 out2str("\nUse \"exit\" to leave shell.\n");
13293                         }
13294                         numeof++;
13295                 } else if (nflag == 0) {
13296                         int i;
13297
13298                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13299                         job_warning >>= 1;
13300                         numeof = 0;
13301                         i = evaltree(n, 0);
13302                         if (n)
13303                                 status = i;
13304                 }
13305                 popstackmark(&smark);
13306                 skip = evalskip;
13307
13308                 if (skip) {
13309                         evalskip &= ~SKIPFUNC;
13310                         break;
13311                 }
13312         }
13313         return status;
13314 }
13315
13316 /*
13317  * Take commands from a file.  To be compatible we should do a path
13318  * search for the file, which is necessary to find sub-commands.
13319  */
13320 static char *
13321 find_dot_file(char *name)
13322 {
13323         char *fullname;
13324         const char *path = pathval();
13325         struct stat statb;
13326
13327         /* don't try this for absolute or relative paths */
13328         if (strchr(name, '/'))
13329                 return name;
13330
13331         while ((fullname = path_advance(&path, name)) != NULL) {
13332                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13333                         /*
13334                          * Don't bother freeing here, since it will
13335                          * be freed by the caller.
13336                          */
13337                         return fullname;
13338                 }
13339                 if (fullname != name)
13340                         stunalloc(fullname);
13341         }
13342         /* not found in PATH */
13343
13344 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13345         return name;
13346 #else
13347         ash_msg_and_raise_error("%s: not found", name);
13348         /* NOTREACHED */
13349 #endif
13350 }
13351
13352 static int FAST_FUNC
13353 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13354 {
13355         /* "false; . empty_file; echo $?" should print 0, not 1: */
13356         int status = 0;
13357         char *fullname;
13358         char **argv;
13359         char *args_need_save;
13360         volatile struct shparam saveparam;
13361
13362 //???
13363 //      struct strlist *sp;
13364 //      for (sp = cmdenviron; sp; sp = sp->next)
13365 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13366
13367         nextopt(nullstr); /* handle possible "--" */
13368         argv = argptr;
13369
13370         if (!argv[0]) {
13371                 /* bash says: "bash: .: filename argument required" */
13372                 return 2; /* bash compat */
13373         }
13374
13375         /* This aborts if file isn't found, which is POSIXly correct.
13376          * bash returns exitcode 1 instead.
13377          */
13378         fullname = find_dot_file(argv[0]);
13379         argv++;
13380         args_need_save = argv[0];
13381         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13382                 int argc;
13383                 saveparam = shellparam;
13384                 shellparam.malloced = 0;
13385                 argc = 1;
13386                 while (argv[argc])
13387                         argc++;
13388                 shellparam.nparam = argc;
13389                 shellparam.p = argv;
13390         };
13391
13392         /* This aborts if file can't be opened, which is POSIXly correct.
13393          * bash returns exitcode 1 instead.
13394          */
13395         setinputfile(fullname, INPUT_PUSH_FILE);
13396         commandname = fullname;
13397         status = cmdloop(0);
13398         popfile();
13399
13400         if (args_need_save) {
13401                 freeparam(&shellparam);
13402                 shellparam = saveparam;
13403         };
13404
13405         return status;
13406 }
13407
13408 static int FAST_FUNC
13409 exitcmd(int argc UNUSED_PARAM, char **argv)
13410 {
13411         if (stoppedjobs())
13412                 return 0;
13413         if (argv[1])
13414                 exitstatus = number(argv[1]);
13415         raise_exception(EXEXIT);
13416         /* NOTREACHED */
13417 }
13418
13419 /*
13420  * Read a file containing shell functions.
13421  */
13422 static void
13423 readcmdfile(char *name)
13424 {
13425         setinputfile(name, INPUT_PUSH_FILE);
13426         cmdloop(0);
13427         popfile();
13428 }
13429
13430
13431 /* ============ find_command inplementation */
13432
13433 /*
13434  * Resolve a command name.  If you change this routine, you may have to
13435  * change the shellexec routine as well.
13436  */
13437 static void
13438 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13439 {
13440         struct tblentry *cmdp;
13441         int idx;
13442         int prev;
13443         char *fullname;
13444         struct stat statb;
13445         int e;
13446         int updatetbl;
13447         struct builtincmd *bcmd;
13448
13449         /* If name contains a slash, don't use PATH or hash table */
13450         if (strchr(name, '/') != NULL) {
13451                 entry->u.index = -1;
13452                 if (act & DO_ABS) {
13453                         while (stat(name, &statb) < 0) {
13454 #ifdef SYSV
13455                                 if (errno == EINTR)
13456                                         continue;
13457 #endif
13458                                 entry->cmdtype = CMDUNKNOWN;
13459                                 return;
13460                         }
13461                 }
13462                 entry->cmdtype = CMDNORMAL;
13463                 return;
13464         }
13465
13466 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13467
13468         updatetbl = (path == pathval());
13469         if (!updatetbl) {
13470                 act |= DO_ALTPATH;
13471                 if (strstr(path, "%builtin") != NULL)
13472                         act |= DO_ALTBLTIN;
13473         }
13474
13475         /* If name is in the table, check answer will be ok */
13476         cmdp = cmdlookup(name, 0);
13477         if (cmdp != NULL) {
13478                 int bit;
13479
13480                 switch (cmdp->cmdtype) {
13481                 default:
13482 #if DEBUG
13483                         abort();
13484 #endif
13485                 case CMDNORMAL:
13486                         bit = DO_ALTPATH;
13487                         break;
13488                 case CMDFUNCTION:
13489                         bit = DO_NOFUNC;
13490                         break;
13491                 case CMDBUILTIN:
13492                         bit = DO_ALTBLTIN;
13493                         break;
13494                 }
13495                 if (act & bit) {
13496                         updatetbl = 0;
13497                         cmdp = NULL;
13498                 } else if (cmdp->rehash == 0)
13499                         /* if not invalidated by cd, we're done */
13500                         goto success;
13501         }
13502
13503         /* If %builtin not in path, check for builtin next */
13504         bcmd = find_builtin(name);
13505         if (bcmd) {
13506                 if (IS_BUILTIN_REGULAR(bcmd))
13507                         goto builtin_success;
13508                 if (act & DO_ALTPATH) {
13509                         if (!(act & DO_ALTBLTIN))
13510                                 goto builtin_success;
13511                 } else if (builtinloc <= 0) {
13512                         goto builtin_success;
13513                 }
13514         }
13515
13516 #if ENABLE_FEATURE_SH_STANDALONE
13517         {
13518                 int applet_no = find_applet_by_name(name);
13519                 if (applet_no >= 0) {
13520                         entry->cmdtype = CMDNORMAL;
13521                         entry->u.index = -2 - applet_no;
13522                         return;
13523                 }
13524         }
13525 #endif
13526
13527         /* We have to search path. */
13528         prev = -1;              /* where to start */
13529         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13530                 if (cmdp->cmdtype == CMDBUILTIN)
13531                         prev = builtinloc;
13532                 else
13533                         prev = cmdp->param.index;
13534         }
13535
13536         e = ENOENT;
13537         idx = -1;
13538  loop:
13539         while ((fullname = path_advance(&path, name)) != NULL) {
13540                 stunalloc(fullname);
13541                 /* NB: code below will still use fullname
13542                  * despite it being "unallocated" */
13543                 idx++;
13544                 if (pathopt) {
13545                         if (prefix(pathopt, "builtin")) {
13546                                 if (bcmd)
13547                                         goto builtin_success;
13548                                 continue;
13549                         }
13550                         if ((act & DO_NOFUNC)
13551                          || !prefix(pathopt, "func")
13552                         ) {     /* ignore unimplemented options */
13553                                 continue;
13554                         }
13555                 }
13556                 /* if rehash, don't redo absolute path names */
13557                 if (fullname[0] == '/' && idx <= prev) {
13558                         if (idx < prev)
13559                                 continue;
13560                         TRACE(("searchexec \"%s\": no change\n", name));
13561                         goto success;
13562                 }
13563                 while (stat(fullname, &statb) < 0) {
13564 #ifdef SYSV
13565                         if (errno == EINTR)
13566                                 continue;
13567 #endif
13568                         if (errno != ENOENT && errno != ENOTDIR)
13569                                 e = errno;
13570                         goto loop;
13571                 }
13572                 e = EACCES;     /* if we fail, this will be the error */
13573                 if (!S_ISREG(statb.st_mode))
13574                         continue;
13575                 if (pathopt) {          /* this is a %func directory */
13576                         stalloc(strlen(fullname) + 1);
13577                         /* NB: stalloc will return space pointed by fullname
13578                          * (because we don't have any intervening allocations
13579                          * between stunalloc above and this stalloc) */
13580                         readcmdfile(fullname);
13581                         cmdp = cmdlookup(name, 0);
13582                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13583                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13584                         stunalloc(fullname);
13585                         goto success;
13586                 }
13587                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13588                 if (!updatetbl) {
13589                         entry->cmdtype = CMDNORMAL;
13590                         entry->u.index = idx;
13591                         return;
13592                 }
13593                 INT_OFF;
13594                 cmdp = cmdlookup(name, 1);
13595                 cmdp->cmdtype = CMDNORMAL;
13596                 cmdp->param.index = idx;
13597                 INT_ON;
13598                 goto success;
13599         }
13600
13601         /* We failed.  If there was an entry for this command, delete it */
13602         if (cmdp && updatetbl)
13603                 delete_cmd_entry();
13604         if (act & DO_ERR) {
13605 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13606                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13607                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13608                         char *argv[3];
13609                         argv[0] = (char*) "command_not_found_handle";
13610                         argv[1] = name;
13611                         argv[2] = NULL;
13612                         evalfun(hookp->param.func, 2, argv, 0);
13613                         entry->cmdtype = CMDUNKNOWN;
13614                         return;
13615                 }
13616 #endif
13617                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13618         }
13619         entry->cmdtype = CMDUNKNOWN;
13620         return;
13621
13622  builtin_success:
13623         if (!updatetbl) {
13624                 entry->cmdtype = CMDBUILTIN;
13625                 entry->u.cmd = bcmd;
13626                 return;
13627         }
13628         INT_OFF;
13629         cmdp = cmdlookup(name, 1);
13630         cmdp->cmdtype = CMDBUILTIN;
13631         cmdp->param.cmd = bcmd;
13632         INT_ON;
13633  success:
13634         cmdp->rehash = 0;
13635         entry->cmdtype = cmdp->cmdtype;
13636         entry->u = cmdp->param;
13637 }
13638
13639
13640 /*
13641  * The trap builtin.
13642  */
13643 static int FAST_FUNC
13644 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13645 {
13646         char *action;
13647         char **ap;
13648         int signo, exitcode;
13649
13650         nextopt(nullstr);
13651         ap = argptr;
13652         if (!*ap) {
13653                 for (signo = 0; signo < NSIG; signo++) {
13654                         char *tr = trap_ptr[signo];
13655                         if (tr) {
13656                                 /* note: bash adds "SIG", but only if invoked
13657                                  * as "bash". If called as "sh", or if set -o posix,
13658                                  * then it prints short signal names.
13659                                  * We are printing short names: */
13660                                 out1fmt("trap -- %s %s\n",
13661                                                 single_quote(tr),
13662                                                 get_signame(signo));
13663                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13664                  * In this case, we will exit very soon, no need to free(). */
13665                                 /* if (trap_ptr != trap && tp[0]) */
13666                                 /*      free(tr); */
13667                         }
13668                 }
13669                 /*
13670                 if (trap_ptr != trap) {
13671                         free(trap_ptr);
13672                         trap_ptr = trap;
13673                 }
13674                 */
13675                 return 0;
13676         }
13677
13678         /* Why the second check?
13679          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13680          * In this case, NUM is signal no, not an action.
13681          */
13682         action = NULL;
13683         if (ap[1] && !is_number(ap[0]))
13684                 action = *ap++;
13685
13686         exitcode = 0;
13687         while (*ap) {
13688                 signo = get_signum(*ap);
13689                 if (signo < 0) {
13690                         /* Mimic bash message exactly */
13691                         ash_msg("%s: invalid signal specification", *ap);
13692                         exitcode = 1;
13693                         goto next;
13694                 }
13695                 INT_OFF;
13696                 if (action) {
13697                         if (LONE_DASH(action))
13698                                 action = NULL;
13699                         else {
13700                                 if (action[0]) /* not NULL and not "" and not "-" */
13701                                         may_have_traps = 1;
13702                                 action = ckstrdup(action);
13703                         }
13704                 }
13705                 free(trap[signo]);
13706                 trap[signo] = action;
13707                 if (signo != 0)
13708                         setsignal(signo);
13709                 INT_ON;
13710  next:
13711                 ap++;
13712         }
13713         return exitcode;
13714 }
13715
13716
13717 /* ============ Builtins */
13718
13719 #if ENABLE_ASH_HELP
13720 static int FAST_FUNC
13721 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13722 {
13723         unsigned col;
13724         unsigned i;
13725
13726         out1fmt(
13727                 "Built-in commands:\n"
13728                 "------------------\n");
13729         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13730                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13731                                         builtintab[i].name + 1);
13732                 if (col > 60) {
13733                         out1fmt("\n");
13734                         col = 0;
13735                 }
13736         }
13737 # if ENABLE_FEATURE_SH_STANDALONE
13738         {
13739                 const char *a = applet_names;
13740                 while (*a) {
13741                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13742                         if (col > 60) {
13743                                 out1fmt("\n");
13744                                 col = 0;
13745                         }
13746                         while (*a++ != '\0')
13747                                 continue;
13748                 }
13749         }
13750 # endif
13751         newline_and_flush(stdout);
13752         return EXIT_SUCCESS;
13753 }
13754 #endif
13755
13756 #if MAX_HISTORY
13757 static int FAST_FUNC
13758 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13759 {
13760         if (line_input_state)
13761                 show_history(line_input_state);
13762         return EXIT_SUCCESS;
13763 }
13764 #endif
13765
13766 /*
13767  * The export and readonly commands.
13768  */
13769 static int FAST_FUNC
13770 exportcmd(int argc UNUSED_PARAM, char **argv)
13771 {
13772         struct var *vp;
13773         char *name;
13774         const char *p;
13775         char **aptr;
13776         char opt;
13777         int flag;
13778         int flag_off;
13779
13780         /* "readonly" in bash accepts, but ignores -n.
13781          * We do the same: it saves a conditional in nextopt's param.
13782          */
13783         flag_off = 0;
13784         while ((opt = nextopt("np")) != '\0') {
13785                 if (opt == 'n')
13786                         flag_off = VEXPORT;
13787         }
13788         flag = VEXPORT;
13789         if (argv[0][0] == 'r') {
13790                 flag = VREADONLY;
13791                 flag_off = 0; /* readonly ignores -n */
13792         }
13793         flag_off = ~flag_off;
13794
13795         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13796         {
13797                 aptr = argptr;
13798                 name = *aptr;
13799                 if (name) {
13800                         do {
13801                                 p = strchr(name, '=');
13802                                 if (p != NULL) {
13803                                         p++;
13804                                 } else {
13805                                         vp = *findvar(hashvar(name), name);
13806                                         if (vp) {
13807                                                 vp->flags = ((vp->flags | flag) & flag_off);
13808                                                 continue;
13809                                         }
13810                                 }
13811                                 setvar(name, p, (flag & flag_off));
13812                         } while ((name = *++aptr) != NULL);
13813                         return 0;
13814                 }
13815         }
13816
13817         /* No arguments. Show the list of exported or readonly vars.
13818          * -n is ignored.
13819          */
13820         showvars(argv[0], flag, 0);
13821         return 0;
13822 }
13823
13824 /*
13825  * Delete a function if it exists.
13826  */
13827 static void
13828 unsetfunc(const char *name)
13829 {
13830         struct tblentry *cmdp;
13831
13832         cmdp = cmdlookup(name, 0);
13833         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13834                 delete_cmd_entry();
13835 }
13836
13837 /*
13838  * The unset builtin command.  We unset the function before we unset the
13839  * variable to allow a function to be unset when there is a readonly variable
13840  * with the same name.
13841  */
13842 static int FAST_FUNC
13843 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13844 {
13845         char **ap;
13846         int i;
13847         int flag = 0;
13848
13849         while ((i = nextopt("vf")) != 0) {
13850                 flag = i;
13851         }
13852
13853         for (ap = argptr; *ap; ap++) {
13854                 if (flag != 'f') {
13855                         unsetvar(*ap);
13856                         continue;
13857                 }
13858                 if (flag != 'v')
13859                         unsetfunc(*ap);
13860         }
13861         return 0;
13862 }
13863
13864 static const unsigned char timescmd_str[] ALIGN1 = {
13865         ' ',  offsetof(struct tms, tms_utime),
13866         '\n', offsetof(struct tms, tms_stime),
13867         ' ',  offsetof(struct tms, tms_cutime),
13868         '\n', offsetof(struct tms, tms_cstime),
13869         0
13870 };
13871 static int FAST_FUNC
13872 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13873 {
13874         unsigned clk_tck;
13875         const unsigned char *p;
13876         struct tms buf;
13877
13878         clk_tck = bb_clk_tck();
13879
13880         times(&buf);
13881         p = timescmd_str;
13882         do {
13883                 unsigned sec, frac;
13884                 unsigned long t;
13885                 t = *(clock_t *)(((char *) &buf) + p[1]);
13886                 sec = t / clk_tck;
13887                 frac = t % clk_tck;
13888                 out1fmt("%um%u.%03us%c",
13889                         sec / 60, sec % 60,
13890                         (frac * 1000) / clk_tck,
13891                         p[0]);
13892                 p += 2;
13893         } while (*p);
13894
13895         return 0;
13896 }
13897
13898 #if ENABLE_FEATURE_SH_MATH
13899 /*
13900  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13901  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13902  *
13903  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13904  */
13905 static int FAST_FUNC
13906 letcmd(int argc UNUSED_PARAM, char **argv)
13907 {
13908         arith_t i;
13909
13910         argv++;
13911         if (!*argv)
13912                 ash_msg_and_raise_error("expression expected");
13913         do {
13914                 i = ash_arith(*argv);
13915         } while (*++argv);
13916
13917         return !i;
13918 }
13919 #endif
13920
13921 /*
13922  * The read builtin. Options:
13923  *      -r              Do not interpret '\' specially
13924  *      -s              Turn off echo (tty only)
13925  *      -n NCHARS       Read NCHARS max
13926  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13927  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13928  *      -u FD           Read from given FD instead of fd 0
13929  *      -d DELIM        End on DELIM char, not newline
13930  * This uses unbuffered input, which may be avoidable in some cases.
13931  * TODO: bash also has:
13932  *      -a ARRAY        Read into array[0],[1],etc
13933  *      -e              Use line editing (tty only)
13934  */
13935 static int FAST_FUNC
13936 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13937 {
13938         struct builtin_read_params params;
13939         const char *r;
13940         int i;
13941
13942         memset(&params, 0, sizeof(params));
13943
13944         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13945                 switch (i) {
13946                 case 'p':
13947                         params.opt_p = optionarg;
13948                         break;
13949                 case 'n':
13950                         params.opt_n = optionarg;
13951                         break;
13952                 case 's':
13953                         params.read_flags |= BUILTIN_READ_SILENT;
13954                         break;
13955                 case 't':
13956                         params.opt_t = optionarg;
13957                         break;
13958                 case 'r':
13959                         params.read_flags |= BUILTIN_READ_RAW;
13960                         break;
13961                 case 'u':
13962                         params.opt_u = optionarg;
13963                         break;
13964 #if BASH_READ_D
13965                 case 'd':
13966                         params.opt_d = optionarg;
13967                         break;
13968 #endif
13969                 default:
13970                         break;
13971                 }
13972         }
13973
13974         params.argv = argptr;
13975         params.setvar = setvar0;
13976         params.ifs = bltinlookup("IFS"); /* can be NULL */
13977
13978         /* "read -s" needs to save/restore termios, can't allow ^C
13979          * to jump out of it.
13980          */
13981  again:
13982         INT_OFF;
13983         r = shell_builtin_read(&params);
13984         INT_ON;
13985
13986         if ((uintptr_t)r == 1 && errno == EINTR) {
13987                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13988                  * Correct behavior is to not exit "read"
13989                  */
13990                 if (pending_sig == 0)
13991                         goto again;
13992         }
13993
13994         if ((uintptr_t)r > 1)
13995                 ash_msg_and_raise_error(r);
13996
13997         return (uintptr_t)r;
13998 }
13999
14000 static int FAST_FUNC
14001 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14002 {
14003         static const char permuser[3] ALIGN1 = "ogu";
14004
14005         mode_t mask;
14006         int symbolic_mode = 0;
14007
14008         while (nextopt("S") != '\0') {
14009                 symbolic_mode = 1;
14010         }
14011
14012         INT_OFF;
14013         mask = umask(0);
14014         umask(mask);
14015         INT_ON;
14016
14017         if (*argptr == NULL) {
14018                 if (symbolic_mode) {
14019                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
14020                         char *p = buf;
14021                         int i;
14022
14023                         i = 2;
14024                         for (;;) {
14025                                 *p++ = ',';
14026                                 *p++ = permuser[i];
14027                                 *p++ = '=';
14028                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
14029                                 if (!(mask & 0400)) *p++ = 'r';
14030                                 if (!(mask & 0200)) *p++ = 'w';
14031                                 if (!(mask & 0100)) *p++ = 'x';
14032                                 mask <<= 3;
14033                                 if (--i < 0)
14034                                         break;
14035                         }
14036                         *p = '\0';
14037                         puts(buf + 1);
14038                 } else {
14039                         out1fmt("%04o\n", mask);
14040                 }
14041         } else {
14042                 char *modestr = *argptr;
14043                 /* numeric umasks are taken as-is */
14044                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
14045                 if (!isdigit(modestr[0]))
14046                         mask ^= 0777;
14047                 mask = bb_parse_mode(modestr, mask);
14048                 if ((unsigned)mask > 0777) {
14049                         ash_msg_and_raise_error("illegal mode: %s", modestr);
14050                 }
14051                 if (!isdigit(modestr[0]))
14052                         mask ^= 0777;
14053                 umask(mask);
14054         }
14055         return 0;
14056 }
14057
14058 static int FAST_FUNC
14059 ulimitcmd(int argc UNUSED_PARAM, char **argv)
14060 {
14061         return shell_builtin_ulimit(argv);
14062 }
14063
14064 /* ============ main() and helpers */
14065
14066 /*
14067  * Called to exit the shell.
14068  */
14069 static void
14070 exitshell(void)
14071 {
14072         struct jmploc loc;
14073         char *p;
14074         int status;
14075
14076 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
14077         if (line_input_state)
14078                 save_history(line_input_state);
14079 #endif
14080         status = exitstatus;
14081         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
14082         if (setjmp(loc.loc)) {
14083                 if (exception_type == EXEXIT)
14084                         status = exitstatus;
14085                 goto out;
14086         }
14087         exception_handler = &loc;
14088         p = trap[0];
14089         if (p) {
14090                 trap[0] = NULL;
14091                 evalskip = 0;
14092                 evalstring(p, 0);
14093                 /*free(p); - we'll exit soon */
14094         }
14095  out:
14096         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
14097          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
14098          */
14099         setjobctl(0);
14100         flush_stdout_stderr();
14101         _exit(status);
14102         /* NOTREACHED */
14103 }
14104
14105 /* Don't inline: conserve stack of caller from having our locals too */
14106 static NOINLINE void
14107 init(void)
14108 {
14109         /* we will never free this */
14110         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
14111         basepf.linno = 1;
14112
14113         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
14114         setsignal(SIGCHLD);
14115
14116         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
14117          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
14118          */
14119         signal(SIGHUP, SIG_DFL);
14120
14121         {
14122                 char **envp;
14123                 const char *p;
14124
14125                 initvar();
14126                 for (envp = environ; envp && *envp; envp++) {
14127 /* Used to have
14128  *                      p = endofname(*envp);
14129  *                      if (p != *envp && *p == '=') {
14130  * here to weed out badly-named variables, but this breaks
14131  * scenarios where people do want them passed to children:
14132  * import os
14133  * os.environ["test-test"]="test"
14134  * if os.fork() == 0:
14135  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
14136  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
14137  */
14138                         if (strchr(*envp, '=')) {
14139                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
14140                         }
14141                 }
14142
14143                 setvareq((char*)defifsvar, VTEXTFIXED);
14144                 setvareq((char*)defoptindvar, VTEXTFIXED);
14145
14146                 setvar0("PPID", utoa(getppid()));
14147 #if BASH_SHLVL_VAR
14148                 p = lookupvar("SHLVL");
14149                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
14150 #endif
14151 #if BASH_HOSTNAME_VAR
14152                 if (!lookupvar("HOSTNAME")) {
14153                         struct utsname uts;
14154                         uname(&uts);
14155                         setvar0("HOSTNAME", uts.nodename);
14156                 }
14157 #endif
14158                 p = lookupvar("PWD");
14159                 if (p) {
14160                         struct stat st1, st2;
14161                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
14162                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
14163                         ) {
14164                                 p = NULL;
14165                         }
14166                 }
14167                 setpwd(p, 0);
14168         }
14169 }
14170
14171
14172 //usage:#define ash_trivial_usage
14173 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
14174 //usage:#define ash_full_usage "\n\n"
14175 //usage:        "Unix shell interpreter"
14176
14177 /*
14178  * Process the shell command line arguments.
14179  */
14180 static int
14181 procargs(char **argv)
14182 {
14183         int i;
14184         const char *xminusc;
14185         char **xargv;
14186         int login_sh;
14187
14188         xargv = argv;
14189         login_sh = xargv[0] && xargv[0][0] == '-';
14190 #if NUM_SCRIPTS > 0
14191         if (minusc)
14192                 goto setarg0;
14193 #endif
14194         arg0 = xargv[0];
14195         /* if (xargv[0]) - mmm, this is always true! */
14196                 xargv++;
14197         argptr = xargv;
14198         for (i = 0; i < NOPTS; i++)
14199                 optlist[i] = 2;
14200         if (options(&login_sh)) {
14201                 /* it already printed err message */
14202                 raise_exception(EXERROR);
14203         }
14204         xargv = argptr;
14205         xminusc = minusc;
14206         if (*xargv == NULL) {
14207                 if (xminusc)
14208                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
14209                 sflag = 1;
14210         }
14211         if (iflag == 2 /* no explicit -i given */
14212          && sflag == 1 /* -s given (or implied) */
14213          && !minusc /* bash compat: ash -sc 'echo $-' is not interactive (dash is) */
14214          && isatty(0) && isatty(1) /* we are on tty */
14215         ) {
14216                 iflag = 1;
14217         }
14218         if (mflag == 2)
14219                 mflag = iflag;
14220         for (i = 0; i < NOPTS; i++)
14221                 if (optlist[i] == 2)
14222                         optlist[i] = 0;
14223 #if DEBUG == 2
14224         debug = 1;
14225 #endif
14226         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14227         if (xminusc) {
14228                 minusc = *xargv++;
14229                 if (*xargv)
14230                         goto setarg0;
14231         } else if (!sflag) {
14232                 setinputfile(*xargv, 0);
14233  setarg0:
14234                 arg0 = *xargv++;
14235                 commandname = arg0;
14236         }
14237
14238         shellparam.p = xargv;
14239 #if ENABLE_ASH_GETOPTS
14240         shellparam.optind = 1;
14241         shellparam.optoff = -1;
14242 #endif
14243         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14244         while (*xargv) {
14245                 shellparam.nparam++;
14246                 xargv++;
14247         }
14248         optschanged();
14249
14250         return login_sh;
14251 }
14252
14253 /*
14254  * Read /etc/profile, ~/.profile, $ENV.
14255  */
14256 static void
14257 read_profile(const char *name)
14258 {
14259         name = expandstr(name, DQSYNTAX);
14260         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14261                 return;
14262         cmdloop(0);
14263         popfile();
14264 }
14265
14266 /*
14267  * This routine is called when an error or an interrupt occurs in an
14268  * interactive shell and control is returned to the main command loop.
14269  * (In dash, this function is auto-generated by build machinery).
14270  */
14271 static void
14272 reset(void)
14273 {
14274         /* from eval.c: */
14275         evalskip = 0;
14276         loopnest = 0;
14277
14278         /* from expand.c: */
14279         ifsfree();
14280
14281         /* from input.c: */
14282         g_parsefile->left_in_buffer = 0;
14283         g_parsefile->left_in_line = 0;      /* clear input buffer */
14284         popallfiles();
14285
14286         /* from redir.c: */
14287         unwindredir(NULL);
14288
14289         /* from var.c: */
14290         unwindlocalvars(NULL);
14291 }
14292
14293 #if PROFILE
14294 static short profile_buf[16384];
14295 extern int etext();
14296 #endif
14297
14298 /*
14299  * Main routine.  We initialize things, parse the arguments, execute
14300  * profiles if we're a login shell, and then call cmdloop to execute
14301  * commands.  The setjmp call sets up the location to jump to when an
14302  * exception occurs.  When an exception occurs the variable "state"
14303  * is used to figure out how far we had gotten.
14304  */
14305 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14306 #if NUM_SCRIPTS > 0
14307 int ash_main(int argc, char **argv)
14308 #else
14309 int ash_main(int argc UNUSED_PARAM, char **argv)
14310 #endif
14311 /* note: 'argc' is used only if embedded scripts are enabled */
14312 {
14313         volatile smallint state;
14314         struct jmploc jmploc;
14315         struct stackmark smark;
14316         int login_sh;
14317
14318         /* Initialize global data */
14319         INIT_G_misc();
14320         INIT_G_memstack();
14321         INIT_G_var();
14322 #if ENABLE_ASH_ALIAS
14323         INIT_G_alias();
14324 #endif
14325         INIT_G_cmdtable();
14326
14327 #if PROFILE
14328         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14329 #endif
14330
14331         state = 0;
14332         if (setjmp(jmploc.loc)) {
14333                 smallint e;
14334                 smallint s;
14335
14336                 reset();
14337
14338                 e = exception_type;
14339                 s = state;
14340                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14341                         exitshell();
14342                 }
14343                 if (e == EXINT) {
14344                         newline_and_flush(stderr);
14345                 }
14346
14347                 popstackmark(&smark);
14348                 FORCE_INT_ON; /* enable interrupts */
14349                 if (s == 1)
14350                         goto state1;
14351                 if (s == 2)
14352                         goto state2;
14353                 if (s == 3)
14354                         goto state3;
14355                 goto state4;
14356         }
14357         exception_handler = &jmploc;
14358         rootpid = getpid();
14359
14360         init();
14361         setstackmark(&smark);
14362
14363 #if NUM_SCRIPTS > 0
14364         if (argc < 0)
14365                 /* Non-NULL minusc tells procargs that an embedded script is being run */
14366                 minusc = get_script_content(-argc - 1);
14367 #endif
14368         login_sh = procargs(argv);
14369 #if DEBUG
14370         TRACE(("Shell args: "));
14371         trace_puts_args(argv);
14372 #endif
14373
14374         if (login_sh) {
14375                 const char *hp;
14376
14377                 state = 1;
14378                 read_profile("/etc/profile");
14379  state1:
14380                 state = 2;
14381                 hp = lookupvar("HOME");
14382                 if (hp)
14383                         read_profile("$HOME/.profile");
14384         }
14385  state2:
14386         state = 3;
14387         if (
14388 #ifndef linux
14389          getuid() == geteuid() && getgid() == getegid() &&
14390 #endif
14391          iflag
14392         ) {
14393                 const char *shinit = lookupvar("ENV");
14394                 if (shinit != NULL && *shinit != '\0')
14395                         read_profile(shinit);
14396         }
14397         popstackmark(&smark);
14398  state3:
14399         state = 4;
14400         if (minusc) {
14401                 /* evalstring pushes parsefile stack.
14402                  * Ensure we don't falsely claim that 0 (stdin)
14403                  * is one of stacked source fds.
14404                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14405
14406                 // if (!sflag) g_parsefile->pf_fd = -1;
14407                 // ^^ not necessary since now we special-case fd 0
14408                 // in save_fd_on_redirect()
14409
14410                 // dash: evalstring(minusc, sflag ? 0 : EV_EXIT);
14411                 // The above makes
14412                 //  ash -sc 'echo $-'
14413                 // continue reading input from stdin after running 'echo'.
14414                 // bash does not do this: it prints "hBcs" and exits.
14415                 evalstring(minusc, EV_EXIT);
14416         }
14417
14418         if (sflag || minusc == NULL) {
14419 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14420                 if (iflag) {
14421                         const char *hp = lookupvar("HISTFILE");
14422                         if (!hp) {
14423                                 hp = lookupvar("HOME");
14424                                 if (hp) {
14425                                         INT_OFF;
14426                                         hp = concat_path_file(hp, ".ash_history");
14427                                         setvar0("HISTFILE", hp);
14428                                         free((char*)hp);
14429                                         INT_ON;
14430                                         hp = lookupvar("HISTFILE");
14431                                 }
14432                         }
14433                         if (hp)
14434                                 line_input_state->hist_file = hp;
14435 # if ENABLE_FEATURE_SH_HISTFILESIZE
14436                         hp = lookupvar("HISTFILESIZE");
14437                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14438 # endif
14439                 }
14440 #endif
14441  state4: /* XXX ??? - why isn't this before the "if" statement */
14442                 cmdloop(1);
14443         }
14444 #if PROFILE
14445         monitor(0);
14446 #endif
14447 #ifdef GPROF
14448         {
14449                 extern void _mcleanup(void);
14450                 _mcleanup();
14451         }
14452 #endif
14453         TRACE(("End of main reached\n"));
14454         exitshell();
14455         /* NOTREACHED */
14456 }
14457
14458
14459 /*-
14460  * Copyright (c) 1989, 1991, 1993, 1994
14461  *      The Regents of the University of California.  All rights reserved.
14462  *
14463  * This code is derived from software contributed to Berkeley by
14464  * Kenneth Almquist.
14465  *
14466  * Redistribution and use in source and binary forms, with or without
14467  * modification, are permitted provided that the following conditions
14468  * are met:
14469  * 1. Redistributions of source code must retain the above copyright
14470  *    notice, this list of conditions and the following disclaimer.
14471  * 2. Redistributions in binary form must reproduce the above copyright
14472  *    notice, this list of conditions and the following disclaimer in the
14473  *    documentation and/or other materials provided with the distribution.
14474  * 3. Neither the name of the University nor the names of its contributors
14475  *    may be used to endorse or promote products derived from this software
14476  *    without specific prior written permission.
14477  *
14478  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14479  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14480  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14481  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14482  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14483  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14484  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14485  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14486  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14487  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14488  * SUCH DAMAGE.
14489  */