78ca1d99c19be50e1ecb16eeb7683c967d72a674
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (78 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_BASH_SOURCE_CURDIR
55 //config:       bool "'source' and '.' builtins search current directory after $PATH"
56 //config:       default n   # do not encourage non-standard behavior
57 //config:       depends on ASH_BASH_COMPAT
58 //config:       help
59 //config:       This is not compliant with standards. Avoid if possible.
60 //config:
61 //config:config ASH_BASH_NOT_FOUND_HOOK
62 //config:       bool "command_not_found_handle hook support"
63 //config:       default y
64 //config:       depends on ASH_BASH_COMPAT
65 //config:       help
66 //config:       Enable support for the 'command_not_found_handle' hook function,
67 //config:       from GNU bash, which allows for alternative command not found
68 //config:       handling.
69 //config:
70 //config:config ASH_JOB_CONTROL
71 //config:       bool "Job control"
72 //config:       default y
73 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
74 //config:
75 //config:config ASH_ALIAS
76 //config:       bool "Alias support"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:
80 //config:config ASH_RANDOM_SUPPORT
81 //config:       bool "Pseudorandom generator and $RANDOM variable"
82 //config:       default y
83 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
84 //config:       help
85 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
86 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
87 //config:       You can reset the generator by using a specified start value.
88 //config:       After "unset RANDOM" the generator will switch off and this
89 //config:       variable will no longer have special treatment.
90 //config:
91 //config:config ASH_EXPAND_PRMT
92 //config:       bool "Expand prompt string"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       $PS# may contain volatile content, such as backquote commands.
97 //config:       This option recreates the prompt string from the environment
98 //config:       variable each time it is displayed.
99 //config:
100 //config:config ASH_IDLE_TIMEOUT
101 //config:       bool "Idle timeout variable $TMOUT"
102 //config:       default y
103 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
104 //config:       help
105 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
106 //config:
107 //config:config ASH_MAIL
108 //config:       bool "Check for new mail in interactive shell"
109 //config:       default y
110 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
111 //config:       help
112 //config:       Enable "check for new mail" function:
113 //config:       if set, $MAIL file and $MAILPATH list of files
114 //config:       are checked for mtime changes, and "you have mail"
115 //config:       message is printed if change is detected.
116 //config:
117 //config:config ASH_ECHO
118 //config:       bool "echo builtin"
119 //config:       default y
120 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
121 //config:
122 //config:config ASH_PRINTF
123 //config:       bool "printf builtin"
124 //config:       default y
125 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
126 //config:
127 //config:config ASH_TEST
128 //config:       bool "test builtin"
129 //config:       default y
130 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
131 //config:
132 //config:config ASH_HELP
133 //config:       bool "help builtin"
134 //config:       default y
135 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
136 //config:
137 //config:config ASH_GETOPTS
138 //config:       bool "getopts builtin"
139 //config:       default y
140 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
141 //config:
142 //config:config ASH_CMDCMD
143 //config:       bool "command builtin"
144 //config:       default y
145 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
146 //config:       help
147 //config:       Enable support for the 'command' builtin, which allows
148 //config:       you to run the specified command or builtin,
149 //config:       even when there is a function with the same name.
150 //config:
151 //config:endif # ash options
152
153 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
154 //                      APPLET_ODDNAME:name  main location    suid_type     help
155 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
156 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
157
158 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
159 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
160 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
161 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
162
163 /*
164  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
165  * DEBUG=2 to compile in and turn on debugging.
166  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
167  * debugging info is written to ./trace, quit signal generates core dump.
168  */
169 #define DEBUG 0
170 /* Tweak debug output verbosity here */
171 #define DEBUG_TIME 0
172 #define DEBUG_PID 1
173 #define DEBUG_SIG 1
174 #define DEBUG_INTONOFF 0
175
176 #define PROFILE 0
177
178 #define JOBS ENABLE_ASH_JOB_CONTROL
179
180 #include <fnmatch.h>
181 #include <sys/times.h>
182 #include <sys/utsname.h> /* for setting $HOSTNAME */
183 #include "busybox.h" /* for applet_names */
184 #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
185 # include "embedded_scripts.h"
186 #else
187 # define NUM_SCRIPTS 0
188 #endif
189
190 /* So far, all bash compat is controlled by one config option */
191 /* Separate defines document which part of code implements what */
192 /* function keyword */
193 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
194 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
195 /* &>file */
196 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
197 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
198 /* $'...' */
199 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
200 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
201 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
202 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
203 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
204 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
205 /* BASH_TEST2: [[ EXPR ]]
206  * Status of [[ support:
207  * We replace && and || with -a and -o
208  * TODO:
209  * singleword+noglob expansion:
210  *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
211  *   [[ /bin/n* ]]; echo 0:$?
212  * -a/-o are not AND/OR ops! (they are just strings)
213  * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
214  * = is glob match operator, not equality operator: STR = GLOB
215  * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
216  * == same as =
217  * add =~ regex match operator: STR =~ REGEX
218  */
219 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
220 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
221 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
222 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
223 #define    BASH_EPOCH_VARS      ENABLE_ASH_BASH_COMPAT
224 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
225 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
226 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
227 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
228 #define    BASH_WAIT_N          ENABLE_ASH_BASH_COMPAT
229
230 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
231 /* Bionic at least up to version 24 has no glob() */
232 # undef  ENABLE_ASH_INTERNAL_GLOB
233 # define ENABLE_ASH_INTERNAL_GLOB 1
234 #endif
235
236 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
237 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
238 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
239 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
240 # error glob() should unbackslash them and match. uClibc does not unbackslash,
241 # error fails to match dirname, subsequently not expanding <pattern> in it.
242 // Testcase:
243 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
244 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
245 #endif
246
247 #if !ENABLE_ASH_INTERNAL_GLOB
248 # include <glob.h>
249 #endif
250
251 #include "unicode.h"
252 #include "shell_common.h"
253 #if ENABLE_FEATURE_SH_MATH
254 # include "math.h"
255 #else
256 typedef long arith_t;
257 # define ARITH_FMT "%ld"
258 #endif
259 #if ENABLE_ASH_RANDOM_SUPPORT
260 # include "random.h"
261 #else
262 # define CLEAR_RANDOM_T(rnd) ((void)0)
263 #endif
264
265 #include "NUM_APPLETS.h"
266 #if NUM_APPLETS == 1
267 /* STANDALONE does not make sense, and won't compile */
268 # undef CONFIG_FEATURE_SH_STANDALONE
269 # undef ENABLE_FEATURE_SH_STANDALONE
270 # undef IF_FEATURE_SH_STANDALONE
271 # undef IF_NOT_FEATURE_SH_STANDALONE
272 # define ENABLE_FEATURE_SH_STANDALONE 0
273 # define IF_FEATURE_SH_STANDALONE(...)
274 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
275 #endif
276
277 #ifndef F_DUPFD_CLOEXEC
278 # define F_DUPFD_CLOEXEC F_DUPFD
279 #endif
280 #ifndef O_CLOEXEC
281 # define O_CLOEXEC 0
282 #endif
283 #ifndef PIPE_BUF
284 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
285 #endif
286
287 #if !BB_MMU
288 # error "Do not even bother, ash will not run on NOMMU machine"
289 #endif
290
291 /* We use a trick to have more optimized code (fewer pointer reloads):
292  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
293  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
294  * This way, compiler in ash.c knows the pointer can not change.
295  *
296  * However, this may break on weird arches or toolchains. In this case,
297  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
298  * this optimization.
299  */
300 #ifndef BB_GLOBAL_CONST
301 # define BB_GLOBAL_CONST const
302 #endif
303
304
305 /* ============ Hash table sizes. Configurable. */
306
307 #define VTABSIZE 39
308 #define ATABSIZE 39
309 #define CMDTABLESIZE 31         /* should be prime */
310
311
312 /* ============ Shell options */
313
314 static const char *const optletters_optnames[] = {
315         "e"   "errexit",
316         "f"   "noglob",
317         "I"   "ignoreeof",
318 /* The below allowed this invocation:
319  * ash -c 'set -i; echo $-; sleep 5; echo $-'
320  * to be ^C-ed and get to interactive ash prompt.
321  * bash does not support such "set -i".
322  * In our code, this is denoted by empty long name:
323  */
324         "i"   "",
325         "m"   "monitor",
326         "n"   "noexec",
327 /* Ditto: bash has no "set -s" */
328         "s"   "",
329         "c"   "",
330         "x"   "xtrace",
331         "v"   "verbose",
332         "C"   "noclobber",
333         "a"   "allexport",
334         "b"   "notify",
335         "u"   "nounset",
336         "\0"  "vi"
337 #if BASH_PIPEFAIL
338         ,"\0"  "pipefail"
339 #endif
340 #if DEBUG
341         ,"\0"  "nolog"
342         ,"\0"  "debug"
343 #endif
344 };
345 //bash 4.4.23 also has these opts (with these defaults):
346 //braceexpand           on
347 //emacs                 on
348 //errtrace              off
349 //functrace             off
350 //hashall               on
351 //histexpand            off
352 //history               on
353 //interactive-comments  on
354 //keyword               off
355 //onecmd                off
356 //physical              off
357 //posix                 off
358 //privileged            off
359
360 #define optletters(n)  optletters_optnames[n][0]
361 #define optnames(n)   (optletters_optnames[n] + 1)
362
363 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
364
365
366 /* ============ Misc data */
367
368 #define msg_illnum "Illegal number: %s"
369
370 /*
371  * We enclose jmp_buf in a structure so that we can declare pointers to
372  * jump locations.  The global variable handler contains the location to
373  * jump to when an exception occurs, and the global variable exception_type
374  * contains a code identifying the exception.  To implement nested
375  * exception handlers, the user should save the value of handler on entry
376  * to an inner scope, set handler to point to a jmploc structure for the
377  * inner scope, and restore handler on exit from the scope.
378  */
379 struct jmploc {
380         jmp_buf loc;
381 };
382
383 struct globals_misc {
384         uint8_t exitstatus;     /* exit status of last command */
385         uint8_t back_exitstatus;/* exit status of backquoted command */
386         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
387         int savestatus;         /* exit status of last command outside traps */
388         int rootpid;            /* pid of main shell */
389         /* shell level: 0 for the main shell, 1 for its children, and so on */
390         int shlvl;
391 #define rootshell (!shlvl)
392         int errlinno;
393
394         char *minusc;  /* argument to -c option */
395
396         char *curdir; // = nullstr;     /* current working directory */
397         char *physdir; // = nullstr;    /* physical working directory */
398
399         char *arg0; /* value of $0 */
400
401         struct jmploc *exception_handler;
402
403         volatile int suppress_int; /* counter */
404         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
405         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
406         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
407         smallint exception_type; /* kind of exception (0..5) */
408         /* exceptions */
409 #define EXINT 0         /* SIGINT received */
410 #define EXERROR 1       /* a generic error */
411 #define EXEXIT 4        /* exit the shell */
412
413         char nullstr[1];        /* zero length string */
414
415         char optlist[NOPTS];
416 #define eflag optlist[0]
417 #define fflag optlist[1]
418 #define Iflag optlist[2]
419 #define iflag optlist[3]
420 #define mflag optlist[4]
421 #define nflag optlist[5]
422 #define sflag optlist[6]
423 #define cflag optlist[7]
424 #define xflag optlist[8]
425 #define vflag optlist[9]
426 #define Cflag optlist[10]
427 #define aflag optlist[11]
428 #define bflag optlist[12]
429 #define uflag optlist[13]
430 #define viflag optlist[14]
431 #if BASH_PIPEFAIL
432 # define pipefail optlist[15]
433 #else
434 # define pipefail 0
435 #endif
436 #if DEBUG
437 # define nolog optlist[15 + BASH_PIPEFAIL]
438 # define debug optlist[16 + BASH_PIPEFAIL]
439 #endif
440
441         /* trap handler commands */
442         /*
443          * Sigmode records the current value of the signal handlers for the various
444          * modes.  A value of zero means that the current handler is not known.
445          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
446          */
447         char sigmode[NSIG - 1];
448 #define S_DFL      1            /* default signal handling (SIG_DFL) */
449 #define S_CATCH    2            /* signal is caught */
450 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
451 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
452
453         /* indicates specified signal received */
454         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
455         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
456         char *trap[NSIG];
457         char **trap_ptr;        /* used only by "trap hack" */
458
459         /* Rarely referenced stuff */
460 #if ENABLE_ASH_RANDOM_SUPPORT
461         random_t random_gen;
462 #endif
463         pid_t backgndpid;        /* pid of last background process */
464 };
465 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
466 #define G_misc (*ash_ptr_to_globals_misc)
467 #define exitstatus        (G_misc.exitstatus )
468 #define back_exitstatus   (G_misc.back_exitstatus )
469 #define job_warning       (G_misc.job_warning)
470 #define savestatus  (G_misc.savestatus )
471 #define rootpid     (G_misc.rootpid    )
472 #define shlvl       (G_misc.shlvl      )
473 #define errlinno    (G_misc.errlinno   )
474 #define minusc      (G_misc.minusc     )
475 #define curdir      (G_misc.curdir     )
476 #define physdir     (G_misc.physdir    )
477 #define arg0        (G_misc.arg0       )
478 #define exception_handler (G_misc.exception_handler)
479 #define exception_type    (G_misc.exception_type   )
480 #define suppress_int      (G_misc.suppress_int     )
481 #define pending_int       (G_misc.pending_int      )
482 #define got_sigchld       (G_misc.got_sigchld      )
483 #define pending_sig       (G_misc.pending_sig      )
484 #define nullstr     (G_misc.nullstr    )
485 #define optlist     (G_misc.optlist    )
486 #define sigmode     (G_misc.sigmode    )
487 #define gotsig      (G_misc.gotsig     )
488 #define may_have_traps    (G_misc.may_have_traps   )
489 #define trap        (G_misc.trap       )
490 #define trap_ptr    (G_misc.trap_ptr   )
491 #define random_gen  (G_misc.random_gen )
492 #define backgndpid  (G_misc.backgndpid )
493 #define INIT_G_misc() do { \
494         (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \
495         barrier(); \
496         savestatus = -1; \
497         curdir = nullstr; \
498         physdir = nullstr; \
499         trap_ptr = trap; \
500 } while (0)
501
502
503 /* ============ DEBUG */
504 #if DEBUG
505 static void trace_printf(const char *fmt, ...);
506 static void trace_vprintf(const char *fmt, va_list va);
507 # define TRACE(param)    trace_printf param
508 # define TRACEV(param)   trace_vprintf param
509 # define close(fd) do { \
510         int dfd = (fd); \
511         if (close(dfd) < 0) \
512                 bb_error_msg("bug on %d: closing %d(0x%x)", \
513                         __LINE__, dfd, dfd); \
514 } while (0)
515 #else
516 # define TRACE(param)
517 # define TRACEV(param)
518 #endif
519
520
521 /* ============ Utility functions */
522 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
523 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
524
525 static int
526 isdigit_str9(const char *str)
527 {
528         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
529         while (--maxlen && isdigit(*str))
530                 str++;
531         return (*str == '\0');
532 }
533
534 static const char *
535 var_end(const char *var)
536 {
537         while (*var)
538                 if (*var++ == '=')
539                         break;
540         return var;
541 }
542
543
544 /* ============ Interrupts / exceptions */
545
546 static void exitshell(void) NORETURN;
547
548 /*
549  * These macros allow the user to suspend the handling of interrupt signals
550  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
551  * much more efficient and portable.  (But hacking the kernel is so much
552  * more fun than worrying about efficiency and portability. :-))
553  */
554 #if DEBUG_INTONOFF
555 # define INT_OFF do { \
556         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
557         suppress_int++; \
558         barrier(); \
559 } while (0)
560 #else
561 # define INT_OFF do { \
562         suppress_int++; \
563         barrier(); \
564 } while (0)
565 #endif
566
567 /*
568  * Called to raise an exception.  Since C doesn't include exceptions, we
569  * just do a longjmp to the exception handler.  The type of exception is
570  * stored in the global variable "exception_type".
571  */
572 static void raise_exception(int) NORETURN;
573 static void
574 raise_exception(int e)
575 {
576 #if DEBUG
577         if (exception_handler == NULL)
578                 abort();
579 #endif
580         INT_OFF;
581         exception_type = e;
582         longjmp(exception_handler->loc, 1);
583 }
584 #if DEBUG
585 #define raise_exception(e) do { \
586         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
587         raise_exception(e); \
588 } while (0)
589 #endif
590
591 /*
592  * Called when a SIGINT is received.  (If the user specifies
593  * that SIGINT is to be trapped or ignored using the trap builtin, then
594  * this routine is not called.)  Suppressint is nonzero when interrupts
595  * are held using the INT_OFF macro.  (The test for iflag is just
596  * defensive programming.)
597  */
598 static void raise_interrupt(void) NORETURN;
599 static void
600 raise_interrupt(void)
601 {
602         pending_int = 0;
603         /* Signal is not automatically unmasked after it is raised,
604          * do it ourself - unmask all signals */
605         sigprocmask_allsigs(SIG_UNBLOCK);
606         /* pending_sig = 0; - now done in signal_handler() */
607
608         if (!(rootshell && iflag)) {
609                 /* Kill ourself with SIGINT */
610                 signal(SIGINT, SIG_DFL);
611                 raise(SIGINT);
612         }
613         /* bash: ^C even on empty command line sets $? */
614         exitstatus = SIGINT + 128;
615         raise_exception(EXINT);
616         /* NOTREACHED */
617 }
618 #if DEBUG
619 #define raise_interrupt() do { \
620         TRACE(("raising interrupt on line %d\n", __LINE__)); \
621         raise_interrupt(); \
622 } while (0)
623 #endif
624
625 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
626 int_on(void)
627 {
628         barrier();
629         if (--suppress_int == 0 && pending_int) {
630                 raise_interrupt();
631         }
632 }
633 #if DEBUG_INTONOFF
634 # define INT_ON do { \
635         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
636         int_on(); \
637 } while (0)
638 #else
639 # define INT_ON int_on()
640 #endif
641 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
642 force_int_on(void)
643 {
644         barrier();
645         suppress_int = 0;
646         if (pending_int)
647                 raise_interrupt();
648 }
649 #define FORCE_INT_ON force_int_on()
650
651 #define SAVE_INT(v) ((v) = suppress_int)
652
653 #define RESTORE_INT(v) do { \
654         barrier(); \
655         suppress_int = (v); \
656         if (suppress_int == 0 && pending_int) \
657                 raise_interrupt(); \
658 } while (0)
659
660
661 /* ============ Stdout/stderr output */
662
663 static void
664 outstr(const char *p, FILE *file)
665 {
666         INT_OFF;
667         fputs(p, file);
668         INT_ON;
669 }
670
671 static void
672 flush_stdout_stderr(void)
673 {
674         INT_OFF;
675         fflush_all();
676         INT_ON;
677 }
678
679 /* Was called outcslow(c,FILE*), but c was always '\n' */
680 static void
681 newline_and_flush(FILE *dest)
682 {
683         INT_OFF;
684         putc('\n', dest);
685         fflush(dest);
686         INT_ON;
687 }
688
689 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
690 static int
691 out1fmt(const char *fmt, ...)
692 {
693         va_list ap;
694         int r;
695
696         INT_OFF;
697         va_start(ap, fmt);
698         r = vprintf(fmt, ap);
699         va_end(ap);
700         INT_ON;
701         return r;
702 }
703
704 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
705 static int
706 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
707 {
708         va_list ap;
709         int ret;
710
711         INT_OFF;
712         va_start(ap, fmt);
713         ret = vsnprintf(outbuf, length, fmt, ap);
714         va_end(ap);
715         INT_ON;
716         return ret > (int)length ? length : ret;
717 }
718
719 static void
720 out1str(const char *p)
721 {
722         outstr(p, stdout);
723 }
724
725 static void
726 out2str(const char *p)
727 {
728         outstr(p, stderr);
729         flush_stdout_stderr();
730 }
731
732
733 /* ============ Parser structures */
734
735 /* control characters in argument strings */
736 #define CTL_FIRST CTLESC
737 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
738 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
739 #define CTLENDVAR    ((unsigned char)'\203')
740 #define CTLBACKQ     ((unsigned char)'\204')
741 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
742 #define CTLENDARI    ((unsigned char)'\207')
743 #define CTLQUOTEMARK ((unsigned char)'\210')
744 #define CTL_LAST CTLQUOTEMARK
745
746 /* variable substitution byte (follows CTLVAR) */
747 #define VSTYPE  0x0f            /* type of variable substitution */
748 #define VSNUL   0x10            /* colon--treat the empty string as unset */
749
750 /* values of VSTYPE field */
751 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
752 #define VSMINUS         0x2     /* ${var-text} */
753 #define VSPLUS          0x3     /* ${var+text} */
754 #define VSQUESTION      0x4     /* ${var?message} */
755 #define VSASSIGN        0x5     /* ${var=text} */
756 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
757 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
758 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
759 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
760 #define VSLENGTH        0xa     /* ${#var} */
761 #if BASH_SUBSTR
762 #define VSSUBSTR        0xc     /* ${var:position:length} */
763 #endif
764 #if BASH_PATTERN_SUBST
765 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
766 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
767 #endif
768
769 static const char dolatstr[] ALIGN1 = {
770         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
771 };
772 #define DOLATSTRLEN 6
773
774 #define NCMD      0
775 #define NPIPE     1
776 #define NREDIR    2
777 #define NBACKGND  3
778 #define NSUBSHELL 4
779 #define NAND      5
780 #define NOR       6
781 #define NSEMI     7
782 #define NIF       8
783 #define NWHILE    9
784 #define NUNTIL   10
785 #define NFOR     11
786 #define NCASE    12
787 #define NCLIST   13
788 #define NDEFUN   14
789 #define NARG     15
790 #define NTO      16
791 #if BASH_REDIR_OUTPUT
792 #define NTO2     17
793 #endif
794 #define NCLOBBER 18
795 #define NFROM    19
796 #define NFROMTO  20
797 #define NAPPEND  21
798 #define NTOFD    22
799 #define NFROMFD  23
800 #define NHERE    24
801 #define NXHERE   25
802 #define NNOT     26
803 #define N_NUMBER 27
804
805 union node;
806
807 struct ncmd {
808         smallint type; /* Nxxxx */
809         int linno;
810         union node *assign;
811         union node *args;
812         union node *redirect;
813 };
814
815 struct npipe {
816         smallint type;
817         smallint pipe_backgnd;
818         struct nodelist *cmdlist;
819 };
820
821 struct nredir {
822         smallint type;
823         int linno;
824         union node *n;
825         union node *redirect;
826 };
827
828 struct nbinary {
829         smallint type;
830         union node *ch1;
831         union node *ch2;
832 };
833
834 struct nif {
835         smallint type;
836         union node *test;
837         union node *ifpart;
838         union node *elsepart;
839 };
840
841 struct nfor {
842         smallint type;
843         int linno;
844         union node *args;
845         union node *body;
846         char *var;
847 };
848
849 struct ncase {
850         smallint type;
851         int linno;
852         union node *expr;
853         union node *cases;
854 };
855
856 struct nclist {
857         smallint type;
858         union node *next;
859         union node *pattern;
860         union node *body;
861 };
862
863 struct ndefun {
864         smallint type;
865         int linno;
866         char *text;
867         union node *body;
868 };
869
870 struct narg {
871         smallint type;
872         union node *next;
873         char *text;
874         struct nodelist *backquote;
875 };
876
877 /* nfile and ndup layout must match!
878  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
879  * that it is actually NTO2 (>&file), and change its type.
880  */
881 struct nfile {
882         smallint type;
883         union node *next;
884         int fd;
885         int _unused_dupfd;
886         union node *fname;
887         char *expfname;
888 };
889
890 struct ndup {
891         smallint type;
892         union node *next;
893         int fd;
894         int dupfd;
895         union node *vname;
896         char *_unused_expfname;
897 };
898
899 struct nhere {
900         smallint type;
901         union node *next;
902         int fd;
903         union node *doc;
904 };
905
906 struct nnot {
907         smallint type;
908         union node *com;
909 };
910
911 union node {
912         smallint type;
913         struct ncmd ncmd;
914         struct npipe npipe;
915         struct nredir nredir;
916         struct nbinary nbinary;
917         struct nif nif;
918         struct nfor nfor;
919         struct ncase ncase;
920         struct nclist nclist;
921         struct ndefun ndefun;
922         struct narg narg;
923         struct nfile nfile;
924         struct ndup ndup;
925         struct nhere nhere;
926         struct nnot nnot;
927 };
928
929 /*
930  * NODE_EOF is returned by parsecmd when it encounters an end of file.
931  * It must be distinct from NULL.
932  */
933 #define NODE_EOF ((union node *) -1L)
934
935 struct nodelist {
936         struct nodelist *next;
937         union node *n;
938 };
939
940 struct funcnode {
941         int count;
942         union node n;
943 };
944
945 /*
946  * Free a parse tree.
947  */
948 static void
949 freefunc(struct funcnode *f)
950 {
951         if (f && --f->count < 0)
952                 free(f);
953 }
954
955
956 /* ============ Debugging output */
957
958 #if DEBUG
959
960 static FILE *tracefile;
961
962 static void
963 trace_printf(const char *fmt, ...)
964 {
965         va_list va;
966
967         if (debug != 1)
968                 return;
969         if (DEBUG_TIME)
970                 fprintf(tracefile, "%u ", (int) time(NULL));
971         if (DEBUG_PID)
972                 fprintf(tracefile, "[%u] ", (int) getpid());
973         if (DEBUG_SIG)
974                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
975         va_start(va, fmt);
976         vfprintf(tracefile, fmt, va);
977         va_end(va);
978 }
979
980 static void
981 trace_vprintf(const char *fmt, va_list va)
982 {
983         if (debug != 1)
984                 return;
985         vfprintf(tracefile, fmt, va);
986         fprintf(tracefile, "\n");
987 }
988
989 static void
990 trace_puts(const char *s)
991 {
992         if (debug != 1)
993                 return;
994         fputs(s, tracefile);
995 }
996
997 static void
998 trace_puts_quoted(char *s)
999 {
1000         char *p;
1001         char c;
1002
1003         if (debug != 1)
1004                 return;
1005         putc('"', tracefile);
1006         for (p = s; *p; p++) {
1007                 switch ((unsigned char)*p) {
1008                 case '\n': c = 'n'; goto backslash;
1009                 case '\t': c = 't'; goto backslash;
1010                 case '\r': c = 'r'; goto backslash;
1011                 case '\"': c = '\"'; goto backslash;
1012                 case '\\': c = '\\'; goto backslash;
1013                 case CTLESC: c = 'e'; goto backslash;
1014                 case CTLVAR: c = 'v'; goto backslash;
1015                 case CTLBACKQ: c = 'q'; goto backslash;
1016  backslash:
1017                         putc('\\', tracefile);
1018                         putc(c, tracefile);
1019                         break;
1020                 default:
1021                         if (*p >= ' ' && *p <= '~')
1022                                 putc(*p, tracefile);
1023                         else {
1024                                 putc('\\', tracefile);
1025                                 putc((*p >> 6) & 03, tracefile);
1026                                 putc((*p >> 3) & 07, tracefile);
1027                                 putc(*p & 07, tracefile);
1028                         }
1029                         break;
1030                 }
1031         }
1032         putc('"', tracefile);
1033 }
1034
1035 static void
1036 trace_puts_args(char **ap)
1037 {
1038         if (debug != 1)
1039                 return;
1040         if (!*ap)
1041                 return;
1042         while (1) {
1043                 trace_puts_quoted(*ap);
1044                 if (!*++ap) {
1045                         putc('\n', tracefile);
1046                         break;
1047                 }
1048                 putc(' ', tracefile);
1049         }
1050 }
1051
1052 static void
1053 opentrace(void)
1054 {
1055         char s[100];
1056 #ifdef O_APPEND
1057         int flags;
1058 #endif
1059
1060         if (debug != 1) {
1061                 if (tracefile)
1062                         fflush(tracefile);
1063                 /* leave open because libedit might be using it */
1064                 return;
1065         }
1066         strcpy(s, "./trace");
1067         if (tracefile) {
1068                 if (!freopen(s, "a", tracefile)) {
1069                         fprintf(stderr, "Can't re-open %s\n", s);
1070                         debug = 0;
1071                         return;
1072                 }
1073         } else {
1074                 tracefile = fopen(s, "a");
1075                 if (tracefile == NULL) {
1076                         fprintf(stderr, "Can't open %s\n", s);
1077                         debug = 0;
1078                         return;
1079                 }
1080         }
1081 #ifdef O_APPEND
1082         flags = fcntl(fileno(tracefile), F_GETFL);
1083         if (flags >= 0)
1084                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1085 #endif
1086         setlinebuf(tracefile);
1087         fputs("\nTracing started.\n", tracefile);
1088 }
1089
1090 static void
1091 indent(int amount, char *pfx, FILE *fp)
1092 {
1093         int i;
1094
1095         for (i = 0; i < amount; i++) {
1096                 if (pfx && i == amount - 1)
1097                         fputs(pfx, fp);
1098                 putc('\t', fp);
1099         }
1100 }
1101
1102 /* little circular references here... */
1103 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1104
1105 static void
1106 sharg(union node *arg, FILE *fp)
1107 {
1108         char *p;
1109         struct nodelist *bqlist;
1110         unsigned char subtype;
1111
1112         if (arg->type != NARG) {
1113                 out1fmt("<node type %d>\n", arg->type);
1114                 abort();
1115         }
1116         bqlist = arg->narg.backquote;
1117         for (p = arg->narg.text; *p; p++) {
1118                 switch ((unsigned char)*p) {
1119                 case CTLESC:
1120                         p++;
1121                         putc(*p, fp);
1122                         break;
1123                 case CTLVAR:
1124                         putc('$', fp);
1125                         putc('{', fp);
1126                         subtype = *++p;
1127                         if (subtype == VSLENGTH)
1128                                 putc('#', fp);
1129
1130                         while (*p != '=') {
1131                                 putc(*p, fp);
1132                                 p++;
1133                         }
1134
1135                         if (subtype & VSNUL)
1136                                 putc(':', fp);
1137
1138                         switch (subtype & VSTYPE) {
1139                         case VSNORMAL:
1140                                 putc('}', fp);
1141                                 break;
1142                         case VSMINUS:
1143                                 putc('-', fp);
1144                                 break;
1145                         case VSPLUS:
1146                                 putc('+', fp);
1147                                 break;
1148                         case VSQUESTION:
1149                                 putc('?', fp);
1150                                 break;
1151                         case VSASSIGN:
1152                                 putc('=', fp);
1153                                 break;
1154                         case VSTRIMLEFT:
1155                                 putc('#', fp);
1156                                 break;
1157                         case VSTRIMLEFTMAX:
1158                                 putc('#', fp);
1159                                 putc('#', fp);
1160                                 break;
1161                         case VSTRIMRIGHT:
1162                                 putc('%', fp);
1163                                 break;
1164                         case VSTRIMRIGHTMAX:
1165                                 putc('%', fp);
1166                                 putc('%', fp);
1167                                 break;
1168                         case VSLENGTH:
1169                                 break;
1170                         default:
1171                                 out1fmt("<subtype %d>", subtype);
1172                         }
1173                         break;
1174                 case CTLENDVAR:
1175                         putc('}', fp);
1176                         break;
1177                 case CTLBACKQ:
1178                         putc('$', fp);
1179                         putc('(', fp);
1180                         shtree(bqlist->n, -1, NULL, fp);
1181                         putc(')', fp);
1182                         break;
1183                 default:
1184                         putc(*p, fp);
1185                         break;
1186                 }
1187         }
1188 }
1189
1190 static void
1191 shcmd(union node *cmd, FILE *fp)
1192 {
1193         union node *np;
1194         int first;
1195         const char *s;
1196         int dftfd;
1197
1198         first = 1;
1199         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1200                 if (!first)
1201                         putc(' ', fp);
1202                 sharg(np, fp);
1203                 first = 0;
1204         }
1205         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1206                 if (!first)
1207                         putc(' ', fp);
1208                 dftfd = 0;
1209                 switch (np->nfile.type) {
1210                 case NTO:      s = ">>"+1; dftfd = 1; break;
1211                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1212                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1213 #if BASH_REDIR_OUTPUT
1214                 case NTO2:
1215 #endif
1216                 case NTOFD:    s = ">&"; dftfd = 1; break;
1217                 case NFROM:    s = "<"; break;
1218                 case NFROMFD:  s = "<&"; break;
1219                 case NFROMTO:  s = "<>"; break;
1220                 default:       s = "*error*"; break;
1221                 }
1222                 if (np->nfile.fd != dftfd)
1223                         fprintf(fp, "%d", np->nfile.fd);
1224                 fputs(s, fp);
1225                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1226                         fprintf(fp, "%d", np->ndup.dupfd);
1227                 } else {
1228                         sharg(np->nfile.fname, fp);
1229                 }
1230                 first = 0;
1231         }
1232 }
1233
1234 static void
1235 shtree(union node *n, int ind, char *pfx, FILE *fp)
1236 {
1237         struct nodelist *lp;
1238         const char *s;
1239
1240         if (n == NULL)
1241                 return;
1242
1243         indent(ind, pfx, fp);
1244
1245         if (n == NODE_EOF) {
1246                 fputs("<EOF>", fp);
1247                 return;
1248         }
1249
1250         switch (n->type) {
1251         case NSEMI:
1252                 s = "; ";
1253                 goto binop;
1254         case NAND:
1255                 s = " && ";
1256                 goto binop;
1257         case NOR:
1258                 s = " || ";
1259  binop:
1260                 shtree(n->nbinary.ch1, ind, NULL, fp);
1261                 /* if (ind < 0) */
1262                         fputs(s, fp);
1263                 shtree(n->nbinary.ch2, ind, NULL, fp);
1264                 break;
1265         case NCMD:
1266                 shcmd(n, fp);
1267                 if (ind >= 0)
1268                         putc('\n', fp);
1269                 break;
1270         case NPIPE:
1271                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1272                         shtree(lp->n, 0, NULL, fp);
1273                         if (lp->next)
1274                                 fputs(" | ", fp);
1275                 }
1276                 if (n->npipe.pipe_backgnd)
1277                         fputs(" &", fp);
1278                 if (ind >= 0)
1279                         putc('\n', fp);
1280                 break;
1281         default:
1282                 fprintf(fp, "<node type %d>", n->type);
1283                 if (ind >= 0)
1284                         putc('\n', fp);
1285                 break;
1286         }
1287 }
1288
1289 static void
1290 showtree(union node *n)
1291 {
1292         trace_puts("showtree called\n");
1293         shtree(n, 1, NULL, stderr);
1294 }
1295
1296 #endif /* DEBUG */
1297
1298
1299 /* ============ Parser data */
1300
1301 /*
1302  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1303  */
1304 struct strlist {
1305         struct strlist *next;
1306         char *text;
1307 };
1308
1309 struct alias;
1310
1311 struct strpush {
1312         struct strpush *prev;   /* preceding string on stack */
1313         char *prev_string;
1314         int prev_left_in_line;
1315 #if ENABLE_ASH_ALIAS
1316         struct alias *ap;       /* if push was associated with an alias */
1317 #endif
1318         char *string;           /* remember the string since it may change */
1319
1320         /* Remember last two characters for pungetc. */
1321         int lastc[2];
1322
1323         /* Number of outstanding calls to pungetc. */
1324         int unget;
1325 };
1326
1327 /*
1328  * The parsefile structure pointed to by the global variable parsefile
1329  * contains information about the current file being read.
1330  */
1331 struct parsefile {
1332         struct parsefile *prev; /* preceding file on stack */
1333         int linno;              /* current line */
1334         int pf_fd;              /* file descriptor (or -1 if string) */
1335         int left_in_line;       /* number of chars left in this line */
1336         int left_in_buffer;     /* number of chars left in this buffer past the line */
1337         char *next_to_pgetc;    /* next char in buffer */
1338         char *buf;              /* input buffer */
1339         struct strpush *strpush; /* for pushing strings at this level */
1340         struct strpush basestrpush; /* so pushing one is fast */
1341
1342         /* Remember last two characters for pungetc. */
1343         int lastc[2];
1344
1345         /* Number of outstanding calls to pungetc. */
1346         int unget;
1347 };
1348
1349 static struct parsefile basepf;        /* top level input file */
1350 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1351 static char *commandname;              /* currently executing command */
1352
1353
1354 /* ============ Message printing */
1355
1356 static void
1357 ash_vmsg(const char *msg, va_list ap)
1358 {
1359         fprintf(stderr, "%s: ", arg0);
1360         if (commandname) {
1361                 if (strcmp(arg0, commandname))
1362                         fprintf(stderr, "%s: ", commandname);
1363                 if (!iflag || g_parsefile->pf_fd > 0)
1364                         fprintf(stderr, "line %d: ", errlinno);
1365         }
1366         vfprintf(stderr, msg, ap);
1367         newline_and_flush(stderr);
1368 }
1369
1370 /*
1371  * Exverror is called to raise the error exception.  If the second argument
1372  * is not NULL then error prints an error message using printf style
1373  * formatting.  It then raises the error exception.
1374  */
1375 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1376 static void
1377 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1378 {
1379 #if DEBUG
1380         if (msg) {
1381                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1382                 TRACEV((msg, ap));
1383         } else
1384                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1385         if (msg)
1386 #endif
1387                 ash_vmsg(msg, ap);
1388
1389         flush_stdout_stderr();
1390         raise_exception(cond);
1391         /* NOTREACHED */
1392 }
1393
1394 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1395 static void
1396 ash_msg_and_raise_error(const char *msg, ...)
1397 {
1398         va_list ap;
1399
1400         exitstatus = 2;
1401
1402         va_start(ap, msg);
1403         ash_vmsg_and_raise(EXERROR, msg, ap);
1404         /* NOTREACHED */
1405         va_end(ap);
1406 }
1407
1408 /*
1409  * 'fmt' must be a string literal.
1410  */
1411 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1412
1413 static void raise_error_syntax(const char *) NORETURN;
1414 static void
1415 raise_error_syntax(const char *msg)
1416 {
1417         errlinno = g_parsefile->linno;
1418         ash_msg_and_raise_error("syntax error: %s", msg);
1419         /* NOTREACHED */
1420 }
1421
1422 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1423 static void
1424 ash_msg_and_raise(int cond, const char *msg, ...)
1425 {
1426         va_list ap;
1427
1428         va_start(ap, msg);
1429         ash_vmsg_and_raise(cond, msg, ap);
1430         /* NOTREACHED */
1431         va_end(ap);
1432 }
1433
1434 /*
1435  * error/warning routines for external builtins
1436  */
1437 static void
1438 ash_msg(const char *fmt, ...)
1439 {
1440         va_list ap;
1441
1442         va_start(ap, fmt);
1443         ash_vmsg(fmt, ap);
1444         va_end(ap);
1445 }
1446
1447 /*
1448  * Return a string describing an error.  The returned string may be a
1449  * pointer to a static buffer that will be overwritten on the next call.
1450  * Action describes the operation that got the error.
1451  */
1452 static const char *
1453 errmsg(int e, const char *em)
1454 {
1455         if (e == ENOENT || e == ENOTDIR) {
1456                 return em;
1457         }
1458         return strerror(e);
1459 }
1460
1461
1462 /* ============ Memory allocation */
1463
1464 #if 0
1465 /* I consider these wrappers nearly useless:
1466  * ok, they return you to nearest exception handler, but
1467  * how much memory do you leak in the process, making
1468  * memory starvation worse?
1469  */
1470 static void *
1471 ckrealloc(void * p, size_t nbytes)
1472 {
1473         p = realloc(p, nbytes);
1474         if (!p)
1475                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1476         return p;
1477 }
1478
1479 static void *
1480 ckmalloc(size_t nbytes)
1481 {
1482         return ckrealloc(NULL, nbytes);
1483 }
1484
1485 static void *
1486 ckzalloc(size_t nbytes)
1487 {
1488         return memset(ckmalloc(nbytes), 0, nbytes);
1489 }
1490
1491 static char *
1492 ckstrdup(const char *s)
1493 {
1494         char *p = strdup(s);
1495         if (!p)
1496                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1497         return p;
1498 }
1499 #else
1500 /* Using bbox equivalents. They exit if out of memory */
1501 # define ckrealloc xrealloc
1502 # define ckmalloc  xmalloc
1503 # define ckzalloc  xzalloc
1504 # define ckstrdup  xstrdup
1505 #endif
1506
1507 /*
1508  * It appears that grabstackstr() will barf with such alignments
1509  * because stalloc() will return a string allocated in a new stackblock.
1510  */
1511 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1512 enum {
1513         /* Most machines require the value returned from malloc to be aligned
1514          * in some way.  The following macro will get this right
1515          * on many machines.  */
1516         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1517         /* Minimum size of a block */
1518         MINSIZE = SHELL_ALIGN(504),
1519 };
1520
1521 struct stack_block {
1522         struct stack_block *prev;
1523         char space[MINSIZE];
1524 };
1525
1526 struct stackmark {
1527         struct stack_block *stackp;
1528         char *stacknxt;
1529         size_t stacknleft;
1530 };
1531
1532
1533 struct globals_memstack {
1534         struct stack_block *g_stackp; // = &stackbase;
1535         char *g_stacknxt; // = stackbase.space;
1536         char *sstrend; // = stackbase.space + MINSIZE;
1537         size_t g_stacknleft; // = MINSIZE;
1538         struct stack_block stackbase;
1539 };
1540 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1541 #define G_memstack (*ash_ptr_to_globals_memstack)
1542 #define g_stackp     (G_memstack.g_stackp    )
1543 #define g_stacknxt   (G_memstack.g_stacknxt  )
1544 #define sstrend      (G_memstack.sstrend     )
1545 #define g_stacknleft (G_memstack.g_stacknleft)
1546 #define stackbase    (G_memstack.stackbase   )
1547 #define INIT_G_memstack() do { \
1548         (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \
1549         barrier(); \
1550         g_stackp = &stackbase; \
1551         g_stacknxt = stackbase.space; \
1552         g_stacknleft = MINSIZE; \
1553         sstrend = stackbase.space + MINSIZE; \
1554 } while (0)
1555
1556
1557 #define stackblock()     ((void *)g_stacknxt)
1558 #define stackblocksize() g_stacknleft
1559
1560 /*
1561  * Parse trees for commands are allocated in lifo order, so we use a stack
1562  * to make this more efficient, and also to avoid all sorts of exception
1563  * handling code to handle interrupts in the middle of a parse.
1564  *
1565  * The size 504 was chosen because the Ultrix malloc handles that size
1566  * well.
1567  */
1568 static void *
1569 stalloc(size_t nbytes)
1570 {
1571         char *p;
1572         size_t aligned;
1573
1574         aligned = SHELL_ALIGN(nbytes);
1575         if (aligned > g_stacknleft) {
1576                 size_t len;
1577                 size_t blocksize;
1578                 struct stack_block *sp;
1579
1580                 blocksize = aligned;
1581                 if (blocksize < MINSIZE)
1582                         blocksize = MINSIZE;
1583                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1584                 if (len < blocksize)
1585                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1586                 INT_OFF;
1587                 sp = ckmalloc(len);
1588                 sp->prev = g_stackp;
1589                 g_stacknxt = sp->space;
1590                 g_stacknleft = blocksize;
1591                 sstrend = g_stacknxt + blocksize;
1592                 g_stackp = sp;
1593                 INT_ON;
1594         }
1595         p = g_stacknxt;
1596         g_stacknxt += aligned;
1597         g_stacknleft -= aligned;
1598         return p;
1599 }
1600
1601 static void *
1602 stzalloc(size_t nbytes)
1603 {
1604         return memset(stalloc(nbytes), 0, nbytes);
1605 }
1606
1607 static void
1608 stunalloc(void *p)
1609 {
1610 #if DEBUG
1611         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1612                 write(STDERR_FILENO, "stunalloc\n", 10);
1613                 abort();
1614         }
1615 #endif
1616         g_stacknleft += g_stacknxt - (char *)p;
1617         g_stacknxt = p;
1618 }
1619
1620 /*
1621  * Like strdup but works with the ash stack.
1622  */
1623 static char *
1624 sstrdup(const char *p)
1625 {
1626         size_t len = strlen(p) + 1;
1627         return memcpy(stalloc(len), p, len);
1628 }
1629
1630 static ALWAYS_INLINE void
1631 grabstackblock(size_t len)
1632 {
1633         stalloc(len);
1634 }
1635
1636 static void
1637 pushstackmark(struct stackmark *mark, size_t len)
1638 {
1639         mark->stackp = g_stackp;
1640         mark->stacknxt = g_stacknxt;
1641         mark->stacknleft = g_stacknleft;
1642         grabstackblock(len);
1643 }
1644
1645 static void
1646 setstackmark(struct stackmark *mark)
1647 {
1648         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1649 }
1650
1651 static void
1652 popstackmark(struct stackmark *mark)
1653 {
1654         struct stack_block *sp;
1655
1656         if (!mark->stackp)
1657                 return;
1658
1659         INT_OFF;
1660         while (g_stackp != mark->stackp) {
1661                 sp = g_stackp;
1662                 g_stackp = sp->prev;
1663                 free(sp);
1664         }
1665         g_stacknxt = mark->stacknxt;
1666         g_stacknleft = mark->stacknleft;
1667         sstrend = mark->stacknxt + mark->stacknleft;
1668         INT_ON;
1669 }
1670
1671 /*
1672  * When the parser reads in a string, it wants to stick the string on the
1673  * stack and only adjust the stack pointer when it knows how big the
1674  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1675  * of space on top of the stack and stackblocklen returns the length of
1676  * this block.  Growstackblock will grow this space by at least one byte,
1677  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1678  * part of the block that has been used.
1679  */
1680 static void
1681 growstackblock(void)
1682 {
1683         size_t newlen;
1684
1685         newlen = g_stacknleft * 2;
1686         if (newlen < g_stacknleft)
1687                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1688         if (newlen < 128)
1689                 newlen += 128;
1690
1691         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1692                 struct stack_block *sp;
1693                 struct stack_block *prevstackp;
1694                 size_t grosslen;
1695
1696                 INT_OFF;
1697                 sp = g_stackp;
1698                 prevstackp = sp->prev;
1699                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1700                 sp = ckrealloc(sp, grosslen);
1701                 sp->prev = prevstackp;
1702                 g_stackp = sp;
1703                 g_stacknxt = sp->space;
1704                 g_stacknleft = newlen;
1705                 sstrend = sp->space + newlen;
1706                 INT_ON;
1707         } else {
1708                 char *oldspace = g_stacknxt;
1709                 size_t oldlen = g_stacknleft;
1710                 char *p = stalloc(newlen);
1711
1712                 /* free the space we just allocated */
1713                 g_stacknxt = memcpy(p, oldspace, oldlen);
1714                 g_stacknleft += newlen;
1715         }
1716 }
1717
1718 /*
1719  * The following routines are somewhat easier to use than the above.
1720  * The user declares a variable of type STACKSTR, which may be declared
1721  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1722  * the user uses the macro STPUTC to add characters to the string.  In
1723  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1724  * grown as necessary.  When the user is done, she can just leave the
1725  * string there and refer to it using stackblock().  Or she can allocate
1726  * the space for it using grabstackstr().  If it is necessary to allow
1727  * someone else to use the stack temporarily and then continue to grow
1728  * the string, the user should use grabstack to allocate the space, and
1729  * then call ungrabstr(p) to return to the previous mode of operation.
1730  *
1731  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1732  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1733  * is space for at least one character.
1734  */
1735 static void *
1736 growstackstr(void)
1737 {
1738         size_t len = stackblocksize();
1739         growstackblock();
1740         return (char *)stackblock() + len;
1741 }
1742
1743 /*
1744  * Called from CHECKSTRSPACE.
1745  */
1746 static char *
1747 makestrspace(size_t newlen, char *p)
1748 {
1749         size_t len = p - g_stacknxt;
1750         size_t size;
1751
1752         for (;;) {
1753                 size_t nleft;
1754
1755                 size = stackblocksize();
1756                 nleft = size - len;
1757                 if (nleft >= newlen)
1758                         break;
1759                 growstackblock();
1760         }
1761         return (char *)stackblock() + len;
1762 }
1763
1764 static char *
1765 stack_nputstr(const char *s, size_t n, char *p)
1766 {
1767         p = makestrspace(n, p);
1768         p = (char *)mempcpy(p, s, n);
1769         return p;
1770 }
1771
1772 static char *
1773 stack_putstr(const char *s, char *p)
1774 {
1775         return stack_nputstr(s, strlen(s), p);
1776 }
1777
1778 static char *
1779 _STPUTC(int c, char *p)
1780 {
1781         if (p == sstrend)
1782                 p = growstackstr();
1783         *p++ = c;
1784         return p;
1785 }
1786
1787 #define STARTSTACKSTR(p)        ((p) = stackblock())
1788 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1789 #define CHECKSTRSPACE(n, p) do { \
1790         char *q = (p); \
1791         size_t l = (n); \
1792         size_t m = sstrend - q; \
1793         if (l > m) \
1794                 (p) = makestrspace(l, q); \
1795 } while (0)
1796 #define USTPUTC(c, p)           (*(p)++ = (c))
1797 #define STACKSTRNUL(p) do { \
1798         if ((p) == sstrend) \
1799                 (p) = growstackstr(); \
1800         *(p) = '\0'; \
1801 } while (0)
1802 #define STUNPUTC(p)             (--(p))
1803 #define STTOPC(p)               ((p)[-1])
1804 #define STADJUST(amount, p)     ((p) += (amount))
1805
1806 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1807 #define ungrabstackstr(s, p)    stunalloc(s)
1808 #define stackstrend()           ((void *)sstrend)
1809
1810
1811 /* ============ String helpers */
1812
1813 /*
1814  * prefix -- see if pfx is a prefix of string.
1815  */
1816 static char *
1817 prefix(const char *string, const char *pfx)
1818 {
1819         while (*pfx) {
1820                 if (*pfx++ != *string++)
1821                         return NULL;
1822         }
1823         return (char *) string;
1824 }
1825
1826 /*
1827  * Check for a valid number.  This should be elsewhere.
1828  */
1829 static int
1830 is_number(const char *p)
1831 {
1832         do {
1833                 if (!isdigit(*p))
1834                         return 0;
1835         } while (*++p != '\0');
1836         return 1;
1837 }
1838
1839 /*
1840  * Convert a string of digits to an integer, printing an error message on
1841  * failure.
1842  */
1843 static int
1844 number(const char *s)
1845 {
1846         if (!is_number(s))
1847                 ash_msg_and_raise_error(msg_illnum, s);
1848         return atoi(s);
1849 }
1850
1851 /*
1852  * Produce a single quoted string suitable as input to the shell.
1853  * The return string is allocated on the stack.
1854  */
1855 static char *
1856 single_quote(const char *s)
1857 {
1858         char *p;
1859
1860         STARTSTACKSTR(p);
1861
1862         do {
1863                 char *q;
1864                 size_t len;
1865
1866                 len = strchrnul(s, '\'') - s;
1867
1868                 q = p = makestrspace(len + 3, p);
1869
1870                 *q++ = '\'';
1871                 q = (char *)mempcpy(q, s, len);
1872                 *q++ = '\'';
1873                 s += len;
1874
1875                 STADJUST(q - p, p);
1876
1877                 if (*s != '\'')
1878                         break;
1879                 len = 0;
1880                 do len++; while (*++s == '\'');
1881
1882                 q = p = makestrspace(len + 3, p);
1883
1884                 *q++ = '"';
1885                 q = (char *)mempcpy(q, s - len, len);
1886                 *q++ = '"';
1887
1888                 STADJUST(q - p, p);
1889         } while (*s);
1890
1891         USTPUTC('\0', p);
1892
1893         return stackblock();
1894 }
1895
1896 /*
1897  * Produce a possibly single quoted string suitable as input to the shell.
1898  * If quoting was done, the return string is allocated on the stack,
1899  * otherwise a pointer to the original string is returned.
1900  */
1901 static const char *
1902 maybe_single_quote(const char *s)
1903 {
1904         const char *p = s;
1905
1906         while (*p) {
1907                 /* Assuming ACSII */
1908                 /* quote ctrl_chars space !"#$%&'()* */
1909                 if (*p < '+')
1910                         goto need_quoting;
1911                 /* quote ;<=>? */
1912                 if (*p >= ';' && *p <= '?')
1913                         goto need_quoting;
1914                 /* quote `[\ */
1915                 if (*p == '`')
1916                         goto need_quoting;
1917                 if (*p == '[')
1918                         goto need_quoting;
1919                 if (*p == '\\')
1920                         goto need_quoting;
1921                 /* quote {|}~ DEL and high bytes */
1922                 if (*p > 'z')
1923                         goto need_quoting;
1924                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1925                 /* TODO: maybe avoid quoting % */
1926                 p++;
1927         }
1928         return s;
1929
1930  need_quoting:
1931         return single_quote(s);
1932 }
1933
1934
1935 /* ============ nextopt */
1936
1937 static char **argptr;                  /* argument list for builtin commands */
1938 static char *optionarg;                /* set by nextopt (like getopt) */
1939 static char *optptr;                   /* used by nextopt */
1940
1941 /*
1942  * XXX - should get rid of. Have all builtins use getopt(3).
1943  * The library getopt must have the BSD extension static variable
1944  * "optreset", otherwise it can't be used within the shell safely.
1945  *
1946  * Standard option processing (a la getopt) for builtin routines.
1947  * The only argument that is passed to nextopt is the option string;
1948  * the other arguments are unnecessary. It returns the character,
1949  * or '\0' on end of input.
1950  */
1951 static int
1952 nextopt(const char *optstring)
1953 {
1954         char *p;
1955         const char *q;
1956         char c;
1957
1958         p = optptr;
1959         if (p == NULL || *p == '\0') {
1960                 /* We ate entire "-param", take next one */
1961                 p = *argptr;
1962                 if (p == NULL)
1963                         return '\0';
1964                 if (*p != '-')
1965                         return '\0';
1966                 if (*++p == '\0') /* just "-" ? */
1967                         return '\0';
1968                 argptr++;
1969                 if (LONE_DASH(p)) /* "--" ? */
1970                         return '\0';
1971                 /* p => next "-param" */
1972         }
1973         /* p => some option char in the middle of a "-param" */
1974         c = *p++;
1975         for (q = optstring; *q != c;) {
1976                 if (*q == '\0')
1977                         ash_msg_and_raise_error("illegal option -%c", c);
1978                 if (*++q == ':')
1979                         q++;
1980         }
1981         if (*++q == ':') {
1982                 if (*p == '\0') {
1983                         p = *argptr++;
1984                         if (p == NULL)
1985                                 ash_msg_and_raise_error("no arg for -%c option", c);
1986                 }
1987                 optionarg = p;
1988                 p = NULL;
1989         }
1990         optptr = p;
1991         return c;
1992 }
1993
1994
1995 /* ============ Shell variables */
1996
1997 struct shparam {
1998         int nparam;             /* # of positional parameters (without $0) */
1999 #if ENABLE_ASH_GETOPTS
2000         int optind;             /* next parameter to be processed by getopts */
2001         int optoff;             /* used by getopts */
2002 #endif
2003         unsigned char malloced; /* if parameter list dynamically allocated */
2004         char **p;               /* parameter list */
2005 };
2006
2007 /*
2008  * Free the list of positional parameters.
2009  */
2010 static void
2011 freeparam(volatile struct shparam *param)
2012 {
2013         if (param->malloced) {
2014                 char **ap, **ap1;
2015                 ap = ap1 = param->p;
2016                 while (*ap)
2017                         free(*ap++);
2018                 free(ap1);
2019         }
2020 }
2021
2022 #if ENABLE_ASH_GETOPTS
2023 static void FAST_FUNC getoptsreset(const char *value);
2024 #endif
2025
2026 struct var {
2027         struct var *next;               /* next entry in hash list */
2028         int flags;                      /* flags are defined above */
2029         const char *var_text;           /* name=value */
2030         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
2031                                         /* the variable gets set/unset */
2032 };
2033
2034 struct localvar {
2035         struct localvar *next;          /* next local variable in list */
2036         struct var *vp;                 /* the variable that was made local */
2037         int flags;                      /* saved flags */
2038         const char *text;               /* saved text */
2039 };
2040
2041 /* flags */
2042 #define VEXPORT         0x01    /* variable is exported */
2043 #define VREADONLY       0x02    /* variable cannot be modified */
2044 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
2045 #define VTEXTFIXED      0x08    /* text is statically allocated */
2046 #define VSTACK          0x10    /* text is allocated on the stack */
2047 #define VUNSET          0x20    /* the variable is not set */
2048 #define VNOFUNC         0x40    /* don't call the callback function */
2049 #define VNOSET          0x80    /* do not set variable - just readonly test */
2050 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2051 #if ENABLE_ASH_RANDOM_SUPPORT
2052 # define VDYNAMIC       0x200   /* dynamic variable */
2053 #else
2054 # define VDYNAMIC       0
2055 #endif
2056
2057
2058 /* Need to be before varinit_data[] */
2059 #if ENABLE_LOCALE_SUPPORT
2060 static void FAST_FUNC
2061 change_lc_all(const char *value)
2062 {
2063         if (value && *value != '\0')
2064                 setlocale(LC_ALL, value);
2065 }
2066 static void FAST_FUNC
2067 change_lc_ctype(const char *value)
2068 {
2069         if (value && *value != '\0')
2070                 setlocale(LC_CTYPE, value);
2071 }
2072 #endif
2073 #if ENABLE_ASH_MAIL
2074 static void chkmail(void);
2075 static void changemail(const char *var_value) FAST_FUNC;
2076 #else
2077 # define chkmail()  ((void)0)
2078 #endif
2079 static void changepath(const char *) FAST_FUNC;
2080 #if ENABLE_ASH_RANDOM_SUPPORT
2081 static void change_random(const char *) FAST_FUNC;
2082 #endif
2083 #if BASH_EPOCH_VARS
2084 static void change_seconds(const char *) FAST_FUNC;
2085 static void change_realtime(const char *) FAST_FUNC;
2086 #endif
2087
2088 static const struct {
2089         int flags;
2090         const char *var_text;
2091         void (*var_func)(const char *) FAST_FUNC;
2092 } varinit_data[] = {
2093         /*
2094          * Note: VEXPORT would not work correctly here for NOFORK applets:
2095          * some environment strings may be constant.
2096          */
2097         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2098 #if ENABLE_ASH_MAIL
2099         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2100         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2101 #endif
2102         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2103         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2104         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2105         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2106 #if ENABLE_ASH_GETOPTS
2107         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2108 #endif
2109         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2110 #if ENABLE_ASH_RANDOM_SUPPORT
2111         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2112 #endif
2113 #if BASH_EPOCH_VARS
2114         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHSECONDS", change_seconds },
2115         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHREALTIME", change_realtime },
2116 #endif
2117 #if ENABLE_LOCALE_SUPPORT
2118         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2119         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2120 #endif
2121 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2122         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2123 #endif
2124 };
2125
2126 struct redirtab;
2127
2128 struct globals_var {
2129         struct shparam shellparam;      /* $@ current positional parameters */
2130         struct redirtab *redirlist;
2131         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2132         struct var *vartab[VTABSIZE];
2133         struct var varinit[ARRAY_SIZE(varinit_data)];
2134         int lineno;
2135         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2136 };
2137 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2138 #define G_var (*ash_ptr_to_globals_var)
2139 #define shellparam    (G_var.shellparam   )
2140 //#define redirlist     (G_var.redirlist    )
2141 #define preverrout_fd (G_var.preverrout_fd)
2142 #define vartab        (G_var.vartab       )
2143 #define varinit       (G_var.varinit      )
2144 #define lineno        (G_var.lineno       )
2145 #define linenovar     (G_var.linenovar    )
2146 #define vifs      varinit[0]
2147 #if ENABLE_ASH_MAIL
2148 # define vmail    varinit[1]
2149 # define vmpath   varinit[2]
2150 #endif
2151 #define VAR_OFFSET1 (ENABLE_ASH_MAIL*2)
2152 #define vpath     varinit[VAR_OFFSET1 + 1]
2153 #define vps1      varinit[VAR_OFFSET1 + 2]
2154 #define vps2      varinit[VAR_OFFSET1 + 3]
2155 #define vps4      varinit[VAR_OFFSET1 + 4]
2156 #if ENABLE_ASH_GETOPTS
2157 # define voptind  varinit[VAR_OFFSET1 + 5]
2158 #endif
2159 #define VAR_OFFSET2 (VAR_OFFSET1 + ENABLE_ASH_GETOPTS)
2160 #define vlineno   varinit[VAR_OFFSET2 + 5]
2161 #if ENABLE_ASH_RANDOM_SUPPORT
2162 # define vrandom  varinit[VAR_OFFSET2 + 6]
2163 #endif
2164 #define VAR_OFFSET3 (VAR_OFFSET2 + ENABLE_ASH_RANDOM_SUPPORT)
2165 #if BASH_EPOCH_VARS
2166 # define vepochs  varinit[VAR_OFFSET3 + 6]
2167 # define vepochr  varinit[VAR_OFFSET3 + 7]
2168 #endif
2169 #define INIT_G_var() do { \
2170         unsigned i; \
2171         (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \
2172         barrier(); \
2173         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2174                 varinit[i].flags    = varinit_data[i].flags; \
2175                 varinit[i].var_text = varinit_data[i].var_text; \
2176                 varinit[i].var_func = varinit_data[i].var_func; \
2177         } \
2178         strcpy(linenovar, "LINENO="); \
2179         vlineno.var_text = linenovar; \
2180 } while (0)
2181
2182 /*
2183  * The following macros access the values of the above variables.
2184  * They have to skip over the name.  They return the null string
2185  * for unset variables.
2186  */
2187 #define ifsval()        (vifs.var_text + 4)
2188 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2189 #if ENABLE_ASH_MAIL
2190 # define mailval()      (vmail.var_text + 5)
2191 # define mpathval()     (vmpath.var_text + 9)
2192 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2193 #endif
2194 #define pathval()       (vpath.var_text + 5)
2195 #define ps1val()        (vps1.var_text + 4)
2196 #define ps2val()        (vps2.var_text + 4)
2197 #define ps4val()        (vps4.var_text + 4)
2198 #if ENABLE_ASH_GETOPTS
2199 # define optindval()    (voptind.var_text + 7)
2200 #endif
2201
2202 #if ENABLE_ASH_GETOPTS
2203 static void FAST_FUNC
2204 getoptsreset(const char *value)
2205 {
2206         shellparam.optind = 1;
2207         if (is_number(value))
2208                 shellparam.optind = number(value) ?: 1;
2209         shellparam.optoff = -1;
2210 }
2211 #endif
2212
2213 /*
2214  * Compares two strings up to the first = or '\0'.  The first
2215  * string must be terminated by '='; the second may be terminated by
2216  * either '=' or '\0'.
2217  */
2218 static int
2219 varcmp(const char *p, const char *q)
2220 {
2221         int c, d;
2222
2223         while ((c = *p) == (d = *q)) {
2224                 if (c == '\0' || c == '=')
2225                         goto out;
2226                 p++;
2227                 q++;
2228         }
2229         if (c == '=')
2230                 c = '\0';
2231         if (d == '=')
2232                 d = '\0';
2233  out:
2234         return c - d;
2235 }
2236
2237 /*
2238  * Find the appropriate entry in the hash table from the name.
2239  */
2240 static struct var **
2241 hashvar(const char *p)
2242 {
2243         unsigned hashval;
2244
2245         hashval = ((unsigned char) *p) << 4;
2246         while (*p && *p != '=')
2247                 hashval += (unsigned char) *p++;
2248         return &vartab[hashval % VTABSIZE];
2249 }
2250
2251 static int
2252 vpcmp(const void *a, const void *b)
2253 {
2254         return varcmp(*(const char **)a, *(const char **)b);
2255 }
2256
2257 /*
2258  * This routine initializes the builtin variables.
2259  */
2260 static void
2261 initvar(void)
2262 {
2263         struct var *vp;
2264         struct var *end;
2265         struct var **vpp;
2266
2267         /*
2268          * PS1 depends on uid
2269          */
2270 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2271         vps1.var_text = "PS1=\\w \\$ ";
2272 #else
2273         if (!geteuid())
2274                 vps1.var_text = "PS1=# ";
2275 #endif
2276         vp = varinit;
2277         end = vp + ARRAY_SIZE(varinit);
2278         do {
2279                 vpp = hashvar(vp->var_text);
2280                 vp->next = *vpp;
2281                 *vpp = vp;
2282         } while (++vp < end);
2283 }
2284
2285 static struct var **
2286 findvar(struct var **vpp, const char *name)
2287 {
2288         for (; *vpp; vpp = &(*vpp)->next) {
2289                 if (varcmp((*vpp)->var_text, name) == 0) {
2290                         break;
2291                 }
2292         }
2293         return vpp;
2294 }
2295
2296 /*
2297  * Find the value of a variable.  Returns NULL if not set.
2298  */
2299 static const char* FAST_FUNC
2300 lookupvar(const char *name)
2301 {
2302         struct var *v;
2303
2304         v = *findvar(hashvar(name), name);
2305         if (v) {
2306 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2307         /*
2308          * Dynamic variables are implemented roughly the same way they are
2309          * in bash. Namely, they're "special" so long as they aren't unset.
2310          * As soon as they're unset, they're no longer dynamic, and dynamic
2311          * lookup will no longer happen at that point. -- PFM.
2312          */
2313                 if (v->flags & VDYNAMIC)
2314                         v->var_func(NULL);
2315 #endif
2316                 if (!(v->flags & VUNSET)) {
2317                         if (v == &vlineno && v->var_text == linenovar) {
2318                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2319                         }
2320                         return var_end(v->var_text);
2321                 }
2322         }
2323         return NULL;
2324 }
2325
2326 #if ENABLE_UNICODE_SUPPORT
2327 static void
2328 reinit_unicode_for_ash(void)
2329 {
2330         /* Unicode support should be activated even if LANG is set
2331          * _during_ shell execution, not only if it was set when
2332          * shell was started. Therefore, re-check LANG every time:
2333          */
2334         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2335          || ENABLE_UNICODE_USING_LOCALE
2336         ) {
2337                 const char *s = lookupvar("LC_ALL");
2338                 if (!s) s = lookupvar("LC_CTYPE");
2339                 if (!s) s = lookupvar("LANG");
2340                 reinit_unicode(s);
2341         }
2342 }
2343 #else
2344 # define reinit_unicode_for_ash() ((void)0)
2345 #endif
2346
2347 /*
2348  * Search the environment of a builtin command.
2349  */
2350 static ALWAYS_INLINE const char *
2351 bltinlookup(const char *name)
2352 {
2353         return lookupvar(name);
2354 }
2355
2356 /*
2357  * Same as setvar except that the variable and value are passed in
2358  * the first argument as name=value.  Since the first argument will
2359  * be actually stored in the table, it should not be a string that
2360  * will go away.
2361  * Called with interrupts off.
2362  */
2363 static struct var *
2364 setvareq(char *s, int flags)
2365 {
2366         struct var *vp, **vpp;
2367
2368         vpp = hashvar(s);
2369         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2370         vpp = findvar(vpp, s);
2371         vp = *vpp;
2372         if (vp) {
2373                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2374                         const char *n;
2375
2376                         if (flags & VNOSAVE)
2377                                 free(s);
2378                         n = vp->var_text;
2379                         exitstatus = 1;
2380                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2381                 }
2382
2383                 if (flags & VNOSET)
2384                         goto out;
2385
2386                 if (vp->var_func && !(flags & VNOFUNC))
2387                         vp->var_func(var_end(s));
2388
2389                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2390                         free((char*)vp->var_text);
2391
2392                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2393                         *vpp = vp->next;
2394                         free(vp);
2395  out_free:
2396                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2397                                 free(s);
2398                         goto out;
2399                 }
2400
2401                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2402 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2403                 if (flags & VUNSET)
2404                         flags &= ~VDYNAMIC;
2405 #endif
2406         } else {
2407                 /* variable s is not found */
2408                 if (flags & VNOSET)
2409                         goto out;
2410                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2411                         goto out_free;
2412                 vp = ckzalloc(sizeof(*vp));
2413                 vp->next = *vpp;
2414                 /*vp->func = NULL; - ckzalloc did it */
2415                 *vpp = vp;
2416         }
2417         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2418                 s = ckstrdup(s);
2419         vp->var_text = s;
2420         vp->flags = flags;
2421
2422  out:
2423         return vp;
2424 }
2425
2426 /*
2427  * Set the value of a variable.  The flags argument is ored with the
2428  * flags of the variable.  If val is NULL, the variable is unset.
2429  */
2430 static struct var *
2431 setvar(const char *name, const char *val, int flags)
2432 {
2433         const char *q;
2434         char *p;
2435         char *nameeq;
2436         size_t namelen;
2437         size_t vallen;
2438         struct var *vp;
2439
2440         q = endofname(name);
2441         p = strchrnul(q, '=');
2442         namelen = p - name;
2443         if (!namelen || p != q)
2444                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2445         vallen = 0;
2446         if (val == NULL) {
2447                 flags |= VUNSET;
2448         } else {
2449                 vallen = strlen(val);
2450         }
2451
2452         INT_OFF;
2453         nameeq = ckzalloc(namelen + vallen + 2);
2454         p = mempcpy(nameeq, name, namelen);
2455         if (val) {
2456                 *p++ = '=';
2457                 memcpy(p, val, vallen);
2458         }
2459         vp = setvareq(nameeq, flags | VNOSAVE);
2460         INT_ON;
2461
2462         return vp;
2463 }
2464
2465 static void FAST_FUNC
2466 setvar0(const char *name, const char *val)
2467 {
2468         setvar(name, val, 0);
2469 }
2470
2471 /*
2472  * Unset the specified variable.
2473  */
2474 static void
2475 unsetvar(const char *s)
2476 {
2477         setvar(s, NULL, 0);
2478 }
2479
2480 /*
2481  * Process a linked list of variable assignments.
2482  */
2483 static void
2484 listsetvar(struct strlist *list_set_var, int flags)
2485 {
2486         struct strlist *lp = list_set_var;
2487
2488         if (!lp)
2489                 return;
2490         INT_OFF;
2491         do {
2492                 setvareq(lp->text, flags);
2493                 lp = lp->next;
2494         } while (lp);
2495         INT_ON;
2496 }
2497
2498 /*
2499  * Generate a list of variables satisfying the given conditions.
2500  */
2501 #if !ENABLE_FEATURE_SH_NOFORK
2502 # define listvars(on, off, lp, end) listvars(on, off, end)
2503 #endif
2504 static char **
2505 listvars(int on, int off, struct strlist *lp, char ***end)
2506 {
2507         struct var **vpp;
2508         struct var *vp;
2509         char **ep;
2510         int mask;
2511
2512         STARTSTACKSTR(ep);
2513         vpp = vartab;
2514         mask = on | off;
2515         do {
2516                 for (vp = *vpp; vp; vp = vp->next) {
2517                         if ((vp->flags & mask) == on) {
2518 #if ENABLE_FEATURE_SH_NOFORK
2519                                 /* If variable with the same name is both
2520                                  * exported and temporarily set for a command:
2521                                  *  export ZVAR=5
2522                                  *  ZVAR=6 printenv
2523                                  * then "ZVAR=6" will be both in vartab and
2524                                  * lp lists. Do not pass it twice to printenv.
2525                                  */
2526                                 struct strlist *lp1 = lp;
2527                                 while (lp1) {
2528                                         if (strcmp(lp1->text, vp->var_text) == 0)
2529                                                 goto skip;
2530                                         lp1 = lp1->next;
2531                                 }
2532 #endif
2533                                 if (ep == stackstrend())
2534                                         ep = growstackstr();
2535                                 *ep++ = (char*)vp->var_text;
2536 #if ENABLE_FEATURE_SH_NOFORK
2537  skip: ;
2538 #endif
2539                         }
2540                 }
2541         } while (++vpp < vartab + VTABSIZE);
2542
2543 #if ENABLE_FEATURE_SH_NOFORK
2544         while (lp) {
2545                 if (ep == stackstrend())
2546                         ep = growstackstr();
2547                 *ep++ = lp->text;
2548                 lp = lp->next;
2549         }
2550 #endif
2551
2552         if (ep == stackstrend())
2553                 ep = growstackstr();
2554         if (end)
2555                 *end = ep;
2556         *ep++ = NULL;
2557         return grabstackstr(ep);
2558 }
2559
2560
2561 /* ============ Path search helper
2562  *
2563  * The variable path (passed by reference) should be set to the start
2564  * of the path before the first call; path_advance will update
2565  * this value as it proceeds.  Successive calls to path_advance will return
2566  * the possible path expansions in sequence.  If an option (indicated by
2567  * a percent sign) appears in the path entry then the global variable
2568  * pathopt will be set to point to it; otherwise pathopt will be set to
2569  * NULL.
2570  */
2571 static const char *pathopt;     /* set by path_advance */
2572
2573 static char *
2574 path_advance(const char **path, const char *name)
2575 {
2576         const char *p;
2577         char *q;
2578         const char *start;
2579         size_t len;
2580
2581         if (*path == NULL)
2582                 return NULL;
2583         start = *path;
2584         for (p = start; *p && *p != ':' && *p != '%'; p++)
2585                 continue;
2586         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2587         while (stackblocksize() < len)
2588                 growstackblock();
2589         q = stackblock();
2590         if (p != start) {
2591                 q = mempcpy(q, start, p - start);
2592                 *q++ = '/';
2593         }
2594         strcpy(q, name);
2595         pathopt = NULL;
2596         if (*p == '%') {
2597                 pathopt = ++p;
2598                 while (*p && *p != ':')
2599                         p++;
2600         }
2601         if (*p == ':')
2602                 *path = p + 1;
2603         else
2604                 *path = NULL;
2605         return stalloc(len);
2606 }
2607
2608
2609 /* ============ Prompt */
2610
2611 static smallint doprompt;                   /* if set, prompt the user */
2612 static smallint needprompt;                 /* true if interactive and at start of line */
2613
2614 #if ENABLE_FEATURE_EDITING
2615 static line_input_t *line_input_state;
2616 static const char *cmdedit_prompt;
2617 static void
2618 putprompt(const char *s)
2619 {
2620         if (ENABLE_ASH_EXPAND_PRMT) {
2621                 free((char*)cmdedit_prompt);
2622                 cmdedit_prompt = ckstrdup(s);
2623                 return;
2624         }
2625         cmdedit_prompt = s;
2626 }
2627 #else
2628 static void
2629 putprompt(const char *s)
2630 {
2631         out2str(s);
2632 }
2633 #endif
2634
2635 /* expandstr() needs parsing machinery, so it is far away ahead... */
2636 static const char *expandstr(const char *ps, int syntax_type);
2637 /* Values for syntax param */
2638 #define BASESYNTAX 0    /* not in quotes */
2639 #define DQSYNTAX   1    /* in double quotes */
2640 #define SQSYNTAX   2    /* in single quotes */
2641 #define ARISYNTAX  3    /* in arithmetic */
2642 #if ENABLE_ASH_EXPAND_PRMT
2643 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2644 #endif
2645 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2646
2647 /*
2648  * called by editline -- any expansions to the prompt should be added here.
2649  */
2650 static void
2651 setprompt_if(smallint do_set, int whichprompt)
2652 {
2653         const char *prompt;
2654         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2655
2656         if (!do_set)
2657                 return;
2658
2659         needprompt = 0;
2660
2661         switch (whichprompt) {
2662         case 1:
2663                 prompt = ps1val();
2664                 break;
2665         case 2:
2666                 prompt = ps2val();
2667                 break;
2668         default:                        /* 0 */
2669                 prompt = nullstr;
2670         }
2671 #if ENABLE_ASH_EXPAND_PRMT
2672         pushstackmark(&smark, stackblocksize());
2673         putprompt(expandstr(prompt, PSSYNTAX));
2674         popstackmark(&smark);
2675 #else
2676         putprompt(prompt);
2677 #endif
2678 }
2679
2680
2681 /* ============ The cd and pwd commands */
2682
2683 #define CD_PHYSICAL 1
2684 #define CD_PRINT 2
2685
2686 static int
2687 cdopt(void)
2688 {
2689         int flags = 0;
2690         int i, j;
2691
2692         j = 'L';
2693         while ((i = nextopt("LP")) != '\0') {
2694                 if (i != j) {
2695                         flags ^= CD_PHYSICAL;
2696                         j = i;
2697                 }
2698         }
2699
2700         return flags;
2701 }
2702
2703 /*
2704  * Update curdir (the name of the current directory) in response to a
2705  * cd command.
2706  */
2707 static const char *
2708 updatepwd(const char *dir)
2709 {
2710         char *new;
2711         char *p;
2712         char *cdcomppath;
2713         const char *lim;
2714
2715         cdcomppath = sstrdup(dir);
2716         STARTSTACKSTR(new);
2717         if (*dir != '/') {
2718                 if (curdir == nullstr)
2719                         return 0;
2720                 new = stack_putstr(curdir, new);
2721         }
2722         new = makestrspace(strlen(dir) + 2, new);
2723         lim = (char *)stackblock() + 1;
2724         if (*dir != '/') {
2725                 if (new[-1] != '/')
2726                         USTPUTC('/', new);
2727                 if (new > lim && *lim == '/')
2728                         lim++;
2729         } else {
2730                 USTPUTC('/', new);
2731                 cdcomppath++;
2732                 if (dir[1] == '/' && dir[2] != '/') {
2733                         USTPUTC('/', new);
2734                         cdcomppath++;
2735                         lim++;
2736                 }
2737         }
2738         p = strtok(cdcomppath, "/");
2739         while (p) {
2740                 switch (*p) {
2741                 case '.':
2742                         if (p[1] == '.' && p[2] == '\0') {
2743                                 while (new > lim) {
2744                                         STUNPUTC(new);
2745                                         if (new[-1] == '/')
2746                                                 break;
2747                                 }
2748                                 break;
2749                         }
2750                         if (p[1] == '\0')
2751                                 break;
2752                         /* fall through */
2753                 default:
2754                         new = stack_putstr(p, new);
2755                         USTPUTC('/', new);
2756                 }
2757                 p = strtok(NULL, "/");
2758         }
2759         if (new > lim)
2760                 STUNPUTC(new);
2761         *new = 0;
2762         return stackblock();
2763 }
2764
2765 /*
2766  * Find out what the current directory is. If we already know the current
2767  * directory, this routine returns immediately.
2768  */
2769 static char *
2770 getpwd(void)
2771 {
2772         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2773         return dir ? dir : nullstr;
2774 }
2775
2776 static void
2777 setpwd(const char *val, int setold)
2778 {
2779         char *oldcur, *dir;
2780
2781         oldcur = dir = curdir;
2782
2783         if (setold) {
2784                 setvar("OLDPWD", oldcur, VEXPORT);
2785         }
2786         INT_OFF;
2787         if (physdir != nullstr) {
2788                 if (physdir != oldcur)
2789                         free(physdir);
2790                 physdir = nullstr;
2791         }
2792         if (oldcur == val || !val) {
2793                 char *s = getpwd();
2794                 physdir = s;
2795                 if (!val)
2796                         dir = s;
2797         } else
2798                 dir = ckstrdup(val);
2799         if (oldcur != dir && oldcur != nullstr) {
2800                 free(oldcur);
2801         }
2802         curdir = dir;
2803         INT_ON;
2804         setvar("PWD", dir, VEXPORT);
2805 }
2806
2807 static void hashcd(void);
2808
2809 /*
2810  * Actually do the chdir.  We also call hashcd to let other routines
2811  * know that the current directory has changed.
2812  */
2813 static int
2814 docd(const char *dest, int flags)
2815 {
2816         const char *dir = NULL;
2817         int err;
2818
2819         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2820
2821         INT_OFF;
2822         if (!(flags & CD_PHYSICAL)) {
2823                 dir = updatepwd(dest);
2824                 if (dir)
2825                         dest = dir;
2826         }
2827         err = chdir(dest);
2828         if (err)
2829                 goto out;
2830         setpwd(dir, 1);
2831         hashcd();
2832  out:
2833         INT_ON;
2834         return err;
2835 }
2836
2837 static int FAST_FUNC
2838 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2839 {
2840         const char *dest;
2841         const char *path;
2842         const char *p;
2843         char c;
2844         struct stat statb;
2845         int flags;
2846
2847         flags = cdopt();
2848         dest = *argptr;
2849         if (!dest)
2850                 dest = bltinlookup("HOME");
2851         else if (LONE_DASH(dest)) {
2852                 dest = bltinlookup("OLDPWD");
2853                 flags |= CD_PRINT;
2854         }
2855         if (!dest)
2856                 dest = nullstr;
2857         if (*dest == '/')
2858                 goto step6;
2859         if (*dest == '.') {
2860                 c = dest[1];
2861  dotdot:
2862                 switch (c) {
2863                 case '\0':
2864                 case '/':
2865                         goto step6;
2866                 case '.':
2867                         c = dest[2];
2868                         if (c != '.')
2869                                 goto dotdot;
2870                 }
2871         }
2872         if (!*dest)
2873                 dest = ".";
2874         path = bltinlookup("CDPATH");
2875         while (path) {
2876                 c = *path;
2877                 p = path_advance(&path, dest);
2878                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2879                         if (c && c != ':')
2880                                 flags |= CD_PRINT;
2881  docd:
2882                         if (!docd(p, flags))
2883                                 goto out;
2884                         goto err;
2885                 }
2886         }
2887
2888  step6:
2889         p = dest;
2890         goto docd;
2891
2892  err:
2893         ash_msg_and_raise_perror("can't cd to %s", dest);
2894         /* NOTREACHED */
2895  out:
2896         if (flags & CD_PRINT)
2897                 out1fmt("%s\n", curdir);
2898         return 0;
2899 }
2900
2901 static int FAST_FUNC
2902 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2903 {
2904         int flags;
2905         const char *dir = curdir;
2906
2907         flags = cdopt();
2908         if (flags) {
2909                 if (physdir == nullstr)
2910                         setpwd(dir, 0);
2911                 dir = physdir;
2912         }
2913         out1fmt("%s\n", dir);
2914         return 0;
2915 }
2916
2917
2918 /* ============ ... */
2919
2920
2921 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2922
2923 /* Syntax classes */
2924 #define CWORD     0             /* character is nothing special */
2925 #define CNL       1             /* newline character */
2926 #define CBACK     2             /* a backslash character */
2927 #define CSQUOTE   3             /* single quote */
2928 #define CDQUOTE   4             /* double quote */
2929 #define CENDQUOTE 5             /* a terminating quote */
2930 #define CBQUOTE   6             /* backwards single quote */
2931 #define CVAR      7             /* a dollar sign */
2932 #define CENDVAR   8             /* a '}' character */
2933 #define CLP       9             /* a left paren in arithmetic */
2934 #define CRP      10             /* a right paren in arithmetic */
2935 #define CENDFILE 11             /* end of file */
2936 #define CCTL     12             /* like CWORD, except it must be escaped */
2937 #define CSPCL    13             /* these terminate a word */
2938 #define CIGN     14             /* character should be ignored */
2939
2940 #define PEOF     256
2941 #if ENABLE_ASH_ALIAS
2942 # define PEOA    257
2943 #endif
2944
2945 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2946
2947 #if ENABLE_FEATURE_SH_MATH
2948 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2949 #else
2950 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2951 #endif
2952 static const uint16_t S_I_T[] ALIGN2 = {
2953 #if ENABLE_ASH_ALIAS
2954         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2955 #endif
2956         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2957         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2958         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2959         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2960         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2961         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2962         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2963         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2964         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2965         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2966         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2967 #if !USE_SIT_FUNCTION
2968         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2969         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2970         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2971 #endif
2972 #undef SIT_ITEM
2973 };
2974 /* Constants below must match table above */
2975 enum {
2976 #if ENABLE_ASH_ALIAS
2977         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2978 #endif
2979         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2980         CNL_CNL_CNL_CNL                    , /*  2 */
2981         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2982         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2983         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2984         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2985         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2986         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2987         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2988         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2989         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2990         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2991         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2992         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2993 };
2994
2995 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2996  * caller must ensure proper cast on it if c is *char_ptr!
2997  */
2998 #if USE_SIT_FUNCTION
2999
3000 static int
3001 SIT(int c, int syntax)
3002 {
3003         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
3004         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
3005         /*
3006          * This causes '/' to be prepended with CTLESC in dquoted string,
3007          * making "./file"* treated incorrectly because we feed
3008          * ".\/file*" string to glob(), confusing it (see expandmeta func).
3009          * The "homegrown" glob implementation is okay with that,
3010          * but glibc one isn't. With '/' always treated as CWORD,
3011          * both work fine.
3012          */
3013 # if ENABLE_ASH_ALIAS
3014         static const uint8_t syntax_index_table[] ALIGN1 = {
3015                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
3016                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
3017                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
3018                 11, 3                           /* "}~" */
3019         };
3020 # else
3021         static const uint8_t syntax_index_table[] ALIGN1 = {
3022                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
3023                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
3024                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
3025                 10, 2                           /* "}~" */
3026         };
3027 # endif
3028         const char *s;
3029         int indx;
3030
3031         if (c == PEOF)
3032                 return CENDFILE;
3033 # if ENABLE_ASH_ALIAS
3034         if (c == PEOA)
3035                 indx = 0;
3036         else
3037 # endif
3038         {
3039                 /* Cast is purely for paranoia here,
3040                  * just in case someone passed signed char to us */
3041                 if ((unsigned char)c >= CTL_FIRST
3042                  && (unsigned char)c <= CTL_LAST
3043                 ) {
3044                         return CCTL;
3045                 }
3046                 s = strchrnul(spec_symbls, c);
3047                 if (*s == '\0')
3048                         return CWORD;
3049                 indx = syntax_index_table[s - spec_symbls];
3050         }
3051         return (S_I_T[indx] >> (syntax*4)) & 0xf;
3052 }
3053
3054 #else   /* !USE_SIT_FUNCTION */
3055
3056 static const uint8_t syntax_index_table[] ALIGN1 = {
3057         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3058         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3059         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3060         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3061         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3062         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3063         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3064         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3065         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3066         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3067         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3068         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3069         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3070         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3071         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3072         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3073         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3074         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3075         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3076         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3077         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3078         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3079         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3080         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3081         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3082         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3083         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3084         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3085         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3086         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3087         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3088         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3089         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3090         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3091         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3092         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3093         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3094         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3095         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3096         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3097         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3098         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3099         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3100         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3101         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3102         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3103         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3104         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3105 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3106         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3107         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3108         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3109         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3110         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3111         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3112         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3113         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3114         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3115         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3116         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3117         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3118         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3119         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3120         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3121         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3122         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3123         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3124         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3125         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3126         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3127         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3128         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3129         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3130         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3131         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3132         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3133         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3134         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3135         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3136         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3137         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3138         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3139         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3140         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3141         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3142         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3143         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3144         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3145         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3146         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3147         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3148         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3149         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3150         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3151         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3152         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3153         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3154         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3155         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3156         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3157         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3158         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3159         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3160         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3161         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3162         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3163         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3164         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3165         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3166         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3167         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3168         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3169         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3170         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3171         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3172         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3173         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3174         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3175         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3176         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3177         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3178         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3179         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3180         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3181         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3182         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3183         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3184         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3185         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3186         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3187         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3188         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3189         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3190         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3191         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3192         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3193         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3194         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3195         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3196         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3258         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3259         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3260         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3261         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3262         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3263         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3264         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3265         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3266         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3267         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3268         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3269         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3270         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3271         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3272         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3273         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3274         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3275         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3276         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3277         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3278         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3279         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3280         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3281         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3282         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3283         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3284         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3285         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3286         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3287         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3288         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3289         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3290         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3291         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3292         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3293         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3294         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3295         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3296         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3297         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3298         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3299         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3300         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3301         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3302         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3303         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3304         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3305         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3306         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3307         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3308         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3309         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3310         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3311         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3312         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3313         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3314         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3315         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3316 # if ENABLE_ASH_ALIAS
3317         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3318 # endif
3319 };
3320
3321 #if 1
3322 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3323 #else /* debug version, caught one signed char bug */
3324 # define SIT(c, syntax) \
3325         ({ \
3326                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3327                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3328                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3329                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3330                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3331         })
3332 #endif
3333
3334 #endif  /* !USE_SIT_FUNCTION */
3335
3336
3337 /* ============ Alias handling */
3338
3339 #if ENABLE_ASH_ALIAS
3340
3341 #define ALIASINUSE 1
3342 #define ALIASDEAD  2
3343
3344 struct alias {
3345         struct alias *next;
3346         char *name;
3347         char *val;
3348         int flag;
3349 };
3350
3351
3352 static struct alias **atab; // [ATABSIZE];
3353 #define INIT_G_alias() do { \
3354         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3355 } while (0)
3356
3357
3358 static struct alias **
3359 __lookupalias(const char *name)
3360 {
3361         unsigned int hashval;
3362         struct alias **app;
3363         const char *p;
3364         unsigned int ch;
3365
3366         p = name;
3367
3368         ch = (unsigned char)*p;
3369         hashval = ch << 4;
3370         while (ch) {
3371                 hashval += ch;
3372                 ch = (unsigned char)*++p;
3373         }
3374         app = &atab[hashval % ATABSIZE];
3375
3376         for (; *app; app = &(*app)->next) {
3377                 if (strcmp(name, (*app)->name) == 0) {
3378                         break;
3379                 }
3380         }
3381
3382         return app;
3383 }
3384
3385 static struct alias *
3386 lookupalias(const char *name, int check)
3387 {
3388         struct alias *ap = *__lookupalias(name);
3389
3390         if (check && ap && (ap->flag & ALIASINUSE))
3391                 return NULL;
3392         return ap;
3393 }
3394
3395 static struct alias *
3396 freealias(struct alias *ap)
3397 {
3398         struct alias *next;
3399
3400         if (ap->flag & ALIASINUSE) {
3401                 ap->flag |= ALIASDEAD;
3402                 return ap;
3403         }
3404
3405         next = ap->next;
3406         free(ap->name);
3407         free(ap->val);
3408         free(ap);
3409         return next;
3410 }
3411
3412 static void
3413 setalias(const char *name, const char *val)
3414 {
3415         struct alias *ap, **app;
3416
3417         app = __lookupalias(name);
3418         ap = *app;
3419         INT_OFF;
3420         if (ap) {
3421                 if (!(ap->flag & ALIASINUSE)) {
3422                         free(ap->val);
3423                 }
3424                 ap->val = ckstrdup(val);
3425                 ap->flag &= ~ALIASDEAD;
3426         } else {
3427                 /* not found */
3428                 ap = ckzalloc(sizeof(struct alias));
3429                 ap->name = ckstrdup(name);
3430                 ap->val = ckstrdup(val);
3431                 /*ap->flag = 0; - ckzalloc did it */
3432                 /*ap->next = NULL;*/
3433                 *app = ap;
3434         }
3435         INT_ON;
3436 }
3437
3438 static int
3439 unalias(const char *name)
3440 {
3441         struct alias **app;
3442
3443         app = __lookupalias(name);
3444
3445         if (*app) {
3446                 INT_OFF;
3447                 *app = freealias(*app);
3448                 INT_ON;
3449                 return 0;
3450         }
3451
3452         return 1;
3453 }
3454
3455 static void
3456 rmaliases(void)
3457 {
3458         struct alias *ap, **app;
3459         int i;
3460
3461         INT_OFF;
3462         for (i = 0; i < ATABSIZE; i++) {
3463                 app = &atab[i];
3464                 for (ap = *app; ap; ap = *app) {
3465                         *app = freealias(*app);
3466                         if (ap == *app) {
3467                                 app = &ap->next;
3468                         }
3469                 }
3470         }
3471         INT_ON;
3472 }
3473
3474 static void
3475 printalias(const struct alias *ap)
3476 {
3477         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3478 }
3479
3480 /*
3481  * TODO - sort output
3482  */
3483 static int FAST_FUNC
3484 aliascmd(int argc UNUSED_PARAM, char **argv)
3485 {
3486         char *n, *v;
3487         int ret = 0;
3488         struct alias *ap;
3489
3490         if (!argv[1]) {
3491                 int i;
3492
3493                 for (i = 0; i < ATABSIZE; i++) {
3494                         for (ap = atab[i]; ap; ap = ap->next) {
3495                                 printalias(ap);
3496                         }
3497                 }
3498                 return 0;
3499         }
3500         while ((n = *++argv) != NULL) {
3501                 v = strchr(n+1, '=');
3502                 if (v == NULL) { /* n+1: funny ksh stuff */
3503                         ap = *__lookupalias(n);
3504                         if (ap == NULL) {
3505                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3506                                 ret = 1;
3507                         } else
3508                                 printalias(ap);
3509                 } else {
3510                         *v++ = '\0';
3511                         setalias(n, v);
3512                 }
3513         }
3514
3515         return ret;
3516 }
3517
3518 static int FAST_FUNC
3519 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3520 {
3521         int i;
3522
3523         while (nextopt("a") != '\0') {
3524                 rmaliases();
3525                 return 0;
3526         }
3527         for (i = 0; *argptr; argptr++) {
3528                 if (unalias(*argptr)) {
3529                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3530                         i = 1;
3531                 }
3532         }
3533
3534         return i;
3535 }
3536
3537 #endif /* ASH_ALIAS */
3538
3539
3540 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3541 #define FORK_FG    0
3542 #define FORK_BG    1
3543 #define FORK_NOJOB 2
3544
3545 /* mode flags for showjob(s) */
3546 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3547 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3548 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3549 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3550
3551 /*
3552  * A job structure contains information about a job.  A job is either a
3553  * single process or a set of processes contained in a pipeline.  In the
3554  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3555  * array of pids.
3556  */
3557 struct procstat {
3558         pid_t   ps_pid;         /* process id */
3559         int     ps_status;      /* last process status from wait() */
3560         char    *ps_cmd;        /* text of command being run */
3561 };
3562
3563 struct job {
3564         struct procstat ps0;    /* status of process */
3565         struct procstat *ps;    /* status of processes when more than one */
3566 #if JOBS
3567         int stopstatus;         /* status of a stopped job */
3568 #endif
3569         unsigned nprocs;        /* number of processes */
3570
3571 #define JOBRUNNING      0       /* at least one proc running */
3572 #define JOBSTOPPED      1       /* all procs are stopped */
3573 #define JOBDONE         2       /* all procs are completed */
3574         unsigned
3575                 state: 8,
3576 #if JOBS
3577                 sigint: 1,      /* job was killed by SIGINT */
3578                 jobctl: 1,      /* job running under job control */
3579 #endif
3580                 waited: 1,      /* true if this entry has been waited for */
3581                 used: 1,        /* true if this entry is in used */
3582                 changed: 1;     /* true if status has changed */
3583         struct job *prev_job;   /* previous job */
3584 };
3585
3586 static struct job *makejob(/*union node *,*/ int);
3587 static int forkshell(struct job *, union node *, int);
3588 static int waitforjob(struct job *);
3589
3590 #if !JOBS
3591 enum { doing_jobctl = 0 };
3592 #define setjobctl(on) do {} while (0)
3593 #else
3594 static smallint doing_jobctl; //references:8
3595 static void setjobctl(int);
3596 #endif
3597
3598 /*
3599  * Ignore a signal.
3600  */
3601 static void
3602 ignoresig(int signo)
3603 {
3604         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3605         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3606                 /* No, need to do it */
3607                 signal(signo, SIG_IGN);
3608         }
3609         sigmode[signo - 1] = S_HARD_IGN;
3610 }
3611
3612 /*
3613  * Only one usage site - in setsignal()
3614  */
3615 static void
3616 signal_handler(int signo)
3617 {
3618         if (signo == SIGCHLD) {
3619                 got_sigchld = 1;
3620                 if (!trap[SIGCHLD])
3621                         return;
3622         }
3623
3624         gotsig[signo - 1] = 1;
3625         pending_sig = signo;
3626
3627         if (signo == SIGINT && !trap[SIGINT]) {
3628                 if (!suppress_int) {
3629                         pending_sig = 0;
3630                         raise_interrupt(); /* does not return */
3631                 }
3632                 pending_int = 1;
3633         }
3634 }
3635
3636 /*
3637  * Set the signal handler for the specified signal.  The routine figures
3638  * out what it should be set to.
3639  */
3640 static void
3641 setsignal(int signo)
3642 {
3643         char *t;
3644         char cur_act, new_act;
3645         struct sigaction act;
3646
3647         t = trap[signo];
3648         new_act = S_DFL;
3649         if (t != NULL) { /* trap for this sig is set */
3650                 new_act = S_CATCH;
3651                 if (t[0] == '\0') /* trap is "": ignore this sig */
3652                         new_act = S_IGN;
3653         }
3654
3655         if (rootshell && new_act == S_DFL) {
3656                 switch (signo) {
3657                 case SIGINT:
3658                         if (iflag || minusc || sflag == 0)
3659                                 new_act = S_CATCH;
3660                         break;
3661                 case SIGQUIT:
3662 #if DEBUG
3663                         if (debug)
3664                                 break;
3665 #endif
3666                         /* man bash:
3667                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3668                          * commands run by bash have signal handlers
3669                          * set to the values inherited by the shell
3670                          * from its parent". */
3671                         new_act = S_IGN;
3672                         break;
3673                 case SIGTERM:
3674                         if (iflag)
3675                                 new_act = S_IGN;
3676                         break;
3677 #if JOBS
3678                 case SIGTSTP:
3679                 case SIGTTOU:
3680                         if (mflag)
3681                                 new_act = S_IGN;
3682                         break;
3683 #endif
3684                 }
3685         }
3686         /* if !rootshell, we reset SIGQUIT to DFL,
3687          * whereas we have to restore it to what shell got on entry.
3688          * This is handled by the fact that if signal was IGNored on entry,
3689          * then cur_act is S_HARD_IGN and we never change its sigaction
3690          * (see code below).
3691          */
3692
3693         if (signo == SIGCHLD)
3694                 new_act = S_CATCH;
3695
3696         t = &sigmode[signo - 1];
3697         cur_act = *t;
3698         if (cur_act == 0) {
3699                 /* current setting is not yet known */
3700                 if (sigaction(signo, NULL, &act)) {
3701                         /* pretend it worked; maybe we should give a warning,
3702                          * but other shells don't. We don't alter sigmode,
3703                          * so we retry every time.
3704                          * btw, in Linux it never fails. --vda */
3705                         return;
3706                 }
3707                 if (act.sa_handler == SIG_IGN) {
3708                         cur_act = S_HARD_IGN;
3709                         if (mflag
3710                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3711                         ) {
3712                                 cur_act = S_IGN;   /* don't hard ignore these */
3713                         }
3714                 }
3715                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3716                         /* installing SIG_DFL over SIG_DFL is a no-op */
3717                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3718                         *t = S_DFL;
3719                         return;
3720                 }
3721         }
3722         if (cur_act == S_HARD_IGN || cur_act == new_act)
3723                 return;
3724
3725         *t = new_act;
3726
3727         act.sa_handler = SIG_DFL;
3728         switch (new_act) {
3729         case S_CATCH:
3730                 act.sa_handler = signal_handler;
3731                 break;
3732         case S_IGN:
3733                 act.sa_handler = SIG_IGN;
3734                 break;
3735         }
3736         /* flags and mask matter only if !DFL and !IGN, but we do it
3737          * for all cases for more deterministic behavior:
3738          */
3739         act.sa_flags = 0; //TODO: why not SA_RESTART?
3740         sigfillset(&act.sa_mask);
3741
3742         sigaction_set(signo, &act);
3743 }
3744
3745 /* mode flags for set_curjob */
3746 #define CUR_DELETE 2
3747 #define CUR_RUNNING 1
3748 #define CUR_STOPPED 0
3749
3750 #if JOBS
3751 /* pgrp of shell on invocation */
3752 static int initialpgrp; //references:2
3753 static int ttyfd = -1; //5
3754 #endif
3755 /* array of jobs */
3756 static struct job *jobtab; //5
3757 /* size of array */
3758 static unsigned njobs; //4
3759 /* current job */
3760 static struct job *curjob; //lots
3761 /* number of presumed living untracked jobs */
3762 static int jobless; //4
3763
3764 #if 0
3765 /* Bash has a feature: it restores termios after a successful wait for
3766  * a foreground job which had at least one stopped or sigkilled member.
3767  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3768  * properly restoring tty state. Should we do this too?
3769  * A reproducer: ^Z an interactive python:
3770  *
3771  * # python
3772  * Python 2.7.12 (...)
3773  * >>> ^Z
3774  *      { python leaves tty in -icanon -echo state. We do survive that... }
3775  *  [1]+  Stopped                    python
3776  *      { ...however, next program (python #2) does not survive it well: }
3777  * # python
3778  * Python 2.7.12 (...)
3779  * >>> Traceback (most recent call last):
3780  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3781  *   File "<stdin>", line 1, in <module>
3782  * NameError: name 'qwerty' is not defined
3783  *
3784  * The implementation below is modeled on bash code and seems to work.
3785  * However, I'm not sure we should do this. For one: what if I'd fg
3786  * the stopped python instead? It'll be confused by "restored" tty state.
3787  */
3788 static struct termios shell_tty_info;
3789 static void
3790 get_tty_state(void)
3791 {
3792         if (rootshell && ttyfd >= 0)
3793                 tcgetattr(ttyfd, &shell_tty_info);
3794 }
3795 static void
3796 set_tty_state(void)
3797 {
3798         /* if (rootshell) - caller ensures this */
3799         if (ttyfd >= 0)
3800                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3801 }
3802 static int
3803 job_signal_status(struct job *jp)
3804 {
3805         int status;
3806         unsigned i;
3807         struct procstat *ps = jp->ps;
3808         for (i = 0; i < jp->nprocs; i++) {
3809                 status = ps[i].ps_status;
3810                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3811                         return status;
3812         }
3813         return 0;
3814 }
3815 static void
3816 restore_tty_if_stopped_or_signaled(struct job *jp)
3817 {
3818 //TODO: check what happens if we come from waitforjob() in expbackq()
3819         if (rootshell) {
3820                 int s = job_signal_status(jp);
3821                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3822                         set_tty_state();
3823         }
3824 }
3825 #else
3826 # define get_tty_state() ((void)0)
3827 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3828 #endif
3829
3830 static void
3831 set_curjob(struct job *jp, unsigned mode)
3832 {
3833         struct job *jp1;
3834         struct job **jpp, **curp;
3835
3836         /* first remove from list */
3837         jpp = curp = &curjob;
3838         while (1) {
3839                 jp1 = *jpp;
3840                 if (jp1 == jp)
3841                         break;
3842                 jpp = &jp1->prev_job;
3843         }
3844         *jpp = jp1->prev_job;
3845
3846         /* Then re-insert in correct position */
3847         jpp = curp;
3848         switch (mode) {
3849         default:
3850 #if DEBUG
3851                 abort();
3852 #endif
3853         case CUR_DELETE:
3854                 /* job being deleted */
3855                 break;
3856         case CUR_RUNNING:
3857                 /* newly created job or backgrounded job,
3858                  * put after all stopped jobs.
3859                  */
3860                 while (1) {
3861                         jp1 = *jpp;
3862 #if JOBS
3863                         if (!jp1 || jp1->state != JOBSTOPPED)
3864 #endif
3865                                 break;
3866                         jpp = &jp1->prev_job;
3867                 }
3868                 /* FALLTHROUGH */
3869 #if JOBS
3870         case CUR_STOPPED:
3871 #endif
3872                 /* newly stopped job - becomes curjob */
3873                 jp->prev_job = *jpp;
3874                 *jpp = jp;
3875                 break;
3876         }
3877 }
3878
3879 #if JOBS || DEBUG
3880 static int
3881 jobno(const struct job *jp)
3882 {
3883         return jp - jobtab + 1;
3884 }
3885 #endif
3886
3887 /*
3888  * Convert a job name to a job structure.
3889  */
3890 #if !JOBS
3891 #define getjob(name, getctl) getjob(name)
3892 #endif
3893 static struct job *
3894 getjob(const char *name, int getctl)
3895 {
3896         struct job *jp;
3897         struct job *found;
3898         const char *err_msg = "%s: no such job";
3899         unsigned num;
3900         int c;
3901         const char *p;
3902         char *(*match)(const char *, const char *);
3903
3904         jp = curjob;
3905         p = name;
3906         if (!p)
3907                 goto currentjob;
3908
3909         if (*p != '%')
3910                 goto err;
3911
3912         c = *++p;
3913         if (!c)
3914                 goto currentjob;
3915
3916         if (!p[1]) {
3917                 if (c == '+' || c == '%') {
3918  currentjob:
3919                         err_msg = "No current job";
3920                         goto check;
3921                 }
3922                 if (c == '-') {
3923                         if (jp)
3924                                 jp = jp->prev_job;
3925                         err_msg = "No previous job";
3926  check:
3927                         if (!jp)
3928                                 goto err;
3929                         goto gotit;
3930                 }
3931         }
3932
3933         if (is_number(p)) {
3934                 num = atoi(p);
3935                 if (num > 0 && num <= njobs) {
3936                         jp = jobtab + num - 1;
3937                         if (jp->used)
3938                                 goto gotit;
3939                         goto err;
3940                 }
3941         }
3942
3943         match = prefix;
3944         if (*p == '?') {
3945                 match = strstr;
3946                 p++;
3947         }
3948
3949         found = NULL;
3950         while (jp) {
3951                 if (match(jp->ps[0].ps_cmd, p)) {
3952                         if (found)
3953                                 goto err;
3954                         found = jp;
3955                         err_msg = "%s: ambiguous";
3956                 }
3957                 jp = jp->prev_job;
3958         }
3959         if (!found)
3960                 goto err;
3961         jp = found;
3962
3963  gotit:
3964 #if JOBS
3965         err_msg = "job %s not created under job control";
3966         if (getctl && jp->jobctl == 0)
3967                 goto err;
3968 #endif
3969         return jp;
3970  err:
3971         ash_msg_and_raise_error(err_msg, name);
3972 }
3973
3974 /*
3975  * Mark a job structure as unused.
3976  */
3977 static void
3978 freejob(struct job *jp)
3979 {
3980         struct procstat *ps;
3981         int i;
3982
3983         INT_OFF;
3984         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3985                 if (ps->ps_cmd != nullstr)
3986                         free(ps->ps_cmd);
3987         }
3988         if (jp->ps != &jp->ps0)
3989                 free(jp->ps);
3990         jp->used = 0;
3991         set_curjob(jp, CUR_DELETE);
3992         INT_ON;
3993 }
3994
3995 #if JOBS
3996 static void
3997 xtcsetpgrp(int fd, pid_t pgrp)
3998 {
3999         if (tcsetpgrp(fd, pgrp))
4000                 ash_msg_and_raise_perror("can't set tty process group");
4001 }
4002
4003 /*
4004  * Turn job control on and off.
4005  *
4006  * Note:  This code assumes that the third arg to ioctl is a character
4007  * pointer, which is true on Berkeley systems but not System V.  Since
4008  * System V doesn't have job control yet, this isn't a problem now.
4009  *
4010  * Called with interrupts off.
4011  */
4012 static void
4013 setjobctl(int on)
4014 {
4015         int fd;
4016         int pgrp;
4017
4018         if (on == doing_jobctl || rootshell == 0)
4019                 return;
4020         if (on) {
4021                 int ofd;
4022                 ofd = fd = open(_PATH_TTY, O_RDWR);
4023                 if (fd < 0) {
4024         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
4025          * That sometimes helps to acquire controlling tty.
4026          * Obviously, a workaround for bugs when someone
4027          * failed to provide a controlling tty to bash! :) */
4028                         fd = 2;
4029                         while (!isatty(fd))
4030                                 if (--fd < 0)
4031                                         goto out;
4032                 }
4033                 /* fd is a tty at this point */
4034                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
4035                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
4036                         close(ofd);
4037                 if (fd < 0)
4038                         goto out; /* F_DUPFD failed */
4039                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
4040                         close_on_exec_on(fd);
4041                 while (1) { /* while we are in the background */
4042                         pgrp = tcgetpgrp(fd);
4043                         if (pgrp < 0) {
4044  out:
4045                                 ash_msg("can't access tty; job control turned off");
4046                                 mflag = on = 0;
4047                                 goto close;
4048                         }
4049                         if (pgrp == getpgrp())
4050                                 break;
4051                         killpg(0, SIGTTIN);
4052                 }
4053                 initialpgrp = pgrp;
4054
4055                 setsignal(SIGTSTP);
4056                 setsignal(SIGTTOU);
4057                 setsignal(SIGTTIN);
4058                 pgrp = rootpid;
4059                 setpgid(0, pgrp);
4060                 xtcsetpgrp(fd, pgrp);
4061         } else {
4062                 /* turning job control off */
4063                 fd = ttyfd;
4064                 pgrp = initialpgrp;
4065                 /* was xtcsetpgrp, but this can make exiting ash
4066                  * loop forever if pty is already deleted */
4067                 tcsetpgrp(fd, pgrp);
4068                 setpgid(0, pgrp);
4069                 setsignal(SIGTSTP);
4070                 setsignal(SIGTTOU);
4071                 setsignal(SIGTTIN);
4072  close:
4073                 if (fd >= 0)
4074                         close(fd);
4075                 fd = -1;
4076         }
4077         ttyfd = fd;
4078         doing_jobctl = on;
4079 }
4080
4081 static int FAST_FUNC
4082 killcmd(int argc, char **argv)
4083 {
4084         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4085                 int i = 1;
4086                 do {
4087                         if (argv[i][0] == '%') {
4088                                 /*
4089                                  * "kill %N" - job kill
4090                                  * Converting to pgrp / pid kill
4091                                  */
4092                                 struct job *jp;
4093                                 char *dst;
4094                                 int j, n;
4095
4096                                 jp = getjob(argv[i], 0);
4097                                 /*
4098                                  * In jobs started under job control, we signal
4099                                  * entire process group by kill -PGRP_ID.
4100                                  * This happens, f.e., in interactive shell.
4101                                  *
4102                                  * Otherwise, we signal each child via
4103                                  * kill PID1 PID2 PID3.
4104                                  * Testcases:
4105                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4106                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4107                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4108                                  */
4109                                 n = jp->nprocs; /* can't be 0 (I hope) */
4110                                 if (jp->jobctl)
4111                                         n = 1;
4112                                 dst = alloca(n * sizeof(int)*4);
4113                                 argv[i] = dst;
4114                                 for (j = 0; j < n; j++) {
4115                                         struct procstat *ps = &jp->ps[j];
4116                                         /* Skip non-running and not-stopped members
4117                                          * (i.e. dead members) of the job
4118                                          */
4119                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4120                                                 continue;
4121                                         /*
4122                                          * kill_main has matching code to expect
4123                                          * leading space. Needed to not confuse
4124                                          * negative pids with "kill -SIGNAL_NO" syntax
4125                                          */
4126                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4127                                 }
4128                                 *dst = '\0';
4129                         }
4130                 } while (argv[++i]);
4131         }
4132         return kill_main(argc, argv);
4133 }
4134
4135 static void
4136 showpipe(struct job *jp /*, FILE *out*/)
4137 {
4138         struct procstat *ps;
4139         struct procstat *psend;
4140
4141         psend = jp->ps + jp->nprocs;
4142         for (ps = jp->ps + 1; ps < psend; ps++)
4143                 printf(" | %s", ps->ps_cmd);
4144         newline_and_flush(stdout);
4145         flush_stdout_stderr();
4146 }
4147
4148
4149 static int
4150 restartjob(struct job *jp, int mode)
4151 {
4152         struct procstat *ps;
4153         int i;
4154         int status;
4155         pid_t pgid;
4156
4157         INT_OFF;
4158         if (jp->state == JOBDONE)
4159                 goto out;
4160         jp->state = JOBRUNNING;
4161         pgid = jp->ps[0].ps_pid;
4162         if (mode == FORK_FG) {
4163                 get_tty_state();
4164                 xtcsetpgrp(ttyfd, pgid);
4165         }
4166         killpg(pgid, SIGCONT);
4167         ps = jp->ps;
4168         i = jp->nprocs;
4169         do {
4170                 if (WIFSTOPPED(ps->ps_status)) {
4171                         ps->ps_status = -1;
4172                 }
4173                 ps++;
4174         } while (--i);
4175  out:
4176         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4177         INT_ON;
4178         return status;
4179 }
4180
4181 static int FAST_FUNC
4182 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4183 {
4184         struct job *jp;
4185         int mode;
4186         int retval;
4187
4188         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4189         nextopt(nullstr);
4190         argv = argptr;
4191         do {
4192                 jp = getjob(*argv, 1);
4193                 if (mode == FORK_BG) {
4194                         set_curjob(jp, CUR_RUNNING);
4195                         printf("[%d] ", jobno(jp));
4196                 }
4197                 out1str(jp->ps[0].ps_cmd);
4198                 showpipe(jp /*, stdout*/);
4199                 retval = restartjob(jp, mode);
4200         } while (*argv && *++argv);
4201         return retval;
4202 }
4203 #endif
4204
4205 static int
4206 sprint_status48(char *os, int status, int sigonly)
4207 {
4208         char *s = os;
4209         int st;
4210
4211         if (!WIFEXITED(status)) {
4212 #if JOBS
4213                 if (WIFSTOPPED(status))
4214                         st = WSTOPSIG(status);
4215                 else
4216 #endif
4217                         st = WTERMSIG(status);
4218                 if (sigonly) {
4219                         if (st == SIGINT || st == SIGPIPE)
4220                                 goto out;
4221 #if JOBS
4222                         if (WIFSTOPPED(status))
4223                                 goto out;
4224 #endif
4225                 }
4226                 st &= 0x7f;
4227 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4228                 //s = stpncpy(s, strsignal(st), 32); //not all libc have stpncpy()
4229                 s += fmtstr(s, 32, strsignal(st));
4230                 if (WCOREDUMP(status)) {
4231                         s = stpcpy(s, " (core dumped)");
4232                 }
4233         } else if (!sigonly) {
4234                 st = WEXITSTATUS(status);
4235                 s += fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4236         }
4237  out:
4238         return s - os;
4239 }
4240
4241 static int
4242 wait_block_or_sig(int *status)
4243 {
4244         int pid;
4245
4246         do {
4247                 sigset_t mask;
4248
4249                 /* Poll all children for changes in their state */
4250                 got_sigchld = 0;
4251                 /* if job control is active, accept stopped processes too */
4252                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4253                 if (pid != 0)
4254                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4255
4256                 /* Children exist, but none are ready. Sleep until interesting signal */
4257 #if 1
4258                 sigfillset(&mask);
4259                 sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */
4260                 while (!got_sigchld && !pending_sig)
4261                         sigsuspend(&mask);
4262                 sigprocmask(SIG_SETMASK, &mask, NULL);
4263 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4264                 while (!got_sigchld && !pending_sig)
4265                         pause();
4266 #endif
4267
4268                 /* If it was SIGCHLD, poll children again */
4269         } while (got_sigchld);
4270
4271         return pid;
4272 }
4273
4274 #define DOWAIT_NONBLOCK 0
4275 #define DOWAIT_BLOCK    1
4276 #define DOWAIT_BLOCK_OR_SIG 2
4277 #if BASH_WAIT_N
4278 # define DOWAIT_JOBSTATUS 0x10   /* OR this to get job's exitstatus instead of pid */
4279 #endif
4280
4281 static int
4282 dowait(int block, struct job *job)
4283 {
4284         int pid;
4285         int status;
4286         struct job *jp;
4287         struct job *thisjob;
4288 #if BASH_WAIT_N
4289         bool want_jobexitstatus = (block & DOWAIT_JOBSTATUS);
4290         block = (block & ~DOWAIT_JOBSTATUS);
4291 #endif
4292
4293         TRACE(("dowait(0x%x) called\n", block));
4294
4295         /* It's wrong to call waitpid() outside of INT_OFF region:
4296          * signal can arrive just after syscall return and handler can
4297          * longjmp away, losing stop/exit notification processing.
4298          * Thus, for "jobs" builtin, and for waiting for a fg job,
4299          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4300          *
4301          * However, for "wait" builtin it is wrong to simply call waitpid()
4302          * in INT_OFF region: "wait" needs to wait for any running job
4303          * to change state, but should exit on any trap too.
4304          * In INT_OFF region, a signal just before syscall entry can set
4305          * pending_sig variables, but we can't check them, and we would
4306          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4307          *
4308          * Because of this, we run inside INT_OFF, but use a special routine
4309          * which combines waitpid() and sigsuspend().
4310          * This is the reason why we need to have a handler for SIGCHLD:
4311          * SIG_DFL handler does not wake sigsuspend().
4312          */
4313         INT_OFF;
4314         if (block == DOWAIT_BLOCK_OR_SIG) {
4315                 pid = wait_block_or_sig(&status);
4316         } else {
4317                 int wait_flags = 0;
4318                 if (block == DOWAIT_NONBLOCK)
4319                         wait_flags = WNOHANG;
4320                 /* if job control is active, accept stopped processes too */
4321                 if (doing_jobctl)
4322                         wait_flags |= WUNTRACED;
4323                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4324                 pid = waitpid(-1, &status, wait_flags);
4325         }
4326         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4327                                 pid, status, errno, strerror(errno)));
4328         thisjob = NULL;
4329         if (pid <= 0)
4330                 goto out;
4331
4332         for (jp = curjob; jp; jp = jp->prev_job) {
4333                 int jobstate;
4334                 struct procstat *ps;
4335                 struct procstat *psend;
4336                 if (jp->state == JOBDONE)
4337                         continue;
4338                 jobstate = JOBDONE;
4339                 ps = jp->ps;
4340                 psend = ps + jp->nprocs;
4341                 do {
4342                         if (ps->ps_pid == pid) {
4343                                 TRACE(("Job %d: changing status of proc %d "
4344                                         "from 0x%x to 0x%x\n",
4345                                         jobno(jp), pid, ps->ps_status, status));
4346                                 ps->ps_status = status;
4347                                 thisjob = jp;
4348                         }
4349                         if (ps->ps_status == -1)
4350                                 jobstate = JOBRUNNING;
4351 #if JOBS
4352                         if (jobstate == JOBRUNNING)
4353                                 continue;
4354                         if (WIFSTOPPED(ps->ps_status)) {
4355                                 jp->stopstatus = ps->ps_status;
4356                                 jobstate = JOBSTOPPED;
4357                         }
4358 #endif
4359                 } while (++ps < psend);
4360                 if (!thisjob)
4361                         continue;
4362
4363                 /* Found the job where one of its processes changed its state.
4364                  * Is there at least one live and running process in this job? */
4365                 if (jobstate != JOBRUNNING) {
4366                         /* No. All live processes in the job are stopped
4367                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4368                          */
4369                         thisjob->changed = 1;
4370                         if (thisjob->state != jobstate) {
4371                                 TRACE(("Job %d: changing state from %d to %d\n",
4372                                         jobno(thisjob), thisjob->state, jobstate));
4373                                 thisjob->state = jobstate;
4374 #if JOBS
4375                                 if (jobstate == JOBSTOPPED)
4376                                         set_curjob(thisjob, CUR_STOPPED);
4377 #endif
4378                         }
4379                 }
4380                 goto out;
4381         }
4382         /* The process wasn't found in job list */
4383 #if JOBS
4384         if (!WIFSTOPPED(status))
4385                 jobless--;
4386 #endif
4387  out:
4388         INT_ON;
4389
4390 #if BASH_WAIT_N
4391         if (want_jobexitstatus) {
4392                 pid = -1;
4393                 if (thisjob && thisjob->state == JOBDONE)
4394                         pid = thisjob->ps[thisjob->nprocs - 1].ps_status;
4395         }
4396 #endif
4397         if (thisjob && thisjob == job) {
4398                 char s[48 + 1];
4399                 int len;
4400
4401                 len = sprint_status48(s, status, 1);
4402                 if (len) {
4403                         s[len] = '\n';
4404                         s[len + 1] = '\0';
4405                         out2str(s);
4406                 }
4407         }
4408         return pid;
4409 }
4410
4411 #if JOBS
4412 static void
4413 showjob(struct job *jp, int mode)
4414 {
4415         struct procstat *ps;
4416         struct procstat *psend;
4417         int col;
4418         int indent_col;
4419         char s[16 + 16 + 48];
4420         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4421
4422         ps = jp->ps;
4423
4424         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4425                 /* just output process (group) id of pipeline */
4426                 fprintf(out, "%d\n", ps->ps_pid);
4427                 return;
4428         }
4429
4430         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4431         indent_col = col;
4432
4433         if (jp == curjob)
4434                 s[col - 3] = '+';
4435         else if (curjob && jp == curjob->prev_job)
4436                 s[col - 3] = '-';
4437
4438         if (mode & SHOW_PIDS)
4439                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4440
4441         psend = ps + jp->nprocs;
4442
4443         if (jp->state == JOBRUNNING) {
4444                 strcpy(s + col, "Running");
4445                 col += sizeof("Running") - 1;
4446         } else {
4447                 int status = psend[-1].ps_status;
4448                 if (jp->state == JOBSTOPPED)
4449                         status = jp->stopstatus;
4450                 col += sprint_status48(s + col, status, 0);
4451         }
4452         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4453
4454         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4455          * or prints several "PID             | <cmdN>" lines,
4456          * depending on SHOW_PIDS bit.
4457          * We do not print status of individual processes
4458          * between PID and <cmdN>. bash does it, but not very well:
4459          * first line shows overall job status, not process status,
4460          * making it impossible to know 1st process status.
4461          */
4462         goto start;
4463         do {
4464                 /* for each process */
4465                 s[0] = '\0';
4466                 col = 33;
4467                 if (mode & SHOW_PIDS)
4468                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4469  start:
4470                 fprintf(out, "%s%*c%s%s",
4471                                 s,
4472                                 33 - col >= 0 ? 33 - col : 0, ' ',
4473                                 ps == jp->ps ? "" : "| ",
4474                                 ps->ps_cmd
4475                 );
4476         } while (++ps != psend);
4477         newline_and_flush(out);
4478
4479         jp->changed = 0;
4480
4481         if (jp->state == JOBDONE) {
4482                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4483                 freejob(jp);
4484         }
4485 }
4486
4487 /*
4488  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4489  * statuses have changed since the last call to showjobs.
4490  */
4491 static void
4492 showjobs(int mode)
4493 {
4494         struct job *jp;
4495
4496         TRACE(("showjobs(0x%x) called\n", mode));
4497
4498         /* Handle all finished jobs */
4499         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4500                 continue;
4501
4502         for (jp = curjob; jp; jp = jp->prev_job) {
4503                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4504                         showjob(jp, mode);
4505                 }
4506         }
4507 }
4508
4509 static int FAST_FUNC
4510 jobscmd(int argc UNUSED_PARAM, char **argv)
4511 {
4512         int mode, m;
4513
4514         mode = 0;
4515         while ((m = nextopt("lp")) != '\0') {
4516                 if (m == 'l')
4517                         mode |= SHOW_PIDS;
4518                 else
4519                         mode |= SHOW_ONLY_PGID;
4520         }
4521
4522         argv = argptr;
4523         if (*argv) {
4524                 do
4525                         showjob(getjob(*argv, 0), mode);
4526                 while (*++argv);
4527         } else {
4528                 showjobs(mode);
4529         }
4530
4531         return 0;
4532 }
4533 #endif /* JOBS */
4534
4535 /* Called only on finished or stopped jobs (no members are running) */
4536 static int
4537 getstatus(struct job *job)
4538 {
4539         int status;
4540         int retval;
4541         struct procstat *ps;
4542
4543         /* Fetch last member's status */
4544         ps = job->ps + job->nprocs - 1;
4545         status = ps->ps_status;
4546         if (pipefail) {
4547                 /* "set -o pipefail" mode: use last _nonzero_ status */
4548                 while (status == 0 && --ps >= job->ps)
4549                         status = ps->ps_status;
4550         }
4551
4552         retval = WEXITSTATUS(status);
4553         if (!WIFEXITED(status)) {
4554 #if JOBS
4555                 retval = WSTOPSIG(status);
4556                 if (!WIFSTOPPED(status))
4557 #endif
4558                 {
4559                         /* XXX: limits number of signals */
4560                         retval = WTERMSIG(status);
4561 #if JOBS
4562                         if (retval == SIGINT)
4563                                 job->sigint = 1;
4564 #endif
4565                 }
4566                 retval += 128;
4567         }
4568         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4569                 jobno(job), job->nprocs, status, retval));
4570         return retval;
4571 }
4572
4573 static int FAST_FUNC
4574 waitcmd(int argc UNUSED_PARAM, char **argv)
4575 {
4576         struct job *job;
4577         int retval;
4578         struct job *jp;
4579 #if BASH_WAIT_N
4580         int status;
4581         char one = nextopt("n");
4582 #else
4583         nextopt(nullstr);
4584 #endif
4585         retval = 0;
4586
4587         argv = argptr;
4588         if (!argv[0]) {
4589                 /* wait for all jobs / one job if -n */
4590                 for (;;) {
4591                         jp = curjob;
4592 #if BASH_WAIT_N
4593                         if (one && !jp)
4594                                 /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */
4595                                 retval = 127;
4596 #endif
4597                         while (1) {
4598                                 if (!jp) /* no running procs */
4599                                         goto ret;
4600                                 if (jp->state == JOBRUNNING)
4601                                         break;
4602                                 jp->waited = 1;
4603                                 jp = jp->prev_job;
4604                         }
4605         /* man bash:
4606          * "When bash is waiting for an asynchronous command via
4607          * the wait builtin, the reception of a signal for which a trap
4608          * has been set will cause the wait builtin to return immediately
4609          * with an exit status greater than 128, immediately after which
4610          * the trap is executed."
4611          */
4612 #if BASH_WAIT_N
4613                         status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL);
4614 #else
4615                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4616 #endif
4617         /* if child sends us a signal *and immediately exits*,
4618          * dowait() returns pid > 0. Check this case,
4619          * not "if (dowait() < 0)"!
4620          */
4621                         if (pending_sig)
4622                                 goto sigout;
4623 #if BASH_WAIT_N
4624                         if (one) {
4625                                 /* wait -n waits for one _job_, not one _process_.
4626                                  *  date; sleep 3 & sleep 2 | sleep 1 & wait -n; date
4627                                  * should wait for 2 seconds. Not 1 or 3.
4628                                  */
4629                                 if (status != -1 && !WIFSTOPPED(status)) {
4630                                         retval = WEXITSTATUS(status);
4631                                         if (WIFSIGNALED(status))
4632                                                 retval = WTERMSIG(status) + 128;
4633                                         goto ret;
4634                                 }
4635                         }
4636 #endif
4637                 }
4638         }
4639
4640         retval = 127;
4641         do {
4642                 if (**argv != '%') {
4643                         pid_t pid = number(*argv);
4644                         job = curjob;
4645                         while (1) {
4646                                 if (!job)
4647                                         goto repeat;
4648                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4649                                         break;
4650                                 job = job->prev_job;
4651                         }
4652                 } else {
4653                         job = getjob(*argv, 0);
4654                 }
4655                 /* loop until process terminated or stopped */
4656                 while (job->state == JOBRUNNING) {
4657                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4658                         if (pending_sig)
4659                                 goto sigout;
4660                 }
4661                 job->waited = 1;
4662                 retval = getstatus(job);
4663  repeat: ;
4664         } while (*++argv);
4665
4666  ret:
4667         return retval;
4668  sigout:
4669         retval = 128 + pending_sig;
4670         return retval;
4671 }
4672
4673 static struct job *
4674 growjobtab(void)
4675 {
4676         size_t len;
4677         ptrdiff_t offset;
4678         struct job *jp, *jq;
4679
4680         len = njobs * sizeof(*jp);
4681         jq = jobtab;
4682         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4683
4684         offset = (char *)jp - (char *)jq;
4685         if (offset) {
4686                 /* Relocate pointers */
4687                 size_t l = len;
4688
4689                 jq = (struct job *)((char *)jq + l);
4690                 while (l) {
4691                         l -= sizeof(*jp);
4692                         jq--;
4693 #define joff(p) ((struct job *)((char *)(p) + l))
4694 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4695                         if (joff(jp)->ps == &jq->ps0)
4696                                 jmove(joff(jp)->ps);
4697                         if (joff(jp)->prev_job)
4698                                 jmove(joff(jp)->prev_job);
4699                 }
4700                 if (curjob)
4701                         jmove(curjob);
4702 #undef joff
4703 #undef jmove
4704         }
4705
4706         njobs += 4;
4707         jobtab = jp;
4708         jp = (struct job *)((char *)jp + len);
4709         jq = jp + 3;
4710         do {
4711                 jq->used = 0;
4712         } while (--jq >= jp);
4713         return jp;
4714 }
4715
4716 /*
4717  * Return a new job structure.
4718  * Called with interrupts off.
4719  */
4720 static struct job *
4721 makejob(/*union node *node,*/ int nprocs)
4722 {
4723         int i;
4724         struct job *jp;
4725
4726         for (i = njobs, jp = jobtab; ; jp++) {
4727                 if (--i < 0) {
4728                         jp = growjobtab();
4729                         break;
4730                 }
4731                 if (jp->used == 0)
4732                         break;
4733                 if (jp->state != JOBDONE || !jp->waited)
4734                         continue;
4735 #if JOBS
4736                 if (doing_jobctl)
4737                         continue;
4738 #endif
4739                 freejob(jp);
4740                 break;
4741         }
4742         memset(jp, 0, sizeof(*jp));
4743 #if JOBS
4744         /* jp->jobctl is a bitfield.
4745          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4746         if (doing_jobctl)
4747                 jp->jobctl = 1;
4748 #endif
4749         jp->prev_job = curjob;
4750         curjob = jp;
4751         jp->used = 1;
4752         jp->ps = &jp->ps0;
4753         if (nprocs > 1) {
4754                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4755         }
4756         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4757                                 jobno(jp)));
4758         return jp;
4759 }
4760
4761 #if JOBS
4762 /*
4763  * Return a string identifying a command (to be printed by the
4764  * jobs command).
4765  */
4766 static char *cmdnextc;
4767
4768 static void
4769 cmdputs(const char *s)
4770 {
4771         static const char vstype[VSTYPE + 1][3] = {
4772                 "", "}", "-", "+", "?", "=",
4773                 "%", "%%", "#", "##"
4774                 IF_BASH_SUBSTR(, ":")
4775                 IF_BASH_PATTERN_SUBST(, "/", "//")
4776         };
4777
4778         const char *p, *str;
4779         char cc[2];
4780         char *nextc;
4781         unsigned char c;
4782         unsigned char subtype = 0;
4783         int quoted = 0;
4784
4785         cc[1] = '\0';
4786         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4787         p = s;
4788         while ((c = *p++) != '\0') {
4789                 str = NULL;
4790                 switch (c) {
4791                 case CTLESC:
4792                         c = *p++;
4793                         break;
4794                 case CTLVAR:
4795                         subtype = *p++;
4796                         if ((subtype & VSTYPE) == VSLENGTH)
4797                                 str = "${#";
4798                         else
4799                                 str = "${";
4800                         goto dostr;
4801                 case CTLENDVAR:
4802                         str = "\"}" + !(quoted & 1);
4803                         quoted >>= 1;
4804                         subtype = 0;
4805                         goto dostr;
4806                 case CTLBACKQ:
4807                         str = "$(...)";
4808                         goto dostr;
4809 #if ENABLE_FEATURE_SH_MATH
4810                 case CTLARI:
4811                         str = "$((";
4812                         goto dostr;
4813                 case CTLENDARI:
4814                         str = "))";
4815                         goto dostr;
4816 #endif
4817                 case CTLQUOTEMARK:
4818                         quoted ^= 1;
4819                         c = '"';
4820                         break;
4821                 case '=':
4822                         if (subtype == 0)
4823                                 break;
4824                         if ((subtype & VSTYPE) != VSNORMAL)
4825                                 quoted <<= 1;
4826                         str = vstype[subtype & VSTYPE];
4827                         if (subtype & VSNUL)
4828                                 c = ':';
4829                         else
4830                                 goto checkstr;
4831                         break;
4832                 case '\'':
4833                 case '\\':
4834                 case '"':
4835                 case '$':
4836                         /* These can only happen inside quotes */
4837                         cc[0] = c;
4838                         str = cc;
4839 //FIXME:
4840 // $ true $$ &
4841 // $ <cr>
4842 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4843                         c = '\\';
4844                         break;
4845                 default:
4846                         break;
4847                 }
4848                 USTPUTC(c, nextc);
4849  checkstr:
4850                 if (!str)
4851                         continue;
4852  dostr:
4853                 while ((c = *str++) != '\0') {
4854                         USTPUTC(c, nextc);
4855                 }
4856         } /* while *p++ not NUL */
4857
4858         if (quoted & 1) {
4859                 USTPUTC('"', nextc);
4860         }
4861         *nextc = 0;
4862         cmdnextc = nextc;
4863 }
4864
4865 /* cmdtxt() and cmdlist() call each other */
4866 static void cmdtxt(union node *n);
4867
4868 static void
4869 cmdlist(union node *np, int sep)
4870 {
4871         for (; np; np = np->narg.next) {
4872                 if (!sep)
4873                         cmdputs(" ");
4874                 cmdtxt(np);
4875                 if (sep && np->narg.next)
4876                         cmdputs(" ");
4877         }
4878 }
4879
4880 static void
4881 cmdtxt(union node *n)
4882 {
4883         union node *np;
4884         struct nodelist *lp;
4885         const char *p;
4886
4887         if (!n)
4888                 return;
4889         switch (n->type) {
4890         default:
4891 #if DEBUG
4892                 abort();
4893 #endif
4894         case NPIPE:
4895                 lp = n->npipe.cmdlist;
4896                 for (;;) {
4897                         cmdtxt(lp->n);
4898                         lp = lp->next;
4899                         if (!lp)
4900                                 break;
4901                         cmdputs(" | ");
4902                 }
4903                 break;
4904         case NSEMI:
4905                 p = "; ";
4906                 goto binop;
4907         case NAND:
4908                 p = " && ";
4909                 goto binop;
4910         case NOR:
4911                 p = " || ";
4912  binop:
4913                 cmdtxt(n->nbinary.ch1);
4914                 cmdputs(p);
4915                 n = n->nbinary.ch2;
4916                 goto donode;
4917         case NREDIR:
4918         case NBACKGND:
4919                 n = n->nredir.n;
4920                 goto donode;
4921         case NNOT:
4922                 cmdputs("!");
4923                 n = n->nnot.com;
4924  donode:
4925                 cmdtxt(n);
4926                 break;
4927         case NIF:
4928                 cmdputs("if ");
4929                 cmdtxt(n->nif.test);
4930                 cmdputs("; then ");
4931                 if (n->nif.elsepart) {
4932                         cmdtxt(n->nif.ifpart);
4933                         cmdputs("; else ");
4934                         n = n->nif.elsepart;
4935                 } else {
4936                         n = n->nif.ifpart;
4937                 }
4938                 p = "; fi";
4939                 goto dotail;
4940         case NSUBSHELL:
4941                 cmdputs("(");
4942                 n = n->nredir.n;
4943                 p = ")";
4944                 goto dotail;
4945         case NWHILE:
4946                 p = "while ";
4947                 goto until;
4948         case NUNTIL:
4949                 p = "until ";
4950  until:
4951                 cmdputs(p);
4952                 cmdtxt(n->nbinary.ch1);
4953                 n = n->nbinary.ch2;
4954                 p = "; done";
4955  dodo:
4956                 cmdputs("; do ");
4957  dotail:
4958                 cmdtxt(n);
4959                 goto dotail2;
4960         case NFOR:
4961                 cmdputs("for ");
4962                 cmdputs(n->nfor.var);
4963                 cmdputs(" in ");
4964                 cmdlist(n->nfor.args, 1);
4965                 n = n->nfor.body;
4966                 p = "; done";
4967                 goto dodo;
4968         case NDEFUN:
4969                 cmdputs(n->ndefun.text);
4970                 p = "() { ... }";
4971                 goto dotail2;
4972         case NCMD:
4973                 cmdlist(n->ncmd.args, 1);
4974                 cmdlist(n->ncmd.redirect, 0);
4975                 break;
4976         case NARG:
4977                 p = n->narg.text;
4978  dotail2:
4979                 cmdputs(p);
4980                 break;
4981         case NHERE:
4982         case NXHERE:
4983                 p = "<<...";
4984                 goto dotail2;
4985         case NCASE:
4986                 cmdputs("case ");
4987                 cmdputs(n->ncase.expr->narg.text);
4988                 cmdputs(" in ");
4989                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4990                         cmdtxt(np->nclist.pattern);
4991                         cmdputs(") ");
4992                         cmdtxt(np->nclist.body);
4993                         cmdputs(";; ");
4994                 }
4995                 p = "esac";
4996                 goto dotail2;
4997         case NTO:
4998                 p = ">";
4999                 goto redir;
5000         case NCLOBBER:
5001                 p = ">|";
5002                 goto redir;
5003         case NAPPEND:
5004                 p = ">>";
5005                 goto redir;
5006 #if BASH_REDIR_OUTPUT
5007         case NTO2:
5008 #endif
5009         case NTOFD:
5010                 p = ">&";
5011                 goto redir;
5012         case NFROM:
5013                 p = "<";
5014                 goto redir;
5015         case NFROMFD:
5016                 p = "<&";
5017                 goto redir;
5018         case NFROMTO:
5019                 p = "<>";
5020  redir:
5021                 cmdputs(utoa(n->nfile.fd));
5022                 cmdputs(p);
5023                 if (n->type == NTOFD || n->type == NFROMFD) {
5024                         if (n->ndup.dupfd >= 0)
5025                                 cmdputs(utoa(n->ndup.dupfd));
5026                         else
5027                                 cmdputs("-");
5028                         break;
5029                 }
5030                 n = n->nfile.fname;
5031                 goto donode;
5032         }
5033 }
5034
5035 static char *
5036 commandtext(union node *n)
5037 {
5038         char *name;
5039
5040         STARTSTACKSTR(cmdnextc);
5041         cmdtxt(n);
5042         name = stackblock();
5043         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
5044         return ckstrdup(name);
5045 }
5046 #endif /* JOBS */
5047
5048 /*
5049  * Fork off a subshell.  If we are doing job control, give the subshell its
5050  * own process group.  Jp is a job structure that the job is to be added to.
5051  * N is the command that will be evaluated by the child.  Both jp and n may
5052  * be NULL.  The mode parameter can be one of the following:
5053  *      FORK_FG - Fork off a foreground process.
5054  *      FORK_BG - Fork off a background process.
5055  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
5056  *                   process group even if job control is on.
5057  *
5058  * When job control is turned off, background processes have their standard
5059  * input redirected to /dev/null (except for the second and later processes
5060  * in a pipeline).
5061  *
5062  * Called with interrupts off.
5063  */
5064 /*
5065  * Clear traps on a fork.
5066  */
5067 static void
5068 clear_traps(void)
5069 {
5070         char **tp;
5071
5072         INT_OFF;
5073         for (tp = trap; tp < &trap[NSIG]; tp++) {
5074                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
5075                         if (trap_ptr == trap)
5076                                 free(*tp);
5077                         /* else: it "belongs" to trap_ptr vector, don't free */
5078                         *tp = NULL;
5079                         if ((tp - trap) != 0)
5080                                 setsignal(tp - trap);
5081                 }
5082         }
5083         may_have_traps = 0;
5084         INT_ON;
5085 }
5086
5087 /* Lives far away from here, needed for forkchild */
5088 static void closescript(void);
5089
5090 /* Called after fork(), in child */
5091 /* jp and n are NULL when called by openhere() for heredoc support */
5092 static NOINLINE void
5093 forkchild(struct job *jp, union node *n, int mode)
5094 {
5095         int oldlvl;
5096
5097         TRACE(("Child shell %d\n", getpid()));
5098         oldlvl = shlvl;
5099         shlvl++;
5100
5101         /* man bash: "Non-builtin commands run by bash have signal handlers
5102          * set to the values inherited by the shell from its parent".
5103          * Do we do it correctly? */
5104
5105         closescript();
5106
5107         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5108          && n && n->type == NCMD        /* is it single cmd? */
5109         /* && n->ncmd.args->type == NARG - always true? */
5110          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5111          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5112         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5113         ) {
5114                 TRACE(("Trap hack\n"));
5115                 /* Awful hack for `trap` or $(trap).
5116                  *
5117                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5118                  * contains an example where "trap" is executed in a subshell:
5119                  *
5120                  * save_traps=$(trap)
5121                  * ...
5122                  * eval "$save_traps"
5123                  *
5124                  * Standard does not say that "trap" in subshell shall print
5125                  * parent shell's traps. It only says that its output
5126                  * must have suitable form, but then, in the above example
5127                  * (which is not supposed to be normative), it implies that.
5128                  *
5129                  * bash (and probably other shell) does implement it
5130                  * (traps are reset to defaults, but "trap" still shows them),
5131                  * but as a result, "trap" logic is hopelessly messed up:
5132                  *
5133                  * # trap
5134                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5135                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5136                  * # true | trap   <--- trap is in subshell - no output (ditto)
5137                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5138                  * trap -- 'echo Ho' SIGWINCH
5139                  * # echo `(trap)`         <--- in subshell in subshell - output
5140                  * trap -- 'echo Ho' SIGWINCH
5141                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5142                  * trap -- 'echo Ho' SIGWINCH
5143                  *
5144                  * The rules when to forget and when to not forget traps
5145                  * get really complex and nonsensical.
5146                  *
5147                  * Our solution: ONLY bare $(trap) or `trap` is special.
5148                  */
5149                 /* Save trap handler strings for trap builtin to print */
5150                 trap_ptr = xmemdup(trap, sizeof(trap));
5151                 /* Fall through into clearing traps */
5152         }
5153         clear_traps();
5154 #if JOBS
5155         /* do job control only in root shell */
5156         doing_jobctl = 0;
5157         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5158                 pid_t pgrp;
5159
5160                 if (jp->nprocs == 0)
5161                         pgrp = getpid();
5162                 else
5163                         pgrp = jp->ps[0].ps_pid;
5164                 /* this can fail because we are doing it in the parent also */
5165                 setpgid(0, pgrp);
5166                 if (mode == FORK_FG)
5167                         xtcsetpgrp(ttyfd, pgrp);
5168                 setsignal(SIGTSTP);
5169                 setsignal(SIGTTOU);
5170         } else
5171 #endif
5172         if (mode == FORK_BG) {
5173                 /* man bash: "When job control is not in effect,
5174                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5175                 ignoresig(SIGINT);
5176                 ignoresig(SIGQUIT);
5177                 if (jp->nprocs == 0) {
5178                         close(0);
5179                         if (open(bb_dev_null, O_RDONLY) != 0)
5180                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5181                 }
5182         }
5183         if (oldlvl == 0) {
5184                 if (iflag) { /* why if iflag only? */
5185                         setsignal(SIGINT);
5186                         setsignal(SIGTERM);
5187                 }
5188                 /* man bash:
5189                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5190                  * commands run by bash have signal handlers
5191                  * set to the values inherited by the shell
5192                  * from its parent".
5193                  * Take care of the second rule: */
5194                 setsignal(SIGQUIT);
5195         }
5196 #if JOBS
5197         if (n && n->type == NCMD
5198          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5199         ) {
5200                 TRACE(("Job hack\n"));
5201                 /* "jobs": we do not want to clear job list for it,
5202                  * instead we remove only _its_ own_ job from job list.
5203                  * This makes "jobs .... | cat" more useful.
5204                  */
5205                 freejob(curjob);
5206                 return;
5207         }
5208 #endif
5209         for (jp = curjob; jp; jp = jp->prev_job)
5210                 freejob(jp);
5211         jobless = 0;
5212 }
5213
5214 /* Called after fork(), in parent */
5215 #if !JOBS
5216 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5217 #endif
5218 static void
5219 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5220 {
5221         TRACE(("In parent shell: child = %d\n", pid));
5222         if (!jp) {
5223                 /* jp is NULL when called by openhere() for heredoc support */
5224                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5225                         continue;
5226                 jobless++;
5227                 return;
5228         }
5229 #if JOBS
5230         if (mode != FORK_NOJOB && jp->jobctl) {
5231                 int pgrp;
5232
5233                 if (jp->nprocs == 0)
5234                         pgrp = pid;
5235                 else
5236                         pgrp = jp->ps[0].ps_pid;
5237                 /* This can fail because we are doing it in the child also */
5238                 setpgid(pid, pgrp);
5239         }
5240 #endif
5241         if (mode == FORK_BG) {
5242                 backgndpid = pid;               /* set $! */
5243                 set_curjob(jp, CUR_RUNNING);
5244         }
5245         if (jp) {
5246                 struct procstat *ps = &jp->ps[jp->nprocs++];
5247                 ps->ps_pid = pid;
5248                 ps->ps_status = -1;
5249                 ps->ps_cmd = nullstr;
5250 #if JOBS
5251                 if (doing_jobctl && n)
5252                         ps->ps_cmd = commandtext(n);
5253 #endif
5254         }
5255 }
5256
5257 /* jp and n are NULL when called by openhere() for heredoc support */
5258 static int
5259 forkshell(struct job *jp, union node *n, int mode)
5260 {
5261         int pid;
5262
5263         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5264         pid = fork();
5265         if (pid < 0) {
5266                 TRACE(("Fork failed, errno=%d", errno));
5267                 if (jp)
5268                         freejob(jp);
5269                 ash_msg_and_raise_perror("can't fork");
5270         }
5271         if (pid == 0) {
5272                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5273                 forkchild(jp, n, mode);
5274         } else {
5275                 forkparent(jp, n, mode, pid);
5276         }
5277         return pid;
5278 }
5279
5280 /*
5281  * Wait for job to finish.
5282  *
5283  * Under job control we have the problem that while a child process
5284  * is running interrupts generated by the user are sent to the child
5285  * but not to the shell.  This means that an infinite loop started by
5286  * an interactive user may be hard to kill.  With job control turned off,
5287  * an interactive user may place an interactive program inside a loop.
5288  * If the interactive program catches interrupts, the user doesn't want
5289  * these interrupts to also abort the loop.  The approach we take here
5290  * is to have the shell ignore interrupt signals while waiting for a
5291  * foreground process to terminate, and then send itself an interrupt
5292  * signal if the child process was terminated by an interrupt signal.
5293  * Unfortunately, some programs want to do a bit of cleanup and then
5294  * exit on interrupt; unless these processes terminate themselves by
5295  * sending a signal to themselves (instead of calling exit) they will
5296  * confuse this approach.
5297  *
5298  * Called with interrupts off.
5299  */
5300 static int
5301 waitforjob(struct job *jp)
5302 {
5303         int st;
5304
5305         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5306
5307         INT_OFF;
5308         while (jp->state == JOBRUNNING) {
5309                 /* In non-interactive shells, we _can_ get
5310                  * a keyboard signal here and be EINTRed,
5311                  * but we just loop back, waiting for command to complete.
5312                  *
5313                  * man bash:
5314                  * "If bash is waiting for a command to complete and receives
5315                  * a signal for which a trap has been set, the trap
5316                  * will not be executed until the command completes."
5317                  *
5318                  * Reality is that even if trap is not set, bash
5319                  * will not act on the signal until command completes.
5320                  * Try this. sleep5intoff.c:
5321                  * #include <signal.h>
5322                  * #include <unistd.h>
5323                  * int main() {
5324                  *         sigset_t set;
5325                  *         sigemptyset(&set);
5326                  *         sigaddset(&set, SIGINT);
5327                  *         sigaddset(&set, SIGQUIT);
5328                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5329                  *         sleep(5);
5330                  *         return 0;
5331                  * }
5332                  * $ bash -c './sleep5intoff; echo hi'
5333                  * ^C^C^C^C <--- pressing ^C once a second
5334                  * $ _
5335                  * $ bash -c './sleep5intoff; echo hi'
5336                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5337                  * $ _
5338                  */
5339                 dowait(DOWAIT_BLOCK, jp);
5340         }
5341         INT_ON;
5342
5343         st = getstatus(jp);
5344 #if JOBS
5345         if (jp->jobctl) {
5346                 xtcsetpgrp(ttyfd, rootpid);
5347                 restore_tty_if_stopped_or_signaled(jp);
5348
5349                 /*
5350                  * This is truly gross.
5351                  * If we're doing job control, then we did a TIOCSPGRP which
5352                  * caused us (the shell) to no longer be in the controlling
5353                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5354                  * intuit from the subprocess exit status whether a SIGINT
5355                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5356                  */
5357                 if (jp->sigint) /* TODO: do the same with all signals */
5358                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5359         }
5360         if (jp->state == JOBDONE)
5361 #endif
5362                 freejob(jp);
5363         return st;
5364 }
5365
5366 /*
5367  * return 1 if there are stopped jobs, otherwise 0
5368  */
5369 static int
5370 stoppedjobs(void)
5371 {
5372         struct job *jp;
5373         int retval;
5374
5375         retval = 0;
5376         if (job_warning)
5377                 goto out;
5378         jp = curjob;
5379         if (jp && jp->state == JOBSTOPPED) {
5380                 out2str("You have stopped jobs.\n");
5381                 job_warning = 2;
5382                 retval++;
5383         }
5384  out:
5385         return retval;
5386 }
5387
5388
5389 /*
5390  * Code for dealing with input/output redirection.
5391  */
5392
5393 #undef EMPTY
5394 #undef CLOSED
5395 #define EMPTY -2                /* marks an unused slot in redirtab */
5396 #define CLOSED -1               /* marks a slot of previously-closed fd */
5397
5398 /*
5399  * Handle here documents.  Normally we fork off a process to write the
5400  * data to a pipe.  If the document is short, we can stuff the data in
5401  * the pipe without forking.
5402  */
5403 /* openhere needs this forward reference */
5404 static void expandhere(union node *arg, int fd);
5405 static int
5406 openhere(union node *redir)
5407 {
5408         int pip[2];
5409         size_t len = 0;
5410
5411         if (pipe(pip) < 0)
5412                 ash_msg_and_raise_perror("can't create pipe");
5413         if (redir->type == NHERE) {
5414                 len = strlen(redir->nhere.doc->narg.text);
5415                 if (len <= PIPE_BUF) {
5416                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5417                         goto out;
5418                 }
5419         }
5420         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5421                 /* child */
5422                 close(pip[0]);
5423                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5424                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5425                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5426                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5427                 signal(SIGPIPE, SIG_DFL);
5428                 if (redir->type == NHERE)
5429                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5430                 else /* NXHERE */
5431                         expandhere(redir->nhere.doc, pip[1]);
5432                 _exit(EXIT_SUCCESS);
5433         }
5434  out:
5435         close(pip[1]);
5436         return pip[0];
5437 }
5438
5439 static int
5440 openredirect(union node *redir)
5441 {
5442         struct stat sb;
5443         char *fname;
5444         int f;
5445
5446         switch (redir->nfile.type) {
5447 /* Can't happen, our single caller does this itself */
5448 //      case NTOFD:
5449 //      case NFROMFD:
5450 //              return -1;
5451         case NHERE:
5452         case NXHERE:
5453                 return openhere(redir);
5454         }
5455
5456         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5457          * allocated space. Do it only when we know it is safe.
5458          */
5459         fname = redir->nfile.expfname;
5460
5461         switch (redir->nfile.type) {
5462         default:
5463 #if DEBUG
5464                 abort();
5465 #endif
5466         case NFROM:
5467                 f = open(fname, O_RDONLY);
5468                 if (f < 0)
5469                         goto eopen;
5470                 break;
5471         case NFROMTO:
5472                 f = open(fname, O_RDWR|O_CREAT, 0666);
5473                 if (f < 0)
5474                         goto ecreate;
5475                 break;
5476         case NTO:
5477 #if BASH_REDIR_OUTPUT
5478         case NTO2:
5479 #endif
5480                 /* Take care of noclobber mode. */
5481                 if (Cflag) {
5482                         if (stat(fname, &sb) < 0) {
5483                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5484                                 if (f < 0)
5485                                         goto ecreate;
5486                         } else if (!S_ISREG(sb.st_mode)) {
5487                                 f = open(fname, O_WRONLY, 0666);
5488                                 if (f < 0)
5489                                         goto ecreate;
5490                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5491                                         close(f);
5492                                         errno = EEXIST;
5493                                         goto ecreate;
5494                                 }
5495                         } else {
5496                                 errno = EEXIST;
5497                                 goto ecreate;
5498                         }
5499                         break;
5500                 }
5501                 /* FALLTHROUGH */
5502         case NCLOBBER:
5503                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5504                 if (f < 0)
5505                         goto ecreate;
5506                 break;
5507         case NAPPEND:
5508                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5509                 if (f < 0)
5510                         goto ecreate;
5511                 break;
5512         }
5513
5514         return f;
5515  ecreate:
5516         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5517  eopen:
5518         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5519 }
5520
5521 /*
5522  * Copy a file descriptor to be >= 10. Throws exception on error.
5523  */
5524 static int
5525 savefd(int from)
5526 {
5527         int newfd;
5528         int err;
5529
5530         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5531         err = newfd < 0 ? errno : 0;
5532         if (err != EBADF) {
5533                 if (err)
5534                         ash_msg_and_raise_perror("%d", from);
5535                 close(from);
5536                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5537                         close_on_exec_on(newfd);
5538         }
5539
5540         return newfd;
5541 }
5542 static int
5543 dup2_or_raise(int from, int to)
5544 {
5545         int newfd;
5546
5547         newfd = (from != to) ? dup2(from, to) : to;
5548         if (newfd < 0) {
5549                 /* Happens when source fd is not open: try "echo >&99" */
5550                 ash_msg_and_raise_perror("%d", from);
5551         }
5552         return newfd;
5553 }
5554 static int
5555 dup_CLOEXEC(int fd, int avoid_fd)
5556 {
5557         int newfd;
5558  repeat:
5559         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5560         if (newfd >= 0) {
5561                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5562                         close_on_exec_on(newfd);
5563         } else { /* newfd < 0 */
5564                 if (errno == EBUSY)
5565                         goto repeat;
5566                 if (errno == EINTR)
5567                         goto repeat;
5568         }
5569         return newfd;
5570 }
5571 static int
5572 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5573 {
5574         int newfd;
5575  repeat:
5576         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5577         if (newfd < 0) {
5578                 if (errno == EBUSY)
5579                         goto repeat;
5580                 if (errno == EINTR)
5581                         goto repeat;
5582                 /* fd was not open? */
5583                 if (errno == EBADF)
5584                         return fd;
5585                 ash_msg_and_raise_perror("%d", newfd);
5586         }
5587         if (F_DUPFD_CLOEXEC == F_DUPFD)
5588                 close_on_exec_on(newfd);
5589         close(fd);
5590         return newfd;
5591 }
5592
5593 /* Struct def and variable are moved down to the first usage site */
5594 struct squirrel {
5595         int orig_fd;
5596         int moved_to;
5597 };
5598 struct redirtab {
5599         struct redirtab *next;
5600         int pair_count;
5601         struct squirrel two_fd[];
5602 };
5603 #define redirlist (G_var.redirlist)
5604
5605 static void
5606 add_squirrel_closed(struct redirtab *sq, int fd)
5607 {
5608         int i;
5609
5610         if (!sq)
5611                 return;
5612
5613         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5614                 /* If we collide with an already moved fd... */
5615                 if (fd == sq->two_fd[i].orig_fd) {
5616                         /* Examples:
5617                          * "echo 3>FILE 3>&- 3>FILE"
5618                          * "echo 3>&- 3>FILE"
5619                          * No need for last redirect to insert
5620                          * another "need to close 3" indicator.
5621                          */
5622                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5623                         return;
5624                 }
5625         }
5626         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5627         sq->two_fd[i].orig_fd = fd;
5628         sq->two_fd[i].moved_to = CLOSED;
5629 }
5630
5631 static int
5632 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5633 {
5634         int i, new_fd;
5635
5636         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5637                 avoid_fd = 9;
5638
5639 #if JOBS
5640         if (fd == ttyfd) {
5641                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5642                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5643                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5644                 return 1; /* "we closed fd" */
5645         }
5646 #endif
5647         /* Are we called from redirect(0)? E.g. redirect
5648          * in a forked child. No need to save fds,
5649          * we aren't going to use them anymore, ok to trash.
5650          */
5651         if (!sq)
5652                 return 0;
5653
5654         /* If this one of script's fds? */
5655         if (fd != 0) {
5656                 struct parsefile *pf = g_parsefile;
5657                 while (pf) {
5658                         /* We skip fd == 0 case because of the following:
5659                          * $ ash  # running ash interactively
5660                          * $ . ./script.sh
5661                          * and in script.sh: "exec 9>&0".
5662                          * Even though top-level pf_fd _is_ 0,
5663                          * it's still ok to use it: "read" builtin uses it,
5664                          * why should we cripple "exec" builtin?
5665                          */
5666                         if (fd == pf->pf_fd) {
5667                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5668                                 return 1; /* "we closed fd" */
5669                         }
5670                         pf = pf->prev;
5671                 }
5672         }
5673
5674         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5675
5676         /* First: do we collide with some already moved fds? */
5677         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5678                 /* If we collide with an already moved fd... */
5679                 if (fd == sq->two_fd[i].moved_to) {
5680                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5681                         sq->two_fd[i].moved_to = new_fd;
5682                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5683                         if (new_fd < 0) /* what? */
5684                                 xfunc_die();
5685                         return 0; /* "we did not close fd" */
5686                 }
5687                 if (fd == sq->two_fd[i].orig_fd) {
5688                         /* Example: echo Hello >/dev/null 1>&2 */
5689                         TRACE(("redirect_fd %d: already moved\n", fd));
5690                         return 0; /* "we did not close fd" */
5691                 }
5692         }
5693
5694         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5695         new_fd = dup_CLOEXEC(fd, avoid_fd);
5696         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5697         if (new_fd < 0) {
5698                 if (errno != EBADF)
5699                         xfunc_die();
5700                 /* new_fd = CLOSED; - already is -1 */
5701         }
5702         sq->two_fd[i].moved_to = new_fd;
5703         sq->two_fd[i].orig_fd = fd;
5704
5705         /* if we move stderr, let "set -x" code know */
5706         if (fd == preverrout_fd)
5707                 preverrout_fd = new_fd;
5708
5709         return 0; /* "we did not close fd" */
5710 }
5711
5712 static int
5713 internally_opened_fd(int fd, struct redirtab *sq)
5714 {
5715         int i;
5716 #if JOBS
5717         if (fd == ttyfd)
5718                 return 1;
5719 #endif
5720         /* If this one of script's fds? */
5721         if (fd != 0) {
5722                 struct parsefile *pf = g_parsefile;
5723                 while (pf) {
5724                         if (fd == pf->pf_fd)
5725                                 return 1;
5726                         pf = pf->prev;
5727                 }
5728         }
5729
5730         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5731                 if (fd == sq->two_fd[i].moved_to)
5732                         return 1;
5733         }
5734         return 0;
5735 }
5736
5737 /*
5738  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5739  * old file descriptors are stashed away so that the redirection can be
5740  * undone by calling popredir.
5741  */
5742 /* flags passed to redirect */
5743 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5744 static void
5745 redirect(union node *redir, int flags)
5746 {
5747         struct redirtab *sv;
5748
5749         if (!redir)
5750                 return;
5751
5752         sv = NULL;
5753         INT_OFF;
5754         if (flags & REDIR_PUSH)
5755                 sv = redirlist;
5756         do {
5757                 int fd;
5758                 int newfd;
5759                 int close_fd;
5760                 int closed;
5761
5762                 fd = redir->nfile.fd;
5763                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5764                         //bb_error_msg("doing %d > %d", fd, newfd);
5765                         newfd = redir->ndup.dupfd;
5766                         close_fd = -1;
5767                 } else {
5768                         newfd = openredirect(redir); /* always >= 0 */
5769                         if (fd == newfd) {
5770                                 /* open() gave us precisely the fd we wanted.
5771                                  * This means that this fd was not busy
5772                                  * (not opened to anywhere).
5773                                  * Remember to close it on restore:
5774                                  */
5775                                 add_squirrel_closed(sv, fd);
5776                                 continue;
5777                         }
5778                         close_fd = newfd;
5779                 }
5780
5781                 if (fd == newfd)
5782                         continue;
5783
5784                 /* if "N>FILE": move newfd to fd */
5785                 /* if "N>&M": dup newfd to fd */
5786                 /* if "N>&-": close fd (newfd is -1) */
5787
5788  IF_BASH_REDIR_OUTPUT(redirect_more:)
5789
5790                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5791                 if (newfd == -1) {
5792                         /* "N>&-" means "close me" */
5793                         if (!closed) {
5794                                 /* ^^^ optimization: saving may already
5795                                  * have closed it. If not... */
5796                                 close(fd);
5797                         }
5798                 } else {
5799                         /* if newfd is a script fd or saved fd, simulate EBADF */
5800                         if (internally_opened_fd(newfd, sv)) {
5801                                 errno = EBADF;
5802                                 ash_msg_and_raise_perror("%d", newfd);
5803                         }
5804                         dup2_or_raise(newfd, fd);
5805                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5806                                 close(close_fd);
5807 #if BASH_REDIR_OUTPUT
5808                         if (redir->nfile.type == NTO2 && fd == 1) {
5809                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5810                                 fd = 2;
5811                                 newfd = 1;
5812                                 close_fd = -1;
5813                                 goto redirect_more;
5814                         }
5815 #endif
5816                 }
5817         } while ((redir = redir->nfile.next) != NULL);
5818         INT_ON;
5819
5820 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5821 #define REDIR_SAVEFD2 0
5822         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5823         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5824         // not only for calls with flags containing REDIR_SAVEFD2.
5825         // We do this unconditionally (see save_fd_on_redirect()).
5826         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5827         //      preverrout_fd = copied_fd2;
5828 }
5829
5830 static int
5831 redirectsafe(union node *redir, int flags)
5832 {
5833         int err;
5834         volatile int saveint;
5835         struct jmploc *volatile savehandler = exception_handler;
5836         struct jmploc jmploc;
5837
5838         SAVE_INT(saveint);
5839         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5840         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5841         if (!err) {
5842                 exception_handler = &jmploc;
5843                 redirect(redir, flags);
5844         }
5845         exception_handler = savehandler;
5846         if (err && exception_type != EXERROR)
5847                 longjmp(exception_handler->loc, 1);
5848         RESTORE_INT(saveint);
5849         return err;
5850 }
5851
5852 static struct redirtab*
5853 pushredir(union node *redir)
5854 {
5855         struct redirtab *sv;
5856         int i;
5857
5858         if (!redir)
5859                 return redirlist;
5860
5861         i = 0;
5862         do {
5863                 i++;
5864 #if BASH_REDIR_OUTPUT
5865                 if (redir->nfile.type == NTO2)
5866                         i++;
5867 #endif
5868                 redir = redir->nfile.next;
5869         } while (redir);
5870
5871         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5872         sv->pair_count = i;
5873         while (--i >= 0)
5874                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5875         sv->next = redirlist;
5876         redirlist = sv;
5877         return sv->next;
5878 }
5879
5880 /*
5881  * Undo the effects of the last redirection.
5882  */
5883 static void
5884 popredir(int drop)
5885 {
5886         struct redirtab *rp;
5887         int i;
5888
5889         if (redirlist == NULL)
5890                 return;
5891         INT_OFF;
5892         rp = redirlist;
5893         for (i = 0; i < rp->pair_count; i++) {
5894                 int fd = rp->two_fd[i].orig_fd;
5895                 int copy = rp->two_fd[i].moved_to;
5896                 if (copy == CLOSED) {
5897                         if (!drop)
5898                                 close(fd);
5899                         continue;
5900                 }
5901                 if (copy != EMPTY) {
5902                         if (!drop) {
5903                                 /*close(fd);*/
5904                                 dup2_or_raise(copy, fd);
5905                         }
5906                         close(copy);
5907                 }
5908         }
5909         redirlist = rp->next;
5910         free(rp);
5911         INT_ON;
5912 }
5913
5914 static void
5915 unwindredir(struct redirtab *stop)
5916 {
5917         while (redirlist != stop)
5918                 popredir(/*drop:*/ 0);
5919 }
5920
5921
5922 /* ============ Routines to expand arguments to commands
5923  *
5924  * We have to deal with backquotes, shell variables, and file metacharacters.
5925  */
5926
5927 #if ENABLE_FEATURE_SH_MATH
5928 static arith_t
5929 ash_arith(const char *s)
5930 {
5931         arith_state_t math_state;
5932         arith_t result;
5933
5934         math_state.lookupvar = lookupvar;
5935         math_state.setvar    = setvar0;
5936         //math_state.endofname = endofname;
5937
5938         INT_OFF;
5939         result = arith(&math_state, s);
5940         if (math_state.errmsg)
5941                 ash_msg_and_raise_error(math_state.errmsg);
5942         INT_ON;
5943
5944         return result;
5945 }
5946 #endif
5947 #if BASH_SUBSTR
5948 # if ENABLE_FEATURE_SH_MATH
5949 static int substr_atoi(const char *s)
5950 {
5951         arith_t t = ash_arith(s);
5952         if (sizeof(t) > sizeof(int)) {
5953                 /* clamp very large or very large negative nums for ${v:N:M}:
5954                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5955                  */
5956                 if (t > INT_MAX)
5957                         t = INT_MAX;
5958                 if (t < INT_MIN)
5959                         t = INT_MIN;
5960         }
5961         return t;
5962 }
5963 # else
5964 #  define substr_atoi(s) number(s)
5965 # endif
5966 #endif
5967
5968 /*
5969  * expandarg flags
5970  */
5971 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5972 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5973 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5974 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5975 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5976  * POSIX says for this case:
5977  *  Pathname expansion shall not be performed on the word by a
5978  *  non-interactive shell; an interactive shell may perform it, but shall
5979  *  do so only when the expansion would result in one word.
5980  * Currently, our code complies to the above rule by never globbing
5981  * redirection filenames.
5982  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5983  * (this means that on a typical Linux distro, bash almost always
5984  * performs globbing, and thus diverges from what we do).
5985  */
5986 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5987 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
5988 #define EXP_WORD        0x40    /* expand word in parameter expansion */
5989 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5990 /*
5991  * rmescape() flags
5992  */
5993 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5994 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5995 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5996 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5997
5998 /* Add CTLESC when necessary. */
5999 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
6000 /* Do not skip NUL characters. */
6001 #define QUOTES_KEEPNUL EXP_TILDE
6002
6003 /*
6004  * Structure specifying which parts of the string should be searched
6005  * for IFS characters.
6006  */
6007 struct ifsregion {
6008         struct ifsregion *next; /* next region in list */
6009         int begoff;             /* offset of start of region */
6010         int endoff;             /* offset of end of region */
6011         int nulonly;            /* search for nul bytes only */
6012 };
6013
6014 struct arglist {
6015         struct strlist *list;
6016         struct strlist **lastp;
6017 };
6018
6019 /* output of current string */
6020 static char *expdest;
6021 /* list of back quote expressions */
6022 static struct nodelist *argbackq;
6023 /* first struct in list of ifs regions */
6024 static struct ifsregion ifsfirst;
6025 /* last struct in list */
6026 static struct ifsregion *ifslastp;
6027 /* holds expanded arg list */
6028 static struct arglist exparg;
6029
6030 /*
6031  * Our own itoa().
6032  * cvtnum() is used even if math support is off (to prepare $? values and such).
6033  */
6034 static int
6035 cvtnum(arith_t num)
6036 {
6037         int len;
6038
6039         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
6040         len = sizeof(arith_t) * 3;
6041         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
6042         if (sizeof(arith_t) < 4) len += 2;
6043
6044         expdest = makestrspace(len, expdest);
6045         len = fmtstr(expdest, len, ARITH_FMT, num);
6046         STADJUST(len, expdest);
6047         return len;
6048 }
6049
6050 /*
6051  * Break the argument string into pieces based upon IFS and add the
6052  * strings to the argument list.  The regions of the string to be
6053  * searched for IFS characters have been stored by recordregion.
6054  */
6055 static void
6056 ifsbreakup(char *string, struct arglist *arglist)
6057 {
6058         struct ifsregion *ifsp;
6059         struct strlist *sp;
6060         char *start;
6061         char *p;
6062         char *q;
6063         const char *ifs, *realifs;
6064         int ifsspc;
6065         int nulonly;
6066
6067         start = string;
6068         if (ifslastp != NULL) {
6069                 ifsspc = 0;
6070                 nulonly = 0;
6071                 realifs = ifsset() ? ifsval() : defifs;
6072                 ifsp = &ifsfirst;
6073                 do {
6074                         int afternul;
6075
6076                         p = string + ifsp->begoff;
6077                         afternul = nulonly;
6078                         nulonly = ifsp->nulonly;
6079                         ifs = nulonly ? nullstr : realifs;
6080                         ifsspc = 0;
6081                         while (p < string + ifsp->endoff) {
6082                                 q = p;
6083                                 if ((unsigned char)*p == CTLESC)
6084                                         p++;
6085                                 if (!strchr(ifs, *p)) {
6086                                         p++;
6087                                         continue;
6088                                 }
6089                                 if (!(afternul || nulonly))
6090                                         ifsspc = (strchr(defifs, *p) != NULL);
6091                                 /* Ignore IFS whitespace at start */
6092                                 if (q == start && ifsspc) {
6093                                         p++;
6094                                         start = p;
6095                                         continue;
6096                                 }
6097                                 *q = '\0';
6098                                 sp = stzalloc(sizeof(*sp));
6099                                 sp->text = start;
6100                                 *arglist->lastp = sp;
6101                                 arglist->lastp = &sp->next;
6102                                 p++;
6103                                 if (!nulonly) {
6104                                         for (;;) {
6105                                                 if (p >= string + ifsp->endoff) {
6106                                                         break;
6107                                                 }
6108                                                 q = p;
6109                                                 if ((unsigned char)*p == CTLESC)
6110                                                         p++;
6111                                                 if (strchr(ifs, *p) == NULL) {
6112                                                         p = q;
6113                                                         break;
6114                                                 }
6115                                                 if (strchr(defifs, *p) == NULL) {
6116                                                         if (ifsspc) {
6117                                                                 p++;
6118                                                                 ifsspc = 0;
6119                                                         } else {
6120                                                                 p = q;
6121                                                                 break;
6122                                                         }
6123                                                 } else
6124                                                         p++;
6125                                         }
6126                                 }
6127                                 start = p;
6128                         } /* while */
6129                         ifsp = ifsp->next;
6130                 } while (ifsp != NULL);
6131                 if (nulonly)
6132                         goto add;
6133         }
6134
6135         if (!*start)
6136                 return;
6137
6138  add:
6139         sp = stzalloc(sizeof(*sp));
6140         sp->text = start;
6141         *arglist->lastp = sp;
6142         arglist->lastp = &sp->next;
6143 }
6144
6145 static void
6146 ifsfree(void)
6147 {
6148         struct ifsregion *p = ifsfirst.next;
6149
6150         if (!p)
6151                 goto out;
6152
6153         INT_OFF;
6154         do {
6155                 struct ifsregion *ifsp;
6156                 ifsp = p->next;
6157                 free(p);
6158                 p = ifsp;
6159         } while (p);
6160         ifsfirst.next = NULL;
6161         INT_ON;
6162  out:
6163         ifslastp = NULL;
6164 }
6165
6166 static size_t
6167 esclen(const char *start, const char *p)
6168 {
6169         size_t esc = 0;
6170
6171         while (p > start && (unsigned char)*--p == CTLESC) {
6172                 esc++;
6173         }
6174         return esc;
6175 }
6176
6177 /*
6178  * Remove any CTLESC characters from a string.
6179  */
6180 #if !BASH_PATTERN_SUBST
6181 #define rmescapes(str, flag, slash_position) \
6182         rmescapes(str, flag)
6183 #endif
6184 static char *
6185 rmescapes(char *str, int flag, int *slash_position)
6186 {
6187         static const char qchars[] ALIGN1 = {
6188                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6189
6190         char *p, *q, *r;
6191         unsigned protect_against_glob;
6192         unsigned globbing;
6193
6194         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6195         if (!p)
6196                 return str;
6197
6198         q = p;
6199         r = str;
6200         if (flag & RMESCAPE_ALLOC) {
6201                 size_t len = p - str;
6202                 size_t fulllen = len + strlen(p) + 1;
6203
6204                 if (flag & RMESCAPE_GROW) {
6205                         int strloc = str - (char *)stackblock();
6206                         r = makestrspace(fulllen, expdest);
6207                         /* p and str may be invalidated by makestrspace */
6208                         str = (char *)stackblock() + strloc;
6209                         p = str + len;
6210                 } else if (flag & RMESCAPE_HEAP) {
6211                         r = ckmalloc(fulllen);
6212                 } else {
6213                         r = stalloc(fulllen);
6214                 }
6215                 q = r;
6216                 if (len > 0) {
6217                         q = (char *)mempcpy(q, str, len);
6218                 }
6219         }
6220
6221         globbing = flag & RMESCAPE_GLOB;
6222         protect_against_glob = globbing;
6223         while (*p) {
6224                 if ((unsigned char)*p == CTLQUOTEMARK) {
6225 // Note: protect_against_glob only affect whether
6226 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6227                         p++;
6228                         protect_against_glob = globbing;
6229                         continue;
6230                 }
6231                 if (*p == '\\') {
6232                         /* naked back slash */
6233                         protect_against_glob = 0;
6234                         goto copy;
6235                 }
6236                 if ((unsigned char)*p == CTLESC) {
6237                         p++;
6238 #if DEBUG
6239                         if (*p == '\0')
6240                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6241 #endif
6242                         if (protect_against_glob) {
6243                                 /*
6244                                  * We used to trust glob() and fnmatch() to eat
6245                                  * superfluous escapes (\z where z has no
6246                                  * special meaning anyway). But this causes
6247                                  * bugs such as string of one greek letter rho
6248                                  * (unicode-encoded as two bytes "cf,81")
6249                                  * getting encoded as "cf,CTLESC,81"
6250                                  * and here, converted to "cf,\,81" -
6251                                  * which does not go well with some flavors
6252                                  * of fnmatch() in unicode locales
6253                                  * (for example, glibc <= 2.22).
6254                                  *
6255                                  * Lets add "\" only on the chars which need it.
6256                                  * Testcases for less obvious chars are shown.
6257                                  */
6258                                 if (*p == '*'
6259                                  || *p == '?'
6260                                  || *p == '['
6261                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6262                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6263                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6264                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6265                                 /* Some libc support [^negate], that's why "^" also needs love */
6266                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6267                                 ) {
6268                                         *q++ = '\\';
6269                                 }
6270                         }
6271                 }
6272 #if BASH_PATTERN_SUBST
6273                 else if (slash_position && p == str + *slash_position) {
6274                         /* stop handling globbing */
6275                         globbing = 0;
6276                         *slash_position = q - r;
6277                         slash_position = NULL;
6278                 }
6279 #endif
6280                 protect_against_glob = globbing;
6281  copy:
6282                 *q++ = *p++;
6283         }
6284         *q = '\0';
6285         if (flag & RMESCAPE_GROW) {
6286                 expdest = r;
6287                 STADJUST(q - r + 1, expdest);
6288         }
6289         return r;
6290 }
6291 #define pmatch(a, b) !fnmatch((a), (b), 0)
6292
6293 /*
6294  * Prepare a pattern for a expmeta (internal glob(3)) call.
6295  *
6296  * Returns an stalloced string.
6297  */
6298 static char *
6299 preglob(const char *pattern, int flag)
6300 {
6301         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6302 }
6303
6304 /*
6305  * Put a string on the stack.
6306  */
6307 static void
6308 memtodest(const char *p, size_t len, int syntax, int quotes)
6309 {
6310         char *q;
6311
6312         if (!len)
6313                 return;
6314
6315         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6316
6317         do {
6318                 unsigned char c = *p++;
6319                 if (c) {
6320                         if (quotes & QUOTES_ESC) {
6321                                 int n = SIT(c, syntax);
6322                                 if (n == CCTL
6323                                  || (syntax != BASESYNTAX && n == CBACK)
6324                                 ) {
6325                                         USTPUTC(CTLESC, q);
6326                                 }
6327                         }
6328                 } else if (!(quotes & QUOTES_KEEPNUL))
6329                         continue;
6330                 USTPUTC(c, q);
6331         } while (--len);
6332
6333         expdest = q;
6334 }
6335
6336 static size_t
6337 strtodest(const char *p, int syntax, int quotes)
6338 {
6339         size_t len = strlen(p);
6340         memtodest(p, len, syntax, quotes);
6341         return len;
6342 }
6343
6344 /*
6345  * Record the fact that we have to scan this region of the
6346  * string for IFS characters.
6347  */
6348 static void
6349 recordregion(int start, int end, int nulonly)
6350 {
6351         struct ifsregion *ifsp;
6352
6353         if (ifslastp == NULL) {
6354                 ifsp = &ifsfirst;
6355         } else {
6356                 INT_OFF;
6357                 ifsp = ckzalloc(sizeof(*ifsp));
6358                 /*ifsp->next = NULL; - ckzalloc did it */
6359                 ifslastp->next = ifsp;
6360                 INT_ON;
6361         }
6362         ifslastp = ifsp;
6363         ifslastp->begoff = start;
6364         ifslastp->endoff = end;
6365         ifslastp->nulonly = nulonly;
6366 }
6367
6368 static void
6369 removerecordregions(int endoff)
6370 {
6371         if (ifslastp == NULL)
6372                 return;
6373
6374         if (ifsfirst.endoff > endoff) {
6375                 while (ifsfirst.next) {
6376                         struct ifsregion *ifsp;
6377                         INT_OFF;
6378                         ifsp = ifsfirst.next->next;
6379                         free(ifsfirst.next);
6380                         ifsfirst.next = ifsp;
6381                         INT_ON;
6382                 }
6383                 if (ifsfirst.begoff > endoff) {
6384                         ifslastp = NULL;
6385                 } else {
6386                         ifslastp = &ifsfirst;
6387                         ifsfirst.endoff = endoff;
6388                 }
6389                 return;
6390         }
6391
6392         ifslastp = &ifsfirst;
6393         while (ifslastp->next && ifslastp->next->begoff < endoff)
6394                 ifslastp = ifslastp->next;
6395         while (ifslastp->next) {
6396                 struct ifsregion *ifsp;
6397                 INT_OFF;
6398                 ifsp = ifslastp->next->next;
6399                 free(ifslastp->next);
6400                 ifslastp->next = ifsp;
6401                 INT_ON;
6402         }
6403         if (ifslastp->endoff > endoff)
6404                 ifslastp->endoff = endoff;
6405 }
6406
6407 static char *
6408 exptilde(char *startp, char *p, int flags)
6409 {
6410         unsigned char c;
6411         char *name;
6412         struct passwd *pw;
6413         const char *home;
6414         int quotes = flags & QUOTES_ESC;
6415
6416         name = p + 1;
6417
6418         while ((c = *++p) != '\0') {
6419                 switch (c) {
6420                 case CTLESC:
6421                         return startp;
6422                 case CTLQUOTEMARK:
6423                         return startp;
6424                 case ':':
6425                         if (flags & EXP_VARTILDE)
6426                                 goto done;
6427                         break;
6428                 case '/':
6429                 case CTLENDVAR:
6430                         goto done;
6431                 }
6432         }
6433  done:
6434         *p = '\0';
6435         if (*name == '\0') {
6436                 home = lookupvar("HOME");
6437         } else {
6438                 pw = getpwnam(name);
6439                 if (pw == NULL)
6440                         goto lose;
6441                 home = pw->pw_dir;
6442         }
6443         if (!home || !*home)
6444                 goto lose;
6445         *p = c;
6446         strtodest(home, SQSYNTAX, quotes);
6447         return p;
6448  lose:
6449         *p = c;
6450         return startp;
6451 }
6452
6453 /*
6454  * Execute a command inside back quotes.  If it's a builtin command, we
6455  * want to save its output in a block obtained from malloc.  Otherwise
6456  * we fork off a subprocess and get the output of the command via a pipe.
6457  * Should be called with interrupts off.
6458  */
6459 struct backcmd {                /* result of evalbackcmd */
6460         int fd;                 /* file descriptor to read from */
6461         int nleft;              /* number of chars in buffer */
6462         char *buf;              /* buffer */
6463         struct job *jp;         /* job structure for command */
6464 };
6465
6466 /* These forward decls are needed to use "eval" code for backticks handling: */
6467 /* flags in argument to evaltree */
6468 #define EV_EXIT    01           /* exit after evaluating tree */
6469 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6470 static int evaltree(union node *, int);
6471
6472 /* An evaltree() which is known to never return.
6473  * Used to use an alias:
6474  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6475  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6476  */
6477 static ALWAYS_INLINE NORETURN void
6478 evaltreenr(union node *n, int flags)
6479 {
6480         evaltree(n, flags);
6481         bb_unreachable(abort());
6482         /* NOTREACHED */
6483 }
6484
6485 static void FAST_FUNC
6486 evalbackcmd(union node *n, struct backcmd *result)
6487 {
6488         int pip[2];
6489         struct job *jp;
6490
6491         result->fd = -1;
6492         result->buf = NULL;
6493         result->nleft = 0;
6494         result->jp = NULL;
6495         if (n == NULL) {
6496                 goto out;
6497         }
6498
6499         if (pipe(pip) < 0)
6500                 ash_msg_and_raise_perror("can't create pipe");
6501         jp = makejob(/*n,*/ 1);
6502         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6503                 /* child */
6504                 FORCE_INT_ON;
6505                 close(pip[0]);
6506                 if (pip[1] != 1) {
6507                         /*close(1);*/
6508                         dup2_or_raise(pip[1], 1);
6509                         close(pip[1]);
6510                 }
6511 /* TODO: eflag clearing makes the following not abort:
6512  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6513  * which is what bash does (unless it is in POSIX mode).
6514  * dash deleted "eflag = 0" line in the commit
6515  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6516  *  [EVAL] Don't clear eflag in evalbackcmd
6517  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6518  */
6519                 eflag = 0;
6520                 ifsfree();
6521                 evaltreenr(n, EV_EXIT);
6522                 /* NOTREACHED */
6523         }
6524         /* parent */
6525         close(pip[1]);
6526         result->fd = pip[0];
6527         result->jp = jp;
6528
6529  out:
6530         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6531                 result->fd, result->buf, result->nleft, result->jp));
6532 }
6533
6534 /*
6535  * Expand stuff in backwards quotes.
6536  */
6537 static void
6538 expbackq(union node *cmd, int flag)
6539 {
6540         struct backcmd in;
6541         int i;
6542         char buf[128];
6543         char *p;
6544         char *dest;
6545         int startloc;
6546         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6547         struct stackmark smark;
6548
6549         INT_OFF;
6550         startloc = expdest - (char *)stackblock();
6551         pushstackmark(&smark, startloc);
6552         evalbackcmd(cmd, &in);
6553         popstackmark(&smark);
6554
6555         p = in.buf;
6556         i = in.nleft;
6557         if (i == 0)
6558                 goto read;
6559         for (;;) {
6560                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6561  read:
6562                 if (in.fd < 0)
6563                         break;
6564                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6565                 TRACE(("expbackq: read returns %d\n", i));
6566                 if (i <= 0)
6567                         break;
6568                 p = buf;
6569         }
6570
6571         free(in.buf);
6572         if (in.fd >= 0) {
6573                 close(in.fd);
6574                 back_exitstatus = waitforjob(in.jp);
6575         }
6576         INT_ON;
6577
6578         /* Eat all trailing newlines */
6579         dest = expdest;
6580         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6581                 STUNPUTC(dest);
6582         expdest = dest;
6583
6584         if (!(flag & EXP_QUOTED))
6585                 recordregion(startloc, dest - (char *)stackblock(), 0);
6586         TRACE(("evalbackq: size:%d:'%.*s'\n",
6587                 (int)((dest - (char *)stackblock()) - startloc),
6588                 (int)((dest - (char *)stackblock()) - startloc),
6589                 stackblock() + startloc));
6590 }
6591
6592 #if ENABLE_FEATURE_SH_MATH
6593 /*
6594  * Expand arithmetic expression.  Backup to start of expression,
6595  * evaluate, place result in (backed up) result, adjust string position.
6596  */
6597 static void
6598 expari(int flag)
6599 {
6600         char *p, *start;
6601         int begoff;
6602         int len;
6603
6604         /* ifsfree(); */
6605
6606         /*
6607          * This routine is slightly over-complicated for
6608          * efficiency.  Next we scan backwards looking for the
6609          * start of arithmetic.
6610          */
6611         start = stackblock();
6612         p = expdest - 1;
6613         *p = '\0';
6614         p--;
6615         while (1) {
6616                 int esc;
6617
6618                 while ((unsigned char)*p != CTLARI) {
6619                         p--;
6620 #if DEBUG
6621                         if (p < start) {
6622                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6623                         }
6624 #endif
6625                 }
6626
6627                 esc = esclen(start, p);
6628                 if (!(esc % 2)) {
6629                         break;
6630                 }
6631
6632                 p -= esc + 1;
6633         }
6634
6635         begoff = p - start;
6636
6637         removerecordregions(begoff);
6638
6639         expdest = p;
6640
6641         if (flag & QUOTES_ESC)
6642                 rmescapes(p + 1, 0, NULL);
6643
6644         len = cvtnum(ash_arith(p + 1));
6645
6646         if (!(flag & EXP_QUOTED))
6647                 recordregion(begoff, begoff + len, 0);
6648 }
6649 #endif
6650
6651 /* argstr needs it */
6652 static char *evalvar(char *p, int flags);
6653
6654 /*
6655  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6656  * characters to allow for further processing.  Otherwise treat
6657  * $@ like $* since no splitting will be performed.
6658  */
6659 static void
6660 argstr(char *p, int flags)
6661 {
6662         static const char spclchars[] ALIGN1 = {
6663                 '=',
6664                 ':',
6665                 CTLQUOTEMARK,
6666                 CTLENDVAR,
6667                 CTLESC,
6668                 CTLVAR,
6669                 CTLBACKQ,
6670 #if ENABLE_FEATURE_SH_MATH
6671                 CTLENDARI,
6672 #endif
6673                 '\0'
6674         };
6675         const char *reject = spclchars;
6676         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6677         int inquotes;
6678         size_t length;
6679         int startloc;
6680
6681         if (!(flags & EXP_VARTILDE)) {
6682                 reject += 2;
6683         } else if (flags & EXP_VARTILDE2) {
6684                 reject++;
6685         }
6686         inquotes = 0;
6687         length = 0;
6688         if (flags & EXP_TILDE) {
6689                 char *q;
6690
6691                 flags &= ~EXP_TILDE;
6692  tilde:
6693                 q = p;
6694                 if (*q == '~')
6695                         p = exptilde(p, q, flags);
6696         }
6697  start:
6698         startloc = expdest - (char *)stackblock();
6699         for (;;) {
6700                 unsigned char c;
6701
6702                 length += strcspn(p + length, reject);
6703                 c = p[length];
6704                 if (c) {
6705                         if (!(c & 0x80)
6706                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6707                         ) {
6708                                 /* c == '=' || c == ':' || c == CTLENDARI */
6709                                 length++;
6710                         }
6711                 }
6712                 if (length > 0) {
6713                         int newloc;
6714                         expdest = stack_nputstr(p, length, expdest);
6715                         newloc = expdest - (char *)stackblock();
6716                         if (breakall && !inquotes && newloc > startloc) {
6717                                 recordregion(startloc, newloc, 0);
6718                         }
6719                         startloc = newloc;
6720                 }
6721                 p += length + 1;
6722                 length = 0;
6723
6724                 switch (c) {
6725                 case '\0':
6726                         goto breakloop;
6727                 case '=':
6728                         if (flags & EXP_VARTILDE2) {
6729                                 p--;
6730                                 continue;
6731                         }
6732                         flags |= EXP_VARTILDE2;
6733                         reject++;
6734                         /* fall through */
6735                 case ':':
6736                         /*
6737                          * sort of a hack - expand tildes in variable
6738                          * assignments (after the first '=' and after ':'s).
6739                          */
6740                         if (*--p == '~') {
6741                                 goto tilde;
6742                         }
6743                         continue;
6744                 }
6745
6746                 switch (c) {
6747                 case CTLENDVAR: /* ??? */
6748                         goto breakloop;
6749                 case CTLQUOTEMARK:
6750                         /* "$@" syntax adherence hack */
6751                         if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6752                                 p = evalvar(p + 1, flags | EXP_QUOTED) + 1;
6753                                 goto start;
6754                         }
6755                         inquotes ^= EXP_QUOTED;
6756  addquote:
6757                         if (flags & QUOTES_ESC) {
6758                                 p--;
6759                                 length++;
6760                                 startloc++;
6761                         }
6762                         break;
6763                 case CTLESC:
6764                         startloc++;
6765                         length++;
6766                         goto addquote;
6767                 case CTLVAR:
6768                         TRACE(("argstr: evalvar('%s')\n", p));
6769                         p = evalvar(p, flags | inquotes);
6770                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6771                         goto start;
6772                 case CTLBACKQ:
6773                         expbackq(argbackq->n, flags | inquotes);
6774                         argbackq = argbackq->next;
6775                         goto start;
6776 #if ENABLE_FEATURE_SH_MATH
6777                 case CTLENDARI:
6778                         p--;
6779                         expari(flags | inquotes);
6780                         goto start;
6781 #endif
6782                 }
6783         }
6784  breakloop: ;
6785 }
6786
6787 static char *
6788 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6789                 char *pattern, int quotes, int zero)
6790 {
6791         char *loc, *loc2;
6792         char c;
6793
6794         loc = startp;
6795         loc2 = rmesc;
6796         do {
6797                 int match;
6798                 const char *s = loc2;
6799
6800                 c = *loc2;
6801                 if (zero) {
6802                         *loc2 = '\0';
6803                         s = rmesc;
6804                 }
6805                 match = pmatch(pattern, s);
6806
6807                 *loc2 = c;
6808                 if (match)
6809                         return loc;
6810                 if (quotes && (unsigned char)*loc == CTLESC)
6811                         loc++;
6812                 loc++;
6813                 loc2++;
6814         } while (c);
6815         return NULL;
6816 }
6817
6818 static char *
6819 scanright(char *startp, char *rmesc, char *rmescend,
6820                 char *pattern, int quotes, int match_at_start)
6821 {
6822 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6823         int try2optimize = match_at_start;
6824 #endif
6825         int esc = 0;
6826         char *loc;
6827         char *loc2;
6828
6829         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6830          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6831          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6832          * Logic:
6833          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6834          * and on each iteration they go back two/one char until they reach the beginning.
6835          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6836          */
6837         /* TODO: document in what other circumstances we are called. */
6838
6839         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6840                 int match;
6841                 char c = *loc2;
6842                 const char *s = loc2;
6843                 if (match_at_start) {
6844                         *loc2 = '\0';
6845                         s = rmesc;
6846                 }
6847                 match = pmatch(pattern, s);
6848                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6849                 *loc2 = c;
6850                 if (match)
6851                         return loc;
6852 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6853                 if (try2optimize) {
6854                         /* Maybe we can optimize this:
6855                          * if pattern ends with unescaped *, we can avoid checking
6856                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6857                          * it won't match truncated "raw_value_of_" strings too.
6858                          */
6859                         unsigned plen = strlen(pattern);
6860                         /* Does it end with "*"? */
6861                         if (plen != 0 && pattern[--plen] == '*') {
6862                                 /* "xxxx*" is not escaped */
6863                                 /* "xxx\*" is escaped */
6864                                 /* "xx\\*" is not escaped */
6865                                 /* "x\\\*" is escaped */
6866                                 int slashes = 0;
6867                                 while (plen != 0 && pattern[--plen] == '\\')
6868                                         slashes++;
6869                                 if (!(slashes & 1))
6870                                         break; /* ends with unescaped "*" */
6871                         }
6872                         try2optimize = 0;
6873                 }
6874 #endif
6875                 loc--;
6876                 if (quotes) {
6877                         if (--esc < 0) {
6878                                 esc = esclen(startp, loc);
6879                         }
6880                         if (esc % 2) {
6881                                 esc--;
6882                                 loc--;
6883                         }
6884                 }
6885         }
6886         return NULL;
6887 }
6888
6889 static void varunset(const char *, const char *, const char *, int) NORETURN;
6890 static void
6891 varunset(const char *end, const char *var, const char *umsg, int varflags)
6892 {
6893         const char *msg;
6894         const char *tail;
6895
6896         tail = nullstr;
6897         msg = "parameter not set";
6898         if (umsg) {
6899                 if ((unsigned char)*end == CTLENDVAR) {
6900                         if (varflags & VSNUL)
6901                                 tail = " or null";
6902                 } else {
6903                         msg = umsg;
6904                 }
6905         }
6906         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6907 }
6908
6909 static const char *
6910 subevalvar(char *p, char *varname, int strloc, int subtype,
6911                 int startloc, int varflags, int flag)
6912 {
6913         struct nodelist *saveargbackq = argbackq;
6914         int quotes = flag & QUOTES_ESC;
6915         char *startp;
6916         char *loc;
6917         char *rmesc, *rmescend;
6918         char *str;
6919         int amount, resetloc;
6920         int argstr_flags;
6921         IF_BASH_PATTERN_SUBST(int workloc;)
6922         IF_BASH_PATTERN_SUBST(int slash_pos;)
6923         IF_BASH_PATTERN_SUBST(char *repl;)
6924         int zero;
6925         char *(*scan)(char*, char*, char*, char*, int, int);
6926
6927         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6928         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6929
6930 #if BASH_PATTERN_SUBST
6931         /* For "${v/pattern/repl}", we must find the delimiter _before_
6932          * argstr() call expands possible variable references in pattern:
6933          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6934          */
6935         repl = NULL;
6936         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6937                 /* Find '/' and replace with NUL */
6938                 repl = p;
6939                 /* The pattern can't be empty.
6940                  * IOW: if the first char after "${v//" is a slash,
6941                  * it does not terminate the pattern - it's the first char of the pattern:
6942                  *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
6943                  *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
6944                  */
6945                 if (*repl == '/')
6946                         repl++;
6947                 for (;;) {
6948                         if (*repl == '\0') {
6949                                 repl = NULL;
6950                                 break;
6951                         }
6952                         if (*repl == '/') {
6953                                 *repl = '\0';
6954                                 break;
6955                         }
6956                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6957                         if ((unsigned char)*repl == CTLESC && repl[1])
6958                                 repl++;
6959                         repl++;
6960                 }
6961         }
6962 #endif
6963         argstr_flags = EXP_TILDE;
6964         if (subtype != VSASSIGN
6965          && subtype != VSQUESTION
6966 #if BASH_SUBSTR
6967          && subtype != VSSUBSTR
6968 #endif
6969         ) {
6970                 /* EXP_CASE keeps CTLESC's */
6971                 argstr_flags = EXP_TILDE | EXP_CASE;
6972         }
6973         argstr(p, argstr_flags);
6974         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
6975 #if BASH_PATTERN_SUBST
6976         slash_pos = -1;
6977         if (repl) {
6978                 slash_pos = expdest - ((char *)stackblock() + strloc);
6979                 STPUTC('/', expdest);
6980                 //bb_error_msg("repl+1:'%s'", repl + 1);
6981                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
6982                 *repl = '/';
6983         }
6984 #endif
6985         STPUTC('\0', expdest);
6986         argbackq = saveargbackq;
6987         startp = (char *)stackblock() + startloc;
6988         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6989
6990         switch (subtype) {
6991         case VSASSIGN:
6992                 setvar0(varname, startp);
6993                 amount = startp - expdest;
6994                 STADJUST(amount, expdest);
6995                 return startp;
6996
6997         case VSQUESTION:
6998                 varunset(p, varname, startp, varflags);
6999                 /* NOTREACHED */
7000
7001 #if BASH_SUBSTR
7002         case VSSUBSTR: {
7003                 int pos, len, orig_len;
7004                 char *colon;
7005
7006                 loc = str = stackblock() + strloc;
7007
7008                 /* Read POS in ${var:POS:LEN} */
7009                 colon = strchr(loc, ':');
7010                 if (colon) *colon = '\0';
7011                 pos = substr_atoi(loc);
7012                 if (colon) *colon = ':';
7013
7014                 /* Read LEN in ${var:POS:LEN} */
7015                 len = str - startp - 1;
7016                 /* *loc != '\0', guaranteed by parser */
7017                 if (quotes) {
7018                         char *ptr;
7019                         /* Adjust the length by the number of escapes */
7020                         for (ptr = startp; ptr < (str - 1); ptr++) {
7021                                 if ((unsigned char)*ptr == CTLESC) {
7022                                         len--;
7023                                         ptr++;
7024                                 }
7025                         }
7026                 }
7027                 orig_len = len;
7028                 if (*loc++ == ':') {
7029                         /* ${var::LEN} */
7030                         len = substr_atoi(loc);
7031                 } else {
7032                         /* Skip POS in ${var:POS:LEN} */
7033                         len = orig_len;
7034                         while (*loc && *loc != ':')
7035                                 loc++;
7036                         if (*loc++ == ':')
7037                                 len = substr_atoi(loc);
7038                 }
7039                 if (pos < 0) {
7040                         /* ${VAR:$((-n)):l} starts n chars from the end */
7041                         pos = orig_len + pos;
7042                 }
7043                 if ((unsigned)pos >= orig_len) {
7044                         /* apart from obvious ${VAR:999999:l},
7045                          * covers ${VAR:$((-9999999)):l} - result is ""
7046                          * (bash compat)
7047                          */
7048                         pos = 0;
7049                         len = 0;
7050                 }
7051                 if (len < 0) {
7052                         /* ${VAR:N:-M} sets LEN to strlen()-M */
7053                         len = (orig_len - pos) + len;
7054                 }
7055                 if ((unsigned)len > (orig_len - pos))
7056                         len = orig_len - pos;
7057
7058                 for (str = startp; pos; str++, pos--) {
7059                         if (quotes && (unsigned char)*str == CTLESC)
7060                                 str++;
7061                 }
7062                 for (loc = startp; len; len--) {
7063                         if (quotes && (unsigned char)*str == CTLESC)
7064                                 *loc++ = *str++;
7065                         *loc++ = *str++;
7066                 }
7067                 *loc = '\0';
7068                 amount = loc - expdest;
7069                 STADJUST(amount, expdest);
7070                 return loc;
7071         }
7072 #endif /* BASH_SUBSTR */
7073         }
7074
7075         resetloc = expdest - (char *)stackblock();
7076
7077 #if BASH_PATTERN_SUBST
7078         repl = NULL;
7079
7080         /* We'll comeback here if we grow the stack while handling
7081          * a VSREPLACE or VSREPLACEALL, since our pointers into the
7082          * stack will need rebasing, and we'll need to remove our work
7083          * areas each time
7084          */
7085  restart:
7086 #endif
7087
7088         amount = expdest - ((char *)stackblock() + resetloc);
7089         STADJUST(-amount, expdest);
7090         startp = (char *)stackblock() + startloc;
7091
7092         rmesc = startp;
7093         rmescend = (char *)stackblock() + strloc;
7094         //bb_error_msg("str7:'%s'", rmescend);
7095         if (quotes) {
7096 //TODO: how to handle slash_pos here if string changes (shortens?)
7097                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
7098                 if (rmesc != startp) {
7099                         rmescend = expdest;
7100                         startp = (char *)stackblock() + startloc;
7101                 }
7102         }
7103         rmescend--;
7104         str = (char *)stackblock() + strloc;
7105         /*
7106          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7107          * The result is a_\_z_c (not a\_\_z_c)!
7108          *
7109          * The search pattern and replace string treat backslashes differently!
7110          * "&slash_pos" causes rmescapes() to work differently on the pattern
7111          * and string.  It's only used on the first call.
7112          */
7113         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7114         rmescapes(str, RMESCAPE_GLOB,
7115                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7116         );
7117
7118 #if BASH_PATTERN_SUBST
7119         workloc = expdest - (char *)stackblock();
7120         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7121                 int len;
7122                 char *idx, *end;
7123
7124                 if (!repl) {
7125                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7126                         repl = nullstr;
7127                         if (slash_pos >= 0) {
7128                                 repl = str + slash_pos;
7129                                 *repl++ = '\0';
7130                         }
7131                 }
7132                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7133
7134                 /* If there's no pattern to match, return the expansion unmolested */
7135                 if (str[0] == '\0')
7136                         return NULL;
7137
7138                 len = 0;
7139                 idx = startp;
7140                 end = str - 1;
7141                 while (idx < end) {
7142  try_to_match:
7143                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7144                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7145                         if (!loc) {
7146                                 /* No match, advance */
7147                                 char *restart_detect = stackblock();
7148  skip_matching:
7149                                 STPUTC(*idx, expdest);
7150                                 if (quotes && (unsigned char)*idx == CTLESC) {
7151                                         idx++;
7152                                         len++;
7153                                         STPUTC(*idx, expdest);
7154                                 }
7155                                 if (stackblock() != restart_detect)
7156                                         goto restart;
7157                                 idx++;
7158                                 len++;
7159                                 rmesc++;
7160                                 /* continue; - prone to quadratic behavior, smarter code: */
7161                                 if (idx >= end)
7162                                         break;
7163                                 if (str[0] == '*') {
7164                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7165                                          * it would never match "ong_string" etc, no point in trying.
7166                                          */
7167                                         goto skip_matching;
7168                                 }
7169                                 goto try_to_match;
7170                         }
7171
7172                         if (subtype == VSREPLACEALL) {
7173                                 while (idx < loc) {
7174                                         if (quotes && (unsigned char)*idx == CTLESC)
7175                                                 idx++;
7176                                         idx++;
7177                                         rmesc++;
7178                                 }
7179                         } else {
7180                                 idx = loc;
7181                         }
7182
7183                         //bb_error_msg("repl:'%s'", repl);
7184                         for (loc = (char*)repl; *loc; loc++) {
7185                                 char *restart_detect = stackblock();
7186                                 if (quotes && *loc == '\\') {
7187                                         STPUTC(CTLESC, expdest);
7188                                         len++;
7189                                 }
7190                                 STPUTC(*loc, expdest);
7191                                 if (stackblock() != restart_detect)
7192                                         goto restart;
7193                                 len++;
7194                         }
7195
7196                         if (subtype == VSREPLACE) {
7197                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7198                                 while (*idx) {
7199                                         char *restart_detect = stackblock();
7200                                         STPUTC(*idx, expdest);
7201                                         if (stackblock() != restart_detect)
7202                                                 goto restart;
7203                                         len++;
7204                                         idx++;
7205                                 }
7206                                 break;
7207                         }
7208                 }
7209
7210                 /* We've put the replaced text into a buffer at workloc, now
7211                  * move it to the right place and adjust the stack.
7212                  */
7213                 STPUTC('\0', expdest);
7214                 startp = (char *)stackblock() + startloc;
7215                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7216                 //bb_error_msg("startp:'%s'", startp);
7217                 amount = expdest - (startp + len);
7218                 STADJUST(-amount, expdest);
7219                 return startp;
7220         }
7221 #endif /* BASH_PATTERN_SUBST */
7222
7223         subtype -= VSTRIMRIGHT;
7224 #if DEBUG
7225         if (subtype < 0 || subtype > 7)
7226                 abort();
7227 #endif
7228         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7229         zero = subtype >> 1;
7230         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7231         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7232
7233         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7234         if (loc) {
7235                 if (zero) {
7236                         memmove(startp, loc, str - loc);
7237                         loc = startp + (str - loc) - 1;
7238                 }
7239                 *loc = '\0';
7240                 amount = loc - expdest;
7241                 STADJUST(amount, expdest);
7242         }
7243         return loc;
7244 }
7245
7246 /*
7247  * Add the value of a specialized variable to the stack string.
7248  * name parameter (examples):
7249  * ash -c 'echo $1'      name:'1='
7250  * ash -c 'echo $qwe'    name:'qwe='
7251  * ash -c 'echo $$'      name:'$='
7252  * ash -c 'echo ${$}'    name:'$='
7253  * ash -c 'echo ${$##q}' name:'$=q'
7254  * ash -c 'echo ${#$}'   name:'$='
7255  * note: examples with bad shell syntax:
7256  * ash -c 'echo ${#$1}'  name:'$=1'
7257  * ash -c 'echo ${#1#}'  name:'1=#'
7258  */
7259 static NOINLINE ssize_t
7260 varvalue(char *name, int varflags, int flags, int quoted)
7261 {
7262         const char *p;
7263         int num;
7264         int i;
7265         ssize_t len = 0;
7266         int sep;
7267         int subtype = varflags & VSTYPE;
7268         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7269         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7270         int syntax;
7271
7272         sep = (flags & EXP_FULL) << CHAR_BIT;
7273         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7274
7275         switch (*name) {
7276         case '$':
7277                 num = rootpid;
7278                 goto numvar;
7279         case '?':
7280                 num = exitstatus;
7281                 goto numvar;
7282         case '#':
7283                 num = shellparam.nparam;
7284                 goto numvar;
7285         case '!':
7286                 num = backgndpid;
7287                 if (num == 0)
7288                         return -1;
7289  numvar:
7290                 len = cvtnum(num);
7291                 goto check_1char_name;
7292         case '-':
7293                 expdest = makestrspace(NOPTS, expdest);
7294                 for (i = NOPTS - 1; i >= 0; i--) {
7295                         if (optlist[i] && optletters(i)) {
7296                                 USTPUTC(optletters(i), expdest);
7297                                 len++;
7298                         }
7299                 }
7300  check_1char_name:
7301 #if 0
7302                 /* handles cases similar to ${#$1} */
7303                 if (name[2] != '\0')
7304                         raise_error_syntax("bad substitution");
7305 #endif
7306                 break;
7307         case '@':
7308                 if (quoted && sep)
7309                         goto param;
7310                 /* fall through */
7311         case '*': {
7312                 char **ap;
7313                 char sepc;
7314                 char c;
7315
7316                 /* We will set c to 0 or ~0 depending on whether
7317                  * we're doing field splitting.  We won't do field
7318                  * splitting if either we're quoted or sep is zero.
7319                  *
7320                  * Instead of testing (quoted || !sep) the following
7321                  * trick optimises away any branches by using the
7322                  * fact that EXP_QUOTED (which is the only bit that
7323                  * can be set in quoted) is the same as EXP_FULL <<
7324                  * CHAR_BIT (which is the only bit that can be set
7325                  * in sep).
7326                  */
7327 #if EXP_QUOTED >> CHAR_BIT != EXP_FULL
7328 #error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
7329 #endif
7330                 c = !((quoted | ~sep) & EXP_QUOTED) - 1;
7331                 sep &= ~quoted;
7332                 sep |= ifsset() ? (unsigned char)(c & ifsval()[0]) : ' ';
7333  param:
7334                 sepc = sep;
7335                 ap = shellparam.p;
7336                 if (!ap)
7337                         return -1;
7338                 while ((p = *ap++) != NULL) {
7339                         len += strtodest(p, syntax, quotes);
7340
7341                         if (*ap && sep) {
7342                                 len++;
7343                                 memtodest(&sepc, 1, syntax, quotes);
7344                         }
7345                 }
7346                 break;
7347         } /* case '*' */
7348         case '0':
7349         case '1':
7350         case '2':
7351         case '3':
7352         case '4':
7353         case '5':
7354         case '6':
7355         case '7':
7356         case '8':
7357         case '9':
7358                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7359                 if (num < 0 || num > shellparam.nparam)
7360                         return -1;
7361                 p = num ? shellparam.p[num - 1] : arg0;
7362                 goto value;
7363         default:
7364                 /* NB: name has form "VAR=..." */
7365                 p = lookupvar(name);
7366  value:
7367                 if (!p)
7368                         return -1;
7369
7370                 len = strtodest(p, syntax, quotes);
7371 #if ENABLE_UNICODE_SUPPORT
7372                 if (subtype == VSLENGTH && len > 0) {
7373                         reinit_unicode_for_ash();
7374                         if (unicode_status == UNICODE_ON) {
7375                                 STADJUST(-len, expdest);
7376                                 discard = 0;
7377                                 len = unicode_strlen(p);
7378                         }
7379                 }
7380 #endif
7381                 break;
7382         }
7383
7384         if (discard)
7385                 STADJUST(-len, expdest);
7386         return len;
7387 }
7388
7389 /*
7390  * Expand a variable, and return a pointer to the next character in the
7391  * input string.
7392  */
7393 static char *
7394 evalvar(char *p, int flag)
7395 {
7396         char varflags;
7397         char subtype;
7398         int quoted;
7399         char *var;
7400         int patloc;
7401         int startloc;
7402         ssize_t varlen;
7403
7404         varflags = (unsigned char) *p++;
7405         subtype = varflags & VSTYPE;
7406
7407         if (!subtype)
7408                 raise_error_syntax("bad substitution");
7409
7410         quoted = flag & EXP_QUOTED;
7411         var = p;
7412         startloc = expdest - (char *)stackblock();
7413         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7414
7415  again:
7416         varlen = varvalue(var, varflags, flag, quoted);
7417         if (varflags & VSNUL)
7418                 varlen--;
7419
7420         if (subtype == VSPLUS) {
7421                 varlen = -1 - varlen;
7422                 goto vsplus;
7423         }
7424
7425         if (subtype == VSMINUS) {
7426  vsplus:
7427                 if (varlen < 0) {
7428                         argstr(
7429                                 p,
7430                                 flag | EXP_TILDE | EXP_WORD
7431                         );
7432                         goto end;
7433                 }
7434                 goto record;
7435         }
7436
7437         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7438                 if (varlen >= 0)
7439                         goto record;
7440
7441                 subevalvar(p, var, 0, subtype, startloc, varflags,
7442                            flag & ~QUOTES_ESC);
7443                 varflags &= ~VSNUL;
7444                 /*
7445                  * Remove any recorded regions beyond
7446                  * start of variable
7447                  */
7448                 removerecordregions(startloc);
7449                 goto again;
7450         }
7451
7452         if (varlen < 0 && uflag)
7453                 varunset(p, var, 0, 0);
7454
7455         if (subtype == VSLENGTH) {
7456                 cvtnum(varlen > 0 ? varlen : 0);
7457                 goto record;
7458         }
7459
7460         if (subtype == VSNORMAL) {
7461  record:
7462                 if (quoted) {
7463                         quoted = *var == '@' && shellparam.nparam;
7464                         if (!quoted)
7465                                 goto end;
7466                 }
7467                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7468                 goto end;
7469         }
7470
7471 #if DEBUG
7472         switch (subtype) {
7473         case VSTRIMLEFT:
7474         case VSTRIMLEFTMAX:
7475         case VSTRIMRIGHT:
7476         case VSTRIMRIGHTMAX:
7477 #if BASH_SUBSTR
7478         case VSSUBSTR:
7479 #endif
7480 #if BASH_PATTERN_SUBST
7481         case VSREPLACE:
7482         case VSREPLACEALL:
7483 #endif
7484                 break;
7485         default:
7486                 abort();
7487         }
7488 #endif
7489
7490         if (varlen >= 0) {
7491                 /*
7492                  * Terminate the string and start recording the pattern
7493                  * right after it
7494                  */
7495                 STPUTC('\0', expdest);
7496                 patloc = expdest - (char *)stackblock();
7497                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7498                                 startloc, varflags, flag)) {
7499                         int amount = expdest - (
7500                                 (char *)stackblock() + patloc - 1
7501                         );
7502                         STADJUST(-amount, expdest);
7503                 }
7504                 /* Remove any recorded regions beyond start of variable */
7505                 removerecordregions(startloc);
7506                 goto record;
7507         }
7508
7509  end:
7510         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7511                 int nesting = 1;
7512                 for (;;) {
7513                         unsigned char c = *p++;
7514                         if (c == CTLESC)
7515                                 p++;
7516                         else if (c == CTLBACKQ) {
7517                                 if (varlen >= 0)
7518                                         argbackq = argbackq->next;
7519                         } else if (c == CTLVAR) {
7520                                 if ((*p++ & VSTYPE) != VSNORMAL)
7521                                         nesting++;
7522                         } else if (c == CTLENDVAR) {
7523                                 if (--nesting == 0)
7524                                         break;
7525                         }
7526                 }
7527         }
7528         return p;
7529 }
7530
7531 /*
7532  * Add a file name to the list.
7533  */
7534 static void
7535 addfname(const char *name)
7536 {
7537         struct strlist *sp;
7538
7539         sp = stzalloc(sizeof(*sp));
7540         sp->text = sstrdup(name);
7541         *exparg.lastp = sp;
7542         exparg.lastp = &sp->next;
7543 }
7544
7545 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7546 static int
7547 hasmeta(const char *p)
7548 {
7549         static const char chars[] ALIGN1 = {
7550                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7551         };
7552
7553         for (;;) {
7554                 p = strpbrk(p, chars);
7555                 if (!p)
7556                         break;
7557                 switch ((unsigned char)*p) {
7558                 case CTLQUOTEMARK:
7559                         for (;;) {
7560                                 p++;
7561                                 if ((unsigned char)*p == CTLQUOTEMARK)
7562                                         break;
7563                                 if ((unsigned char)*p == CTLESC)
7564                                         p++;
7565                                 if (*p == '\0') /* huh? */
7566                                         return 0;
7567                         }
7568                         break;
7569                 case '\\':
7570                 case CTLESC:
7571                         p++;
7572                         if (*p == '\0')
7573                                 return 0;
7574                         break;
7575                 case '[':
7576                         if (!strchr(p + 1, ']')) {
7577                                 /* It's not a properly closed [] pattern,
7578                                  * but other metas may follow. Continue checking.
7579                                  * my[file* _is_ globbed by bash
7580                                  * and matches filenames like "my[file1".
7581                                  */
7582                                 break;
7583                         }
7584                         /* fallthrough */
7585                 default:
7586                 /* case '*': */
7587                 /* case '?': */
7588                         return 1;
7589                 }
7590                 p++;
7591         }
7592
7593         return 0;
7594 }
7595
7596 /* If we want to use glob() from libc... */
7597 #if !ENABLE_ASH_INTERNAL_GLOB
7598
7599 /* Add the result of glob() to the list */
7600 static void
7601 addglob(const glob_t *pglob)
7602 {
7603         char **p = pglob->gl_pathv;
7604
7605         do {
7606                 addfname(*p);
7607         } while (*++p);
7608 }
7609 static void
7610 expandmeta(struct strlist *str /*, int flag*/)
7611 {
7612         /* TODO - EXP_REDIR */
7613
7614         while (str) {
7615                 char *p;
7616                 glob_t pglob;
7617                 int i;
7618
7619                 if (fflag)
7620                         goto nometa;
7621
7622                 if (!hasmeta(str->text))
7623                         goto nometa;
7624
7625                 INT_OFF;
7626                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7627 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7628 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7629 //
7630 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7631 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7632 // Which means you need to unescape the string, right? Not so fast:
7633 // if there _is_ a file named "file\?" (with backslash), it is returned
7634 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7635 // You DON'T KNOW by looking at the result whether you need to unescape it.
7636 //
7637 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7638 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7639 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7640 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7641 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7642 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7643                 i = glob(p, 0, NULL, &pglob);
7644                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7645                 if (p != str->text)
7646                         free(p);
7647                 switch (i) {
7648                 case 0:
7649 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7650                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7651                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7652                                 goto nometa2;
7653 #endif
7654                         addglob(&pglob);
7655                         globfree(&pglob);
7656                         INT_ON;
7657                         break;
7658                 case GLOB_NOMATCH:
7659  //nometa2:
7660                         globfree(&pglob);
7661                         INT_ON;
7662  nometa:
7663                         *exparg.lastp = str;
7664                         rmescapes(str->text, 0, NULL);
7665                         exparg.lastp = &str->next;
7666                         break;
7667                 default:        /* GLOB_NOSPACE */
7668                         globfree(&pglob);
7669                         INT_ON;
7670                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7671                 }
7672                 str = str->next;
7673         }
7674 }
7675
7676 #else
7677 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7678
7679 /*
7680  * Do metacharacter (i.e. *, ?, [...]) expansion.
7681  */
7682 typedef struct exp_t {
7683         char *dir;
7684         unsigned dir_max;
7685 } exp_t;
7686 static void
7687 expmeta(exp_t *exp, char *name, unsigned name_len, unsigned expdir_len)
7688 {
7689 #define expdir exp->dir
7690 #define expdir_max exp->dir_max
7691         char *enddir = expdir + expdir_len;
7692         char *p;
7693         const char *cp;
7694         char *start;
7695         char *endname;
7696         int metaflag;
7697         struct stat statb;
7698         DIR *dirp;
7699         struct dirent *dp;
7700         int atend;
7701         int matchdot;
7702         int esc;
7703
7704         metaflag = 0;
7705         start = name;
7706         for (p = name; esc = 0, *p; p += esc + 1) {
7707                 if (*p == '*' || *p == '?')
7708                         metaflag = 1;
7709                 else if (*p == '[') {
7710                         char *q = p + 1;
7711                         if (*q == '!')
7712                                 q++;
7713                         for (;;) {
7714                                 if (*q == '\\')
7715                                         q++;
7716                                 if (*q == '/' || *q == '\0')
7717                                         break;
7718                                 if (*++q == ']') {
7719                                         metaflag = 1;
7720                                         break;
7721                                 }
7722                         }
7723                 } else {
7724                         if (*p == '\\' && p[1])
7725                                 esc++;
7726                         if (p[esc] == '/') {
7727                                 if (metaflag)
7728                                         break;
7729                                 start = p + esc + 1;
7730                         }
7731                 }
7732         }
7733         if (metaflag == 0) {    /* we've reached the end of the file name */
7734                 if (!expdir_len)
7735                         return;
7736                 p = name;
7737                 do {
7738                         if (*p == '\\' && p[1])
7739                                 p++;
7740                         *enddir++ = *p;
7741                 } while (*p++);
7742                 if (lstat(expdir, &statb) == 0)
7743                         addfname(expdir);
7744                 return;
7745         }
7746         endname = p;
7747         if (name < start) {
7748                 p = name;
7749                 do {
7750                         if (*p == '\\' && p[1])
7751                                 p++;
7752                         *enddir++ = *p++;
7753                 } while (p < start);
7754         }
7755         *enddir = '\0';
7756         cp = expdir;
7757         expdir_len = enddir - cp;
7758         if (!expdir_len)
7759                 cp = ".";
7760         dirp = opendir(cp);
7761         if (dirp == NULL)
7762                 return;
7763         if (*endname == 0) {
7764                 atend = 1;
7765         } else {
7766                 atend = 0;
7767                 *endname = '\0';
7768                 endname += esc + 1;
7769         }
7770         name_len -= endname - name;
7771         matchdot = 0;
7772         p = start;
7773         if (*p == '\\')
7774                 p++;
7775         if (*p == '.')
7776                 matchdot++;
7777         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7778                 if (dp->d_name[0] == '.' && !matchdot)
7779                         continue;
7780                 if (pmatch(start, dp->d_name)) {
7781                         if (atend) {
7782                                 strcpy(enddir, dp->d_name);
7783                                 addfname(expdir);
7784                         } else {
7785                                 unsigned offset;
7786                                 unsigned len;
7787
7788                                 p = stpcpy(enddir, dp->d_name);
7789                                 *p = '/';
7790
7791                                 offset = p - expdir + 1;
7792                                 len = offset + name_len + NAME_MAX;
7793                                 if (len > expdir_max) {
7794                                         len += PATH_MAX;
7795                                         expdir = ckrealloc(expdir, len);
7796                                         expdir_max = len;
7797                                 }
7798
7799                                 expmeta(exp, endname, name_len, offset);
7800                                 enddir = expdir + expdir_len;
7801                         }
7802                 }
7803         }
7804         closedir(dirp);
7805         if (!atend)
7806                 endname[-esc - 1] = esc ? '\\' : '/';
7807 #undef expdir
7808 #undef expdir_max
7809 }
7810
7811 static struct strlist *
7812 msort(struct strlist *list, int len)
7813 {
7814         struct strlist *p, *q = NULL;
7815         struct strlist **lpp;
7816         int half;
7817         int n;
7818
7819         if (len <= 1)
7820                 return list;
7821         half = len >> 1;
7822         p = list;
7823         for (n = half; --n >= 0;) {
7824                 q = p;
7825                 p = p->next;
7826         }
7827         q->next = NULL;                 /* terminate first half of list */
7828         q = msort(list, half);          /* sort first half of list */
7829         p = msort(p, len - half);               /* sort second half */
7830         lpp = &list;
7831         for (;;) {
7832 #if ENABLE_LOCALE_SUPPORT
7833                 if (strcoll(p->text, q->text) < 0)
7834 #else
7835                 if (strcmp(p->text, q->text) < 0)
7836 #endif
7837                                                 {
7838                         *lpp = p;
7839                         lpp = &p->next;
7840                         p = *lpp;
7841                         if (p == NULL) {
7842                                 *lpp = q;
7843                                 break;
7844                         }
7845                 } else {
7846                         *lpp = q;
7847                         lpp = &q->next;
7848                         q = *lpp;
7849                         if (q == NULL) {
7850                                 *lpp = p;
7851                                 break;
7852                         }
7853                 }
7854         }
7855         return list;
7856 }
7857
7858 /*
7859  * Sort the results of file name expansion.  It calculates the number of
7860  * strings to sort and then calls msort (short for merge sort) to do the
7861  * work.
7862  */
7863 static struct strlist *
7864 expsort(struct strlist *str)
7865 {
7866         int len;
7867         struct strlist *sp;
7868
7869         len = 0;
7870         for (sp = str; sp; sp = sp->next)
7871                 len++;
7872         return msort(str, len);
7873 }
7874
7875 static void
7876 expandmeta(struct strlist *str /*, int flag*/)
7877 {
7878         /* TODO - EXP_REDIR */
7879
7880         while (str) {
7881                 exp_t exp;
7882                 struct strlist **savelastp;
7883                 struct strlist *sp;
7884                 char *p;
7885                 unsigned len;
7886
7887                 if (fflag)
7888                         goto nometa;
7889                 if (!hasmeta(str->text))
7890                         goto nometa;
7891                 savelastp = exparg.lastp;
7892
7893                 INT_OFF;
7894                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7895                 len = strlen(p);
7896                 exp.dir_max = len + PATH_MAX;
7897                 exp.dir = ckmalloc(exp.dir_max);
7898
7899                 expmeta(&exp, p, len, 0);
7900                 free(exp.dir);
7901                 if (p != str->text)
7902                         free(p);
7903                 INT_ON;
7904                 if (exparg.lastp == savelastp) {
7905                         /*
7906                          * no matches
7907                          */
7908  nometa:
7909                         *exparg.lastp = str;
7910                         rmescapes(str->text, 0, NULL);
7911                         exparg.lastp = &str->next;
7912                 } else {
7913                         *exparg.lastp = NULL;
7914                         *savelastp = sp = expsort(*savelastp);
7915                         while (sp->next != NULL)
7916                                 sp = sp->next;
7917                         exparg.lastp = &sp->next;
7918                 }
7919                 str = str->next;
7920         }
7921 }
7922 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7923
7924 /*
7925  * Perform variable substitution and command substitution on an argument,
7926  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7927  * perform splitting and file name expansion.  When arglist is NULL, perform
7928  * here document expansion.
7929  */
7930 static void
7931 expandarg(union node *arg, struct arglist *arglist, int flag)
7932 {
7933         struct strlist *sp;
7934         char *p;
7935
7936         argbackq = arg->narg.backquote;
7937         STARTSTACKSTR(expdest);
7938         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7939         argstr(arg->narg.text, flag);
7940         p = _STPUTC('\0', expdest);
7941         expdest = p - 1;
7942         if (arglist == NULL) {
7943                 /* here document expanded */
7944                 goto out;
7945         }
7946         p = grabstackstr(p);
7947         TRACE(("expandarg: p:'%s'\n", p));
7948         exparg.lastp = &exparg.list;
7949         /*
7950          * TODO - EXP_REDIR
7951          */
7952         if (flag & EXP_FULL) {
7953                 ifsbreakup(p, &exparg);
7954                 *exparg.lastp = NULL;
7955                 exparg.lastp = &exparg.list;
7956                 expandmeta(exparg.list /*, flag*/);
7957         } else {
7958                 sp = stzalloc(sizeof(*sp));
7959                 sp->text = p;
7960                 *exparg.lastp = sp;
7961                 exparg.lastp = &sp->next;
7962         }
7963         *exparg.lastp = NULL;
7964         if (exparg.list) {
7965                 *arglist->lastp = exparg.list;
7966                 arglist->lastp = exparg.lastp;
7967         }
7968
7969  out:
7970         ifsfree();
7971 }
7972
7973 /*
7974  * Expand shell variables and backquotes inside a here document.
7975  */
7976 static void
7977 expandhere(union node *arg, int fd)
7978 {
7979         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7980         full_write(fd, stackblock(), expdest - (char *)stackblock());
7981 }
7982
7983 /*
7984  * Returns true if the pattern matches the string.
7985  */
7986 static int
7987 patmatch(char *pattern, const char *string)
7988 {
7989         char *p = preglob(pattern, 0);
7990         int r = pmatch(p, string);
7991         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7992         return r;
7993 }
7994
7995 /*
7996  * See if a pattern matches in a case statement.
7997  */
7998 static int
7999 casematch(union node *pattern, char *val)
8000 {
8001         struct stackmark smark;
8002         int result;
8003
8004         setstackmark(&smark);
8005         argbackq = pattern->narg.backquote;
8006         STARTSTACKSTR(expdest);
8007         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
8008         STACKSTRNUL(expdest);
8009         ifsfree();
8010         result = patmatch(stackblock(), val);
8011         popstackmark(&smark);
8012         return result;
8013 }
8014
8015
8016 /* ============ find_command */
8017
8018 struct builtincmd {
8019         const char *name;
8020         int (*builtin)(int, char **) FAST_FUNC;
8021         /* unsigned flags; */
8022 };
8023 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
8024 /* "regular" builtins always take precedence over commands,
8025  * regardless of PATH=....%builtin... position */
8026 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
8027 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
8028
8029 struct cmdentry {
8030         smallint cmdtype;       /* CMDxxx */
8031         union param {
8032                 int index;
8033                 /* index >= 0 for commands without path (slashes) */
8034                 /* (TODO: what exactly does the value mean? PATH position?) */
8035                 /* index == -1 for commands with slashes */
8036                 /* index == (-2 - applet_no) for NOFORK applets */
8037                 const struct builtincmd *cmd;
8038                 struct funcnode *func;
8039         } u;
8040 };
8041 /* values of cmdtype */
8042 #define CMDUNKNOWN      -1      /* no entry in table for command */
8043 #define CMDNORMAL       0       /* command is an executable program */
8044 #define CMDFUNCTION     1       /* command is a shell function */
8045 #define CMDBUILTIN      2       /* command is a shell builtin */
8046
8047 /* action to find_command() */
8048 #define DO_ERR          0x01    /* prints errors */
8049 #define DO_ABS          0x02    /* checks absolute paths */
8050 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
8051 #define DO_ALTPATH      0x08    /* using alternate path */
8052 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
8053
8054 static void find_command(char *, struct cmdentry *, int, const char *);
8055
8056
8057 /* ============ Hashing commands */
8058
8059 /*
8060  * When commands are first encountered, they are entered in a hash table.
8061  * This ensures that a full path search will not have to be done for them
8062  * on each invocation.
8063  *
8064  * We should investigate converting to a linear search, even though that
8065  * would make the command name "hash" a misnomer.
8066  */
8067
8068 struct tblentry {
8069         struct tblentry *next;  /* next entry in hash chain */
8070         union param param;      /* definition of builtin function */
8071         smallint cmdtype;       /* CMDxxx */
8072         char rehash;            /* if set, cd done since entry created */
8073         char cmdname[1];        /* name of command */
8074 };
8075
8076 static struct tblentry **cmdtable;
8077 #define INIT_G_cmdtable() do { \
8078         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
8079 } while (0)
8080
8081 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
8082
8083
8084 static void
8085 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
8086 {
8087 #if ENABLE_FEATURE_SH_STANDALONE
8088         if (applet_no >= 0) {
8089                 if (APPLET_IS_NOEXEC(applet_no)) {
8090                         clearenv();
8091                         while (*envp)
8092                                 putenv(*envp++);
8093                         popredir(/*drop:*/ 1);
8094                         run_noexec_applet_and_exit(applet_no, cmd, argv);
8095                 }
8096                 /* re-exec ourselves with the new arguments */
8097                 execve(bb_busybox_exec_path, argv, envp);
8098                 /* If they called chroot or otherwise made the binary no longer
8099                  * executable, fall through */
8100         }
8101 #endif
8102
8103  repeat:
8104 #ifdef SYSV
8105         do {
8106                 execve(cmd, argv, envp);
8107         } while (errno == EINTR);
8108 #else
8109         execve(cmd, argv, envp);
8110 #endif
8111
8112         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8113                 /* Run "cmd" as a shell script:
8114                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8115                  * "If the execve() function fails with ENOEXEC, the shell
8116                  * shall execute a command equivalent to having a shell invoked
8117                  * with the command name as its first operand,
8118                  * with any remaining arguments passed to the new shell"
8119                  *
8120                  * That is, do not use $SHELL, user's shell, or /bin/sh;
8121                  * just call ourselves.
8122                  *
8123                  * Note that bash reads ~80 chars of the file, and if it sees
8124                  * a zero byte before it sees newline, it doesn't try to
8125                  * interpret it, but fails with "cannot execute binary file"
8126                  * message and exit code 126. For one, this prevents attempts
8127                  * to interpret foreign ELF binaries as shell scripts.
8128                  */
8129                 argv[0] = (char*) cmd;
8130                 cmd = bb_busybox_exec_path;
8131                 /* NB: this is only possible because all callers of shellexec()
8132                  * ensure that the argv[-1] slot exists!
8133                  */
8134                 argv--;
8135                 argv[0] = (char*) "ash";
8136                 goto repeat;
8137         }
8138 }
8139
8140 /*
8141  * Exec a program.  Never returns.  If you change this routine, you may
8142  * have to change the find_command routine as well.
8143  * argv[-1] must exist and be writable! See tryexec() for why.
8144  */
8145 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8146 static void shellexec(char *prog, char **argv, const char *path, int idx)
8147 {
8148         char *cmdname;
8149         int e;
8150         char **envp;
8151         int exerrno;
8152         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8153
8154         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8155         if (strchr(prog, '/') != NULL
8156 #if ENABLE_FEATURE_SH_STANDALONE
8157          || (applet_no = find_applet_by_name(prog)) >= 0
8158 #endif
8159         ) {
8160                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8161                 if (applet_no >= 0) {
8162                         /* We tried execing ourself, but it didn't work.
8163                          * Maybe /proc/self/exe doesn't exist?
8164                          * Try $PATH search.
8165                          */
8166                         goto try_PATH;
8167                 }
8168                 e = errno;
8169         } else {
8170  try_PATH:
8171                 e = ENOENT;
8172                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8173                         if (--idx < 0 && pathopt == NULL) {
8174                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8175                                 if (errno != ENOENT && errno != ENOTDIR)
8176                                         e = errno;
8177                         }
8178                         stunalloc(cmdname);
8179                 }
8180         }
8181
8182         /* Map to POSIX errors */
8183         switch (e) {
8184         default:
8185                 exerrno = 126;
8186                 break;
8187         case ELOOP:
8188         case ENAMETOOLONG:
8189         case ENOENT:
8190         case ENOTDIR:
8191                 exerrno = 127;
8192                 break;
8193         }
8194         exitstatus = exerrno;
8195         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8196                 prog, e, suppress_int));
8197         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8198         /* NOTREACHED */
8199 }
8200
8201 static void
8202 printentry(struct tblentry *cmdp)
8203 {
8204         int idx;
8205         const char *path;
8206         char *name;
8207
8208         idx = cmdp->param.index;
8209         path = pathval();
8210         do {
8211                 name = path_advance(&path, cmdp->cmdname);
8212                 stunalloc(name);
8213         } while (--idx >= 0);
8214         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8215 }
8216
8217 /*
8218  * Clear out command entries.  The argument specifies the first entry in
8219  * PATH which has changed.
8220  */
8221 static void
8222 clearcmdentry(int firstchange)
8223 {
8224         struct tblentry **tblp;
8225         struct tblentry **pp;
8226         struct tblentry *cmdp;
8227
8228         INT_OFF;
8229         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8230                 pp = tblp;
8231                 while ((cmdp = *pp) != NULL) {
8232                         if ((cmdp->cmdtype == CMDNORMAL &&
8233                              cmdp->param.index >= firstchange)
8234                          || (cmdp->cmdtype == CMDBUILTIN &&
8235                              builtinloc >= firstchange)
8236                         ) {
8237                                 *pp = cmdp->next;
8238                                 free(cmdp);
8239                         } else {
8240                                 pp = &cmdp->next;
8241                         }
8242                 }
8243         }
8244         INT_ON;
8245 }
8246
8247 /*
8248  * Locate a command in the command hash table.  If "add" is nonzero,
8249  * add the command to the table if it is not already present.  The
8250  * variable "lastcmdentry" is set to point to the address of the link
8251  * pointing to the entry, so that delete_cmd_entry can delete the
8252  * entry.
8253  *
8254  * Interrupts must be off if called with add != 0.
8255  */
8256 static struct tblentry **lastcmdentry;
8257
8258 static struct tblentry *
8259 cmdlookup(const char *name, int add)
8260 {
8261         unsigned int hashval;
8262         const char *p;
8263         struct tblentry *cmdp;
8264         struct tblentry **pp;
8265
8266         p = name;
8267         hashval = (unsigned char)*p << 4;
8268         while (*p)
8269                 hashval += (unsigned char)*p++;
8270         hashval &= 0x7FFF;
8271         pp = &cmdtable[hashval % CMDTABLESIZE];
8272         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8273                 if (strcmp(cmdp->cmdname, name) == 0)
8274                         break;
8275                 pp = &cmdp->next;
8276         }
8277         if (add && cmdp == NULL) {
8278                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8279                                 + strlen(name)
8280                                 /* + 1 - already done because
8281                                  * tblentry::cmdname is char[1] */);
8282                 /*cmdp->next = NULL; - ckzalloc did it */
8283                 cmdp->cmdtype = CMDUNKNOWN;
8284                 strcpy(cmdp->cmdname, name);
8285         }
8286         lastcmdentry = pp;
8287         return cmdp;
8288 }
8289
8290 /*
8291  * Delete the command entry returned on the last lookup.
8292  */
8293 static void
8294 delete_cmd_entry(void)
8295 {
8296         struct tblentry *cmdp;
8297
8298         INT_OFF;
8299         cmdp = *lastcmdentry;
8300         *lastcmdentry = cmdp->next;
8301         if (cmdp->cmdtype == CMDFUNCTION)
8302                 freefunc(cmdp->param.func);
8303         free(cmdp);
8304         INT_ON;
8305 }
8306
8307 /*
8308  * Add a new command entry, replacing any existing command entry for
8309  * the same name - except special builtins.
8310  */
8311 static void
8312 addcmdentry(char *name, struct cmdentry *entry)
8313 {
8314         struct tblentry *cmdp;
8315
8316         cmdp = cmdlookup(name, 1);
8317         if (cmdp->cmdtype == CMDFUNCTION) {
8318                 freefunc(cmdp->param.func);
8319         }
8320         cmdp->cmdtype = entry->cmdtype;
8321         cmdp->param = entry->u;
8322         cmdp->rehash = 0;
8323 }
8324
8325 static int FAST_FUNC
8326 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8327 {
8328         struct tblentry **pp;
8329         struct tblentry *cmdp;
8330         int c;
8331         struct cmdentry entry;
8332         char *name;
8333
8334         if (nextopt("r") != '\0') {
8335                 clearcmdentry(0);
8336                 return 0;
8337         }
8338
8339         if (*argptr == NULL) {
8340                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8341                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8342                                 if (cmdp->cmdtype == CMDNORMAL)
8343                                         printentry(cmdp);
8344                         }
8345                 }
8346                 return 0;
8347         }
8348
8349         c = 0;
8350         while ((name = *argptr) != NULL) {
8351                 cmdp = cmdlookup(name, 0);
8352                 if (cmdp != NULL
8353                  && (cmdp->cmdtype == CMDNORMAL
8354                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8355                 ) {
8356                         delete_cmd_entry();
8357                 }
8358                 find_command(name, &entry, DO_ERR, pathval());
8359                 if (entry.cmdtype == CMDUNKNOWN)
8360                         c = 1;
8361                 argptr++;
8362         }
8363         return c;
8364 }
8365
8366 /*
8367  * Called when a cd is done.  Marks all commands so the next time they
8368  * are executed they will be rehashed.
8369  */
8370 static void
8371 hashcd(void)
8372 {
8373         struct tblentry **pp;
8374         struct tblentry *cmdp;
8375
8376         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8377                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8378                         if (cmdp->cmdtype == CMDNORMAL
8379                          || (cmdp->cmdtype == CMDBUILTIN
8380                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8381                              && builtinloc > 0)
8382                         ) {
8383                                 cmdp->rehash = 1;
8384                         }
8385                 }
8386         }
8387 }
8388
8389 /*
8390  * Fix command hash table when PATH changed.
8391  * Called before PATH is changed.  The argument is the new value of PATH;
8392  * pathval() still returns the old value at this point.
8393  * Called with interrupts off.
8394  */
8395 static void FAST_FUNC
8396 changepath(const char *new)
8397 {
8398         const char *old;
8399         int firstchange;
8400         int idx;
8401         int idx_bltin;
8402
8403         old = pathval();
8404         firstchange = 9999;     /* assume no change */
8405         idx = 0;
8406         idx_bltin = -1;
8407         for (;;) {
8408                 if (*old != *new) {
8409                         firstchange = idx;
8410                         if ((*old == '\0' && *new == ':')
8411                          || (*old == ':' && *new == '\0')
8412                         ) {
8413                                 firstchange++;
8414                         }
8415                         old = new;      /* ignore subsequent differences */
8416                 }
8417                 if (*new == '\0')
8418                         break;
8419                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8420                         idx_bltin = idx;
8421                 if (*new == ':')
8422                         idx++;
8423                 new++;
8424                 old++;
8425         }
8426         if (builtinloc < 0 && idx_bltin >= 0)
8427                 builtinloc = idx_bltin;             /* zap builtins */
8428         if (builtinloc >= 0 && idx_bltin < 0)
8429                 firstchange = 0;
8430         clearcmdentry(firstchange);
8431         builtinloc = idx_bltin;
8432 }
8433 enum {
8434         TEOF,
8435         TNL,
8436         TREDIR,
8437         TWORD,
8438         TSEMI,
8439         TBACKGND,
8440         TAND,
8441         TOR,
8442         TPIPE,
8443         TLP,
8444         TRP,
8445         TENDCASE,
8446         TENDBQUOTE,
8447         TNOT,
8448         TCASE,
8449         TDO,
8450         TDONE,
8451         TELIF,
8452         TELSE,
8453         TESAC,
8454         TFI,
8455         TFOR,
8456 #if BASH_FUNCTION
8457         TFUNCTION,
8458 #endif
8459         TIF,
8460         TIN,
8461         TTHEN,
8462         TUNTIL,
8463         TWHILE,
8464         TBEGIN,
8465         TEND
8466 };
8467 typedef smallint token_id_t;
8468
8469 /* Nth bit indicates if token marks the end of a list */
8470 enum {
8471         tokendlist = 0
8472         /*  0 */ | (1u << TEOF)
8473         /*  1 */ | (0u << TNL)
8474         /*  2 */ | (0u << TREDIR)
8475         /*  3 */ | (0u << TWORD)
8476         /*  4 */ | (0u << TSEMI)
8477         /*  5 */ | (0u << TBACKGND)
8478         /*  6 */ | (0u << TAND)
8479         /*  7 */ | (0u << TOR)
8480         /*  8 */ | (0u << TPIPE)
8481         /*  9 */ | (0u << TLP)
8482         /* 10 */ | (1u << TRP)
8483         /* 11 */ | (1u << TENDCASE)
8484         /* 12 */ | (1u << TENDBQUOTE)
8485         /* 13 */ | (0u << TNOT)
8486         /* 14 */ | (0u << TCASE)
8487         /* 15 */ | (1u << TDO)
8488         /* 16 */ | (1u << TDONE)
8489         /* 17 */ | (1u << TELIF)
8490         /* 18 */ | (1u << TELSE)
8491         /* 19 */ | (1u << TESAC)
8492         /* 20 */ | (1u << TFI)
8493         /* 21 */ | (0u << TFOR)
8494 #if BASH_FUNCTION
8495         /* 22 */ | (0u << TFUNCTION)
8496 #endif
8497         /* 23 */ | (0u << TIF)
8498         /* 24 */ | (0u << TIN)
8499         /* 25 */ | (1u << TTHEN)
8500         /* 26 */ | (0u << TUNTIL)
8501         /* 27 */ | (0u << TWHILE)
8502         /* 28 */ | (0u << TBEGIN)
8503         /* 29 */ | (1u << TEND)
8504         , /* thus far 29 bits used */
8505 };
8506
8507 static const char *const tokname_array[] = {
8508         "end of file",
8509         "newline",
8510         "redirection",
8511         "word",
8512         ";",
8513         "&",
8514         "&&",
8515         "||",
8516         "|",
8517         "(",
8518         ")",
8519         ";;",
8520         "`",
8521 #define KWDOFFSET 13
8522         /* the following are keywords */
8523         "!",
8524         "case",
8525         "do",
8526         "done",
8527         "elif",
8528         "else",
8529         "esac",
8530         "fi",
8531         "for",
8532 #if BASH_FUNCTION
8533         "function",
8534 #endif
8535         "if",
8536         "in",
8537         "then",
8538         "until",
8539         "while",
8540         "{",
8541         "}",
8542 };
8543
8544 /* Wrapper around strcmp for qsort/bsearch/... */
8545 static int
8546 pstrcmp(const void *a, const void *b)
8547 {
8548         return strcmp((char*)a, *(char**)b);
8549 }
8550
8551 static const char *const *
8552 findkwd(const char *s)
8553 {
8554         return bsearch(s, tokname_array + KWDOFFSET,
8555                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8556                         sizeof(tokname_array[0]), pstrcmp);
8557 }
8558
8559 /*
8560  * Locate and print what a word is...
8561  */
8562 static int
8563 describe_command(char *command, const char *path, int describe_command_verbose)
8564 {
8565         struct cmdentry entry;
8566 #if ENABLE_ASH_ALIAS
8567         const struct alias *ap;
8568 #endif
8569
8570         path = path ? path : pathval();
8571
8572         if (describe_command_verbose) {
8573                 out1str(command);
8574         }
8575
8576         /* First look at the keywords */
8577         if (findkwd(command)) {
8578                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8579                 goto out;
8580         }
8581
8582 #if ENABLE_ASH_ALIAS
8583         /* Then look at the aliases */
8584         ap = lookupalias(command, 0);
8585         if (ap != NULL) {
8586                 if (!describe_command_verbose) {
8587                         out1str("alias ");
8588                         printalias(ap);
8589                         return 0;
8590                 }
8591                 out1fmt(" is an alias for %s", ap->val);
8592                 goto out;
8593         }
8594 #endif
8595         /* Brute force */
8596         find_command(command, &entry, DO_ABS, path);
8597
8598         switch (entry.cmdtype) {
8599         case CMDNORMAL: {
8600                 int j = entry.u.index;
8601                 char *p;
8602                 if (j < 0) {
8603                         p = command;
8604                 } else {
8605                         do {
8606                                 p = path_advance(&path, command);
8607                                 stunalloc(p);
8608                         } while (--j >= 0);
8609                 }
8610                 if (describe_command_verbose) {
8611                         out1fmt(" is %s", p);
8612                 } else {
8613                         out1str(p);
8614                 }
8615                 break;
8616         }
8617
8618         case CMDFUNCTION:
8619                 if (describe_command_verbose) {
8620                         /*out1str(" is a shell function");*/
8621                         out1str(" is a function"); /* bash says this */
8622                 } else {
8623                         out1str(command);
8624                 }
8625                 break;
8626
8627         case CMDBUILTIN:
8628                 if (describe_command_verbose) {
8629                         out1fmt(" is a %sshell builtin",
8630                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8631                                         "special " : nullstr
8632                         );
8633                 } else {
8634                         out1str(command);
8635                 }
8636                 break;
8637
8638         default:
8639                 if (describe_command_verbose) {
8640                         out1str(": not found\n");
8641                 }
8642                 return 127;
8643         }
8644  out:
8645         out1str("\n");
8646         return 0;
8647 }
8648
8649 static int FAST_FUNC
8650 typecmd(int argc UNUSED_PARAM, char **argv)
8651 {
8652         int i = 1;
8653         int err = 0;
8654         int verbose = 1;
8655
8656         /* type -p ... ? (we don't bother checking for 'p') */
8657         if (argv[1] && argv[1][0] == '-') {
8658                 i++;
8659                 verbose = 0;
8660         }
8661         while (argv[i]) {
8662                 err |= describe_command(argv[i++], NULL, verbose);
8663         }
8664         return err;
8665 }
8666
8667 #if ENABLE_ASH_CMDCMD
8668 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8669 static char **
8670 parse_command_args(char **argv, const char **path)
8671 {
8672         char *cp, c;
8673
8674         for (;;) {
8675                 cp = *++argv;
8676                 if (!cp)
8677                         return NULL;
8678                 if (*cp++ != '-')
8679                         break;
8680                 c = *cp++;
8681                 if (!c)
8682                         break;
8683                 if (c == '-' && !*cp) {
8684                         if (!*++argv)
8685                                 return NULL;
8686                         break;
8687                 }
8688                 do {
8689                         switch (c) {
8690                         case 'p':
8691                                 *path = bb_default_path;
8692                                 break;
8693                         default:
8694                                 /* run 'typecmd' for other options */
8695                                 return NULL;
8696                         }
8697                         c = *cp++;
8698                 } while (c);
8699         }
8700         return argv;
8701 }
8702
8703 static int FAST_FUNC
8704 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8705 {
8706         char *cmd;
8707         int c;
8708         enum {
8709                 VERIFY_BRIEF = 1,
8710                 VERIFY_VERBOSE = 2,
8711         } verify = 0;
8712         const char *path = NULL;
8713
8714         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8715          * never reaches this function.
8716          */
8717
8718         while ((c = nextopt("pvV")) != '\0')
8719                 if (c == 'V')
8720                         verify |= VERIFY_VERBOSE;
8721                 else if (c == 'v')
8722                         /*verify |= VERIFY_BRIEF*/;
8723 #if DEBUG
8724                 else if (c != 'p')
8725                         abort();
8726 #endif
8727                 else
8728                         path = bb_default_path;
8729
8730         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8731         cmd = *argptr;
8732         if (/*verify && */ cmd)
8733                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8734
8735         return 0;
8736 }
8737 #endif
8738
8739
8740 /*static int funcblocksize;     // size of structures in function */
8741 /*static int funcstringsize;    // size of strings in node */
8742 static void *funcblock;         /* block to allocate function from */
8743 static char *funcstring_end;    /* end of block to allocate strings from */
8744
8745 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8746         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8747         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8748         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8749         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8750         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8751         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8752         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8753         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8754         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8755         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8756         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8757         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8758         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8759         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8760         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8761         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8762         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8763 #if BASH_REDIR_OUTPUT
8764         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8765 #endif
8766         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8767         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8768         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8769         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8770         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8771         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8772         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8773         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8774         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8775 };
8776
8777 static int calcsize(int funcblocksize, union node *n);
8778
8779 static int
8780 sizenodelist(int funcblocksize, struct nodelist *lp)
8781 {
8782         while (lp) {
8783                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8784                 funcblocksize = calcsize(funcblocksize, lp->n);
8785                 lp = lp->next;
8786         }
8787         return funcblocksize;
8788 }
8789
8790 static int
8791 calcsize(int funcblocksize, union node *n)
8792 {
8793         if (n == NULL)
8794                 return funcblocksize;
8795         funcblocksize += nodesize[n->type];
8796         switch (n->type) {
8797         case NCMD:
8798                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8799                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8800                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8801                 break;
8802         case NPIPE:
8803                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8804                 break;
8805         case NREDIR:
8806         case NBACKGND:
8807         case NSUBSHELL:
8808                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8809                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8810                 break;
8811         case NAND:
8812         case NOR:
8813         case NSEMI:
8814         case NWHILE:
8815         case NUNTIL:
8816                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8817                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8818                 break;
8819         case NIF:
8820                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8821                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8822                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8823                 break;
8824         case NFOR:
8825                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8826                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8827                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8828                 break;
8829         case NCASE:
8830                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8831                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8832                 break;
8833         case NCLIST:
8834                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8835                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8836                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8837                 break;
8838         case NDEFUN:
8839                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8840                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8841                 break;
8842         case NARG:
8843                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8844                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8845                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8846                 break;
8847         case NTO:
8848 #if BASH_REDIR_OUTPUT
8849         case NTO2:
8850 #endif
8851         case NCLOBBER:
8852         case NFROM:
8853         case NFROMTO:
8854         case NAPPEND:
8855                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8856                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8857                 break;
8858         case NTOFD:
8859         case NFROMFD:
8860                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8861                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8862         break;
8863         case NHERE:
8864         case NXHERE:
8865                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8866                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8867                 break;
8868         case NNOT:
8869                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8870                 break;
8871         };
8872         return funcblocksize;
8873 }
8874
8875 static char *
8876 nodeckstrdup(char *s)
8877 {
8878         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8879         return strcpy(funcstring_end, s);
8880 }
8881
8882 static union node *copynode(union node *);
8883
8884 static struct nodelist *
8885 copynodelist(struct nodelist *lp)
8886 {
8887         struct nodelist *start;
8888         struct nodelist **lpp;
8889
8890         lpp = &start;
8891         while (lp) {
8892                 *lpp = funcblock;
8893                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8894                 (*lpp)->n = copynode(lp->n);
8895                 lp = lp->next;
8896                 lpp = &(*lpp)->next;
8897         }
8898         *lpp = NULL;
8899         return start;
8900 }
8901
8902 static union node *
8903 copynode(union node *n)
8904 {
8905         union node *new;
8906
8907         if (n == NULL)
8908                 return NULL;
8909         new = funcblock;
8910         funcblock = (char *) funcblock + nodesize[n->type];
8911
8912         switch (n->type) {
8913         case NCMD:
8914                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8915                 new->ncmd.args = copynode(n->ncmd.args);
8916                 new->ncmd.assign = copynode(n->ncmd.assign);
8917                 new->ncmd.linno = n->ncmd.linno;
8918                 break;
8919         case NPIPE:
8920                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8921                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8922                 break;
8923         case NREDIR:
8924         case NBACKGND:
8925         case NSUBSHELL:
8926                 new->nredir.redirect = copynode(n->nredir.redirect);
8927                 new->nredir.n = copynode(n->nredir.n);
8928                 new->nredir.linno = n->nredir.linno;
8929                 break;
8930         case NAND:
8931         case NOR:
8932         case NSEMI:
8933         case NWHILE:
8934         case NUNTIL:
8935                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8936                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8937                 break;
8938         case NIF:
8939                 new->nif.elsepart = copynode(n->nif.elsepart);
8940                 new->nif.ifpart = copynode(n->nif.ifpart);
8941                 new->nif.test = copynode(n->nif.test);
8942                 break;
8943         case NFOR:
8944                 new->nfor.var = nodeckstrdup(n->nfor.var);
8945                 new->nfor.body = copynode(n->nfor.body);
8946                 new->nfor.args = copynode(n->nfor.args);
8947                 new->nfor.linno = n->nfor.linno;
8948                 break;
8949         case NCASE:
8950                 new->ncase.cases = copynode(n->ncase.cases);
8951                 new->ncase.expr = copynode(n->ncase.expr);
8952                 new->ncase.linno = n->ncase.linno;
8953                 break;
8954         case NCLIST:
8955                 new->nclist.body = copynode(n->nclist.body);
8956                 new->nclist.pattern = copynode(n->nclist.pattern);
8957                 new->nclist.next = copynode(n->nclist.next);
8958                 break;
8959         case NDEFUN:
8960                 new->ndefun.body = copynode(n->ndefun.body);
8961                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8962                 new->ndefun.linno = n->ndefun.linno;
8963                 break;
8964         case NARG:
8965                 new->narg.backquote = copynodelist(n->narg.backquote);
8966                 new->narg.text = nodeckstrdup(n->narg.text);
8967                 new->narg.next = copynode(n->narg.next);
8968                 break;
8969         case NTO:
8970 #if BASH_REDIR_OUTPUT
8971         case NTO2:
8972 #endif
8973         case NCLOBBER:
8974         case NFROM:
8975         case NFROMTO:
8976         case NAPPEND:
8977                 new->nfile.fname = copynode(n->nfile.fname);
8978                 new->nfile.fd = n->nfile.fd;
8979                 new->nfile.next = copynode(n->nfile.next);
8980                 break;
8981         case NTOFD:
8982         case NFROMFD:
8983                 new->ndup.vname = copynode(n->ndup.vname);
8984                 new->ndup.dupfd = n->ndup.dupfd;
8985                 new->ndup.fd = n->ndup.fd;
8986                 new->ndup.next = copynode(n->ndup.next);
8987                 break;
8988         case NHERE:
8989         case NXHERE:
8990                 new->nhere.doc = copynode(n->nhere.doc);
8991                 new->nhere.fd = n->nhere.fd;
8992                 new->nhere.next = copynode(n->nhere.next);
8993                 break;
8994         case NNOT:
8995                 new->nnot.com = copynode(n->nnot.com);
8996                 break;
8997         };
8998         new->type = n->type;
8999         return new;
9000 }
9001
9002 /*
9003  * Make a copy of a parse tree.
9004  */
9005 static struct funcnode *
9006 copyfunc(union node *n)
9007 {
9008         struct funcnode *f;
9009         size_t blocksize;
9010
9011         /*funcstringsize = 0;*/
9012         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
9013         f = ckzalloc(blocksize /* + funcstringsize */);
9014         funcblock = (char *) f + offsetof(struct funcnode, n);
9015         funcstring_end = (char *) f + blocksize;
9016         copynode(n);
9017         /* f->count = 0; - ckzalloc did it */
9018         return f;
9019 }
9020
9021 /*
9022  * Define a shell function.
9023  */
9024 static void
9025 defun(union node *func)
9026 {
9027         struct cmdentry entry;
9028
9029         INT_OFF;
9030         entry.cmdtype = CMDFUNCTION;
9031         entry.u.func = copyfunc(func);
9032         addcmdentry(func->ndefun.text, &entry);
9033         INT_ON;
9034 }
9035
9036 /* Reasons for skipping commands (see comment on breakcmd routine) */
9037 #define SKIPBREAK      (1 << 0)
9038 #define SKIPCONT       (1 << 1)
9039 #define SKIPFUNC       (1 << 2)
9040 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
9041 static int skipcount;           /* number of levels to skip */
9042 static int loopnest;            /* current loop nesting level */
9043 static int funcline;            /* starting line number of current function, or 0 if not in a function */
9044
9045 /* Forward decl way out to parsing code - dotrap needs it */
9046 static int evalstring(char *s, int flags);
9047
9048 /* Called to execute a trap.
9049  * Single callsite - at the end of evaltree().
9050  * If we return non-zero, evaltree raises EXEXIT exception.
9051  *
9052  * Perhaps we should avoid entering new trap handlers
9053  * while we are executing a trap handler. [is it a TODO?]
9054  */
9055 static void
9056 dotrap(void)
9057 {
9058         uint8_t *g;
9059         int sig;
9060         int status, last_status;
9061
9062         if (!pending_sig)
9063                 return;
9064
9065         status = savestatus;
9066         last_status = status;
9067         if (status < 0) {
9068                 status = exitstatus;
9069                 savestatus = status;
9070         }
9071         pending_sig = 0;
9072         barrier();
9073
9074         TRACE(("dotrap entered\n"));
9075         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
9076                 char *p;
9077
9078                 if (!*g)
9079                         continue;
9080
9081                 if (evalskip) {
9082                         pending_sig = sig;
9083                         break;
9084                 }
9085
9086                 p = trap[sig];
9087                 /* non-trapped SIGINT is handled separately by raise_interrupt,
9088                  * don't upset it by resetting gotsig[SIGINT-1] */
9089                 if (sig == SIGINT && !p)
9090                         continue;
9091
9092                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
9093                 *g = 0;
9094                 if (!p)
9095                         continue;
9096                 evalstring(p, 0);
9097                 exitstatus = status;
9098         }
9099
9100         savestatus = last_status;
9101         TRACE(("dotrap returns\n"));
9102 }
9103
9104 /* forward declarations - evaluation is fairly recursive business... */
9105 static int evalloop(union node *, int);
9106 static int evalfor(union node *, int);
9107 static int evalcase(union node *, int);
9108 static int evalsubshell(union node *, int);
9109 static void expredir(union node *);
9110 static int evalpipe(union node *, int);
9111 static int evalcommand(union node *, int);
9112 static int evalbltin(const struct builtincmd *, int, char **, int);
9113 static void prehash(union node *);
9114
9115 /*
9116  * Evaluate a parse tree.  The value is left in the global variable
9117  * exitstatus.
9118  */
9119 static int
9120 evaltree(union node *n, int flags)
9121 {
9122         int checkexit = 0;
9123         int (*evalfn)(union node *, int);
9124         struct stackmark smark;
9125         int status = 0;
9126
9127         setstackmark(&smark);
9128
9129         if (n == NULL) {
9130                 TRACE(("evaltree(NULL) called\n"));
9131                 goto out;
9132         }
9133         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
9134
9135         dotrap();
9136
9137         switch (n->type) {
9138         default:
9139 #if DEBUG
9140                 out1fmt("Node type = %d\n", n->type);
9141                 fflush_all();
9142                 break;
9143 #endif
9144         case NNOT:
9145                 status = !evaltree(n->nnot.com, EV_TESTED);
9146                 goto setstatus;
9147         case NREDIR:
9148                 errlinno = lineno = n->nredir.linno;
9149                 if (funcline)
9150                         lineno -= funcline - 1;
9151                 expredir(n->nredir.redirect);
9152                 pushredir(n->nredir.redirect);
9153                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9154                 if (!status) {
9155                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9156                 }
9157                 if (n->nredir.redirect)
9158                         popredir(/*drop:*/ 0);
9159                 goto setstatus;
9160         case NCMD:
9161                 evalfn = evalcommand;
9162  checkexit:
9163                 if (eflag && !(flags & EV_TESTED))
9164                         checkexit = ~0;
9165                 goto calleval;
9166         case NFOR:
9167                 evalfn = evalfor;
9168                 goto calleval;
9169         case NWHILE:
9170         case NUNTIL:
9171                 evalfn = evalloop;
9172                 goto calleval;
9173         case NSUBSHELL:
9174         case NBACKGND:
9175                 evalfn = evalsubshell;
9176                 goto checkexit;
9177         case NPIPE:
9178                 evalfn = evalpipe;
9179                 goto checkexit;
9180         case NCASE:
9181                 evalfn = evalcase;
9182                 goto calleval;
9183         case NAND:
9184         case NOR:
9185         case NSEMI: {
9186
9187 #if NAND + 1 != NOR
9188 #error NAND + 1 != NOR
9189 #endif
9190 #if NOR + 1 != NSEMI
9191 #error NOR + 1 != NSEMI
9192 #endif
9193                 unsigned is_or = n->type - NAND;
9194                 status = evaltree(
9195                         n->nbinary.ch1,
9196                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9197                 );
9198                 if ((!status) == is_or || evalskip)
9199                         break;
9200                 n = n->nbinary.ch2;
9201  evaln:
9202                 evalfn = evaltree;
9203  calleval:
9204                 status = evalfn(n, flags);
9205                 goto setstatus;
9206         }
9207         case NIF:
9208                 status = evaltree(n->nif.test, EV_TESTED);
9209                 if (evalskip)
9210                         break;
9211                 if (!status) {
9212                         n = n->nif.ifpart;
9213                         goto evaln;
9214                 }
9215                 if (n->nif.elsepart) {
9216                         n = n->nif.elsepart;
9217                         goto evaln;
9218                 }
9219                 status = 0;
9220                 goto setstatus;
9221         case NDEFUN:
9222                 defun(n);
9223                 /* Not necessary. To test it:
9224                  * "false; f() { qwerty; }; echo $?" should print 0.
9225                  */
9226                 /* status = 0; */
9227  setstatus:
9228                 exitstatus = status;
9229                 break;
9230         }
9231  out:
9232         /* Order of checks below is important:
9233          * signal handlers trigger before exit caused by "set -e".
9234          */
9235         dotrap();
9236
9237         if (checkexit & status)
9238                 raise_exception(EXEXIT);
9239         if (flags & EV_EXIT)
9240                 raise_exception(EXEXIT);
9241
9242         popstackmark(&smark);
9243         TRACE(("leaving evaltree (no interrupts)\n"));
9244         return exitstatus;
9245 }
9246
9247 static int
9248 skiploop(void)
9249 {
9250         int skip = evalskip;
9251
9252         switch (skip) {
9253         case 0:
9254                 break;
9255         case SKIPBREAK:
9256         case SKIPCONT:
9257                 if (--skipcount <= 0) {
9258                         evalskip = 0;
9259                         break;
9260                 }
9261                 skip = SKIPBREAK;
9262                 break;
9263         }
9264         return skip;
9265 }
9266
9267 static int
9268 evalloop(union node *n, int flags)
9269 {
9270         int skip;
9271         int status;
9272
9273         loopnest++;
9274         status = 0;
9275         flags &= EV_TESTED;
9276         do {
9277                 int i;
9278
9279                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9280                 skip = skiploop();
9281                 if (skip == SKIPFUNC)
9282                         status = i;
9283                 if (skip)
9284                         continue;
9285                 if (n->type != NWHILE)
9286                         i = !i;
9287                 if (i != 0)
9288                         break;
9289                 status = evaltree(n->nbinary.ch2, flags);
9290                 skip = skiploop();
9291         } while (!(skip & ~SKIPCONT));
9292         loopnest--;
9293
9294         return status;
9295 }
9296
9297 static int
9298 evalfor(union node *n, int flags)
9299 {
9300         struct arglist arglist;
9301         union node *argp;
9302         struct strlist *sp;
9303         int status = 0;
9304
9305         errlinno = lineno = n->ncase.linno;
9306         if (funcline)
9307                 lineno -= funcline - 1;
9308
9309         arglist.list = NULL;
9310         arglist.lastp = &arglist.list;
9311         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9312                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9313         }
9314         *arglist.lastp = NULL;
9315
9316         loopnest++;
9317         flags &= EV_TESTED;
9318         for (sp = arglist.list; sp; sp = sp->next) {
9319                 setvar0(n->nfor.var, sp->text);
9320                 status = evaltree(n->nfor.body, flags);
9321                 if (skiploop() & ~SKIPCONT)
9322                         break;
9323         }
9324         loopnest--;
9325
9326         return status;
9327 }
9328
9329 static int
9330 evalcase(union node *n, int flags)
9331 {
9332         union node *cp;
9333         union node *patp;
9334         struct arglist arglist;
9335         int status = 0;
9336
9337         errlinno = lineno = n->ncase.linno;
9338         if (funcline)
9339                 lineno -= funcline - 1;
9340
9341         arglist.list = NULL;
9342         arglist.lastp = &arglist.list;
9343         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9344         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9345                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9346                         if (casematch(patp, arglist.list->text)) {
9347                                 /* Ensure body is non-empty as otherwise
9348                                  * EV_EXIT may prevent us from setting the
9349                                  * exit status.
9350                                  */
9351                                 if (evalskip == 0 && cp->nclist.body) {
9352                                         status = evaltree(cp->nclist.body, flags);
9353                                 }
9354                                 goto out;
9355                         }
9356                 }
9357         }
9358  out:
9359         return status;
9360 }
9361
9362 /*
9363  * Kick off a subshell to evaluate a tree.
9364  */
9365 static int
9366 evalsubshell(union node *n, int flags)
9367 {
9368         struct job *jp;
9369         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9370         int status;
9371
9372         errlinno = lineno = n->nredir.linno;
9373         if (funcline)
9374                 lineno -= funcline - 1;
9375
9376         expredir(n->nredir.redirect);
9377         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9378                 goto nofork;
9379         INT_OFF;
9380         if (backgnd == FORK_FG)
9381                 get_tty_state();
9382         jp = makejob(/*n,*/ 1);
9383         if (forkshell(jp, n, backgnd) == 0) {
9384                 /* child */
9385                 INT_ON;
9386                 flags |= EV_EXIT;
9387                 if (backgnd)
9388                         flags &= ~EV_TESTED;
9389  nofork:
9390                 redirect(n->nredir.redirect, 0);
9391                 evaltreenr(n->nredir.n, flags);
9392                 /* never returns */
9393         }
9394         /* parent */
9395         status = 0;
9396         if (backgnd == FORK_FG)
9397                 status = waitforjob(jp);
9398         INT_ON;
9399         return status;
9400 }
9401
9402 /*
9403  * Compute the names of the files in a redirection list.
9404  */
9405 static void fixredir(union node *, const char *, int);
9406 static void
9407 expredir(union node *n)
9408 {
9409         union node *redir;
9410
9411         for (redir = n; redir; redir = redir->nfile.next) {
9412                 struct arglist fn;
9413
9414                 fn.list = NULL;
9415                 fn.lastp = &fn.list;
9416                 switch (redir->type) {
9417                 case NFROMTO:
9418                 case NFROM:
9419                 case NTO:
9420 #if BASH_REDIR_OUTPUT
9421                 case NTO2:
9422 #endif
9423                 case NCLOBBER:
9424                 case NAPPEND:
9425                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9426                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9427 #if BASH_REDIR_OUTPUT
9428  store_expfname:
9429 #endif
9430 #if 0
9431 // By the design of stack allocator, the loop of this kind:
9432 //      while true; do while true; do break; done </dev/null; done
9433 // will look like a memory leak: ash plans to free expfname's
9434 // of "/dev/null" as soon as it finishes running the loop
9435 // (in this case, never).
9436 // This "fix" is wrong:
9437                         if (redir->nfile.expfname)
9438                                 stunalloc(redir->nfile.expfname);
9439 // It results in corrupted state of stacked allocations.
9440 #endif
9441                         redir->nfile.expfname = fn.list->text;
9442                         break;
9443                 case NFROMFD:
9444                 case NTOFD: /* >& */
9445                         if (redir->ndup.vname) {
9446                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9447                                 if (fn.list == NULL)
9448                                         ash_msg_and_raise_error("redir error");
9449 #if BASH_REDIR_OUTPUT
9450 //FIXME: we used expandarg with different args!
9451                                 if (!isdigit_str9(fn.list->text)) {
9452                                         /* >&file, not >&fd */
9453                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9454                                                 ash_msg_and_raise_error("redir error");
9455                                         redir->type = NTO2;
9456                                         goto store_expfname;
9457                                 }
9458 #endif
9459                                 fixredir(redir, fn.list->text, 1);
9460                         }
9461                         break;
9462                 }
9463         }
9464 }
9465
9466 /*
9467  * Evaluate a pipeline.  All the processes in the pipeline are children
9468  * of the process creating the pipeline.  (This differs from some versions
9469  * of the shell, which make the last process in a pipeline the parent
9470  * of all the rest.)
9471  */
9472 static int
9473 evalpipe(union node *n, int flags)
9474 {
9475         struct job *jp;
9476         struct nodelist *lp;
9477         int pipelen;
9478         int prevfd;
9479         int pip[2];
9480         int status = 0;
9481
9482         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9483         pipelen = 0;
9484         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9485                 pipelen++;
9486         flags |= EV_EXIT;
9487         INT_OFF;
9488         if (n->npipe.pipe_backgnd == 0)
9489                 get_tty_state();
9490         jp = makejob(/*n,*/ pipelen);
9491         prevfd = -1;
9492         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9493                 prehash(lp->n);
9494                 pip[1] = -1;
9495                 if (lp->next) {
9496                         if (pipe(pip) < 0) {
9497                                 close(prevfd);
9498                                 ash_msg_and_raise_perror("can't create pipe");
9499                         }
9500                 }
9501                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9502                         /* child */
9503                         INT_ON;
9504                         if (pip[1] >= 0) {
9505                                 close(pip[0]);
9506                         }
9507                         if (prevfd > 0) {
9508                                 dup2(prevfd, 0);
9509                                 close(prevfd);
9510                         }
9511                         if (pip[1] > 1) {
9512                                 dup2(pip[1], 1);
9513                                 close(pip[1]);
9514                         }
9515                         evaltreenr(lp->n, flags);
9516                         /* never returns */
9517                 }
9518                 /* parent */
9519                 if (prevfd >= 0)
9520                         close(prevfd);
9521                 prevfd = pip[0];
9522                 /* Don't want to trigger debugging */
9523                 if (pip[1] != -1)
9524                         close(pip[1]);
9525         }
9526         if (n->npipe.pipe_backgnd == 0) {
9527                 status = waitforjob(jp);
9528                 TRACE(("evalpipe:  job done exit status %d\n", status));
9529         }
9530         INT_ON;
9531
9532         return status;
9533 }
9534
9535 /* setinteractive needs this forward reference */
9536 #if EDITING_HAS_get_exe_name
9537 static const char *get_builtin_name(int i) FAST_FUNC;
9538 #endif
9539
9540 /*
9541  * Controls whether the shell is interactive or not.
9542  */
9543 static void
9544 setinteractive(int on)
9545 {
9546         static smallint is_interactive;
9547
9548         if (++on == is_interactive)
9549                 return;
9550         is_interactive = on;
9551         setsignal(SIGINT);
9552         setsignal(SIGQUIT);
9553         setsignal(SIGTERM);
9554         if (is_interactive > 1) {
9555 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9556                 /* Looks like they want an interactive shell */
9557                 static smallint did_banner;
9558
9559                 if (!did_banner) {
9560                         /* note: ash and hush share this string */
9561                         out1fmt("\n\n%s %s\n"
9562                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9563                                 "\n",
9564                                 bb_banner,
9565                                 "built-in shell (ash)"
9566                         );
9567                         did_banner = 1;
9568                 }
9569 #endif
9570 #if ENABLE_FEATURE_EDITING
9571                 if (!line_input_state) {
9572                         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
9573 # if EDITING_HAS_get_exe_name
9574                         line_input_state->get_exe_name = get_builtin_name;
9575 # endif
9576                 }
9577 #endif
9578         }
9579 }
9580
9581 static void
9582 optschanged(void)
9583 {
9584 #if DEBUG
9585         opentrace();
9586 #endif
9587         setinteractive(iflag);
9588         setjobctl(mflag);
9589 #if ENABLE_FEATURE_EDITING_VI
9590         if (line_input_state) {
9591                 if (viflag)
9592                         line_input_state->flags |= VI_MODE;
9593                 else
9594                         line_input_state->flags &= ~VI_MODE;
9595         }
9596 #else
9597         viflag = 0; /* forcibly keep the option off */
9598 #endif
9599 }
9600
9601 struct localvar_list {
9602         struct localvar_list *next;
9603         struct localvar *lv;
9604 };
9605
9606 static struct localvar_list *localvar_stack;
9607
9608 /*
9609  * Called after a function returns.
9610  * Interrupts must be off.
9611  */
9612 static void
9613 poplocalvars(int keep)
9614 {
9615         struct localvar_list *ll;
9616         struct localvar *lvp, *next;
9617         struct var *vp;
9618
9619         INT_OFF;
9620         ll = localvar_stack;
9621         localvar_stack = ll->next;
9622
9623         next = ll->lv;
9624         free(ll);
9625
9626         while ((lvp = next) != NULL) {
9627                 next = lvp->next;
9628                 vp = lvp->vp;
9629                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9630                 if (keep) {
9631                         int bits = VSTRFIXED;
9632
9633                         if (lvp->flags != VUNSET) {
9634                                 if (vp->var_text == lvp->text)
9635                                         bits |= VTEXTFIXED;
9636                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9637                                         free((char*)lvp->text);
9638                         }
9639
9640                         vp->flags &= ~bits;
9641                         vp->flags |= (lvp->flags & bits);
9642
9643                         if ((vp->flags &
9644                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9645                                 unsetvar(vp->var_text);
9646                 } else if (vp == NULL) {        /* $- saved */
9647                         memcpy(optlist, lvp->text, sizeof(optlist));
9648                         free((char*)lvp->text);
9649                         optschanged();
9650                 } else if (lvp->flags == VUNSET) {
9651                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9652                         unsetvar(vp->var_text);
9653                 } else {
9654                         if (vp->var_func)
9655                                 vp->var_func(var_end(lvp->text));
9656                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9657                                 free((char*)vp->var_text);
9658                         vp->flags = lvp->flags;
9659                         vp->var_text = lvp->text;
9660                 }
9661                 free(lvp);
9662         }
9663         INT_ON;
9664 }
9665
9666 /*
9667  * Create a new localvar environment.
9668  */
9669 static struct localvar_list *
9670 pushlocalvars(void)
9671 {
9672         struct localvar_list *ll;
9673
9674         INT_OFF;
9675         ll = ckzalloc(sizeof(*ll));
9676         /*ll->lv = NULL; - zalloc did it */
9677         ll->next = localvar_stack;
9678         localvar_stack = ll;
9679         INT_ON;
9680
9681         return ll->next;
9682 }
9683
9684 static void
9685 unwindlocalvars(struct localvar_list *stop)
9686 {
9687         while (localvar_stack != stop)
9688                 poplocalvars(0);
9689 }
9690
9691 static int
9692 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9693 {
9694         volatile struct shparam saveparam;
9695         struct jmploc *volatile savehandler;
9696         struct jmploc jmploc;
9697         int e;
9698         int savefuncline;
9699
9700         saveparam = shellparam;
9701         savefuncline = funcline;
9702         savehandler = exception_handler;
9703         e = setjmp(jmploc.loc);
9704         if (e) {
9705                 goto funcdone;
9706         }
9707         INT_OFF;
9708         exception_handler = &jmploc;
9709         shellparam.malloced = 0;
9710         func->count++;
9711         funcline = func->n.ndefun.linno;
9712         INT_ON;
9713         shellparam.nparam = argc - 1;
9714         shellparam.p = argv + 1;
9715 #if ENABLE_ASH_GETOPTS
9716         shellparam.optind = 1;
9717         shellparam.optoff = -1;
9718 #endif
9719         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9720  funcdone:
9721         INT_OFF;
9722         funcline = savefuncline;
9723         freefunc(func);
9724         freeparam(&shellparam);
9725         shellparam = saveparam;
9726         exception_handler = savehandler;
9727         INT_ON;
9728         evalskip &= ~SKIPFUNC;
9729         return e;
9730 }
9731
9732 /*
9733  * Make a variable a local variable.  When a variable is made local, it's
9734  * value and flags are saved in a localvar structure.  The saved values
9735  * will be restored when the shell function returns.  We handle the name
9736  * "-" as a special case: it makes changes to "set +-options" local
9737  * (options will be restored on return from the function).
9738  */
9739 static void
9740 mklocal(char *name)
9741 {
9742         struct localvar *lvp;
9743         struct var **vpp;
9744         struct var *vp;
9745         char *eq = strchr(name, '=');
9746
9747         INT_OFF;
9748         /* Cater for duplicate "local". Examples:
9749          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9750          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9751          */
9752         lvp = localvar_stack->lv;
9753         while (lvp) {
9754                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9755                         if (eq)
9756                                 setvareq(name, 0);
9757                         /* else:
9758                          * it's a duplicate "local VAR" declaration, do nothing
9759                          */
9760                         goto ret;
9761                 }
9762                 lvp = lvp->next;
9763         }
9764
9765         lvp = ckzalloc(sizeof(*lvp));
9766         if (LONE_DASH(name)) {
9767                 char *p;
9768                 p = ckmalloc(sizeof(optlist));
9769                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9770                 vp = NULL;
9771         } else {
9772                 vpp = hashvar(name);
9773                 vp = *findvar(vpp, name);
9774                 if (vp == NULL) {
9775                         /* variable did not exist yet */
9776                         if (eq)
9777                                 vp = setvareq(name, VSTRFIXED);
9778                         else
9779                                 vp = setvar(name, NULL, VSTRFIXED);
9780                         lvp->flags = VUNSET;
9781                 } else {
9782                         lvp->text = vp->var_text;
9783                         lvp->flags = vp->flags;
9784                         /* make sure neither "struct var" nor string gets freed
9785                          * during (un)setting:
9786                          */
9787                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9788                         if (eq)
9789                                 setvareq(name, 0);
9790                         else
9791                                 /* "local VAR" unsets VAR: */
9792                                 setvar0(name, NULL);
9793                 }
9794         }
9795         lvp->vp = vp;
9796         lvp->next = localvar_stack->lv;
9797         localvar_stack->lv = lvp;
9798  ret:
9799         INT_ON;
9800 }
9801
9802 /*
9803  * The "local" command.
9804  */
9805 static int FAST_FUNC
9806 localcmd(int argc UNUSED_PARAM, char **argv)
9807 {
9808         char *name;
9809
9810         if (!localvar_stack)
9811                 ash_msg_and_raise_error("not in a function");
9812
9813         argv = argptr;
9814         while ((name = *argv++) != NULL) {
9815                 mklocal(name);
9816         }
9817         return 0;
9818 }
9819
9820 static int FAST_FUNC
9821 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9822 {
9823         return 1;
9824 }
9825
9826 static int FAST_FUNC
9827 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9828 {
9829         return 0;
9830 }
9831
9832 static int FAST_FUNC
9833 execcmd(int argc UNUSED_PARAM, char **argv)
9834 {
9835         optionarg = NULL;
9836         while (nextopt("a:") != '\0')
9837                 /* nextopt() sets optionarg to "-a ARGV0" */;
9838
9839         argv = argptr;
9840         if (argv[0]) {
9841                 char *prog;
9842
9843                 iflag = 0;              /* exit on error */
9844                 mflag = 0;
9845                 optschanged();
9846                 /* We should set up signals for "exec CMD"
9847                  * the same way as for "CMD" without "exec".
9848                  * But optschanged->setinteractive->setsignal
9849                  * still thought we are a root shell. Therefore, for example,
9850                  * SIGQUIT is still set to IGN. Fix it:
9851                  */
9852                 shlvl++;
9853                 setsignal(SIGQUIT);
9854                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9855                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9856                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9857
9858                 prog = argv[0];
9859                 if (optionarg)
9860                         argv[0] = optionarg;
9861                 shellexec(prog, argv, pathval(), 0);
9862                 /* NOTREACHED */
9863         }
9864         return 0;
9865 }
9866
9867 /*
9868  * The return command.
9869  */
9870 static int FAST_FUNC
9871 returncmd(int argc UNUSED_PARAM, char **argv)
9872 {
9873         /*
9874          * If called outside a function, do what ksh does;
9875          * skip the rest of the file.
9876          */
9877         evalskip = SKIPFUNC;
9878         return argv[1] ? number(argv[1]) : exitstatus;
9879 }
9880
9881 /* Forward declarations for builtintab[] */
9882 static int breakcmd(int, char **) FAST_FUNC;
9883 static int dotcmd(int, char **) FAST_FUNC;
9884 static int evalcmd(int, char **, int) FAST_FUNC;
9885 static int exitcmd(int, char **) FAST_FUNC;
9886 static int exportcmd(int, char **) FAST_FUNC;
9887 #if ENABLE_ASH_GETOPTS
9888 static int getoptscmd(int, char **) FAST_FUNC;
9889 #endif
9890 #if ENABLE_ASH_HELP
9891 static int helpcmd(int, char **) FAST_FUNC;
9892 #endif
9893 #if MAX_HISTORY
9894 static int historycmd(int, char **) FAST_FUNC;
9895 #endif
9896 #if ENABLE_FEATURE_SH_MATH
9897 static int letcmd(int, char **) FAST_FUNC;
9898 #endif
9899 static int readcmd(int, char **) FAST_FUNC;
9900 static int setcmd(int, char **) FAST_FUNC;
9901 static int shiftcmd(int, char **) FAST_FUNC;
9902 static int timescmd(int, char **) FAST_FUNC;
9903 static int trapcmd(int, char **) FAST_FUNC;
9904 static int umaskcmd(int, char **) FAST_FUNC;
9905 static int unsetcmd(int, char **) FAST_FUNC;
9906 static int ulimitcmd(int, char **) FAST_FUNC;
9907
9908 #define BUILTIN_NOSPEC          "0"
9909 #define BUILTIN_SPECIAL         "1"
9910 #define BUILTIN_REGULAR         "2"
9911 #define BUILTIN_SPEC_REG        "3"
9912 #define BUILTIN_ASSIGN          "4"
9913 #define BUILTIN_SPEC_ASSG       "5"
9914 #define BUILTIN_REG_ASSG        "6"
9915 #define BUILTIN_SPEC_REG_ASSG   "7"
9916
9917 /* Stubs for calling non-FAST_FUNC's */
9918 #if ENABLE_ASH_ECHO
9919 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9920 #endif
9921 #if ENABLE_ASH_PRINTF
9922 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9923 #endif
9924 #if ENABLE_ASH_TEST || BASH_TEST2
9925 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9926 #endif
9927
9928 /* Keep these in proper order since it is searched via bsearch() */
9929 static const struct builtincmd builtintab[] = {
9930         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9931         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9932 #if ENABLE_ASH_TEST
9933         { BUILTIN_REGULAR       "["       , testcmd    },
9934 #endif
9935 #if BASH_TEST2
9936         { BUILTIN_REGULAR       "[["      , testcmd    },
9937 #endif
9938 #if ENABLE_ASH_ALIAS
9939         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9940 #endif
9941 #if JOBS
9942         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9943 #endif
9944         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9945         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9946         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9947 #if ENABLE_ASH_CMDCMD
9948         { BUILTIN_REGULAR       "command" , commandcmd },
9949 #endif
9950         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9951 #if ENABLE_ASH_ECHO
9952         { BUILTIN_REGULAR       "echo"    , echocmd    },
9953 #endif
9954         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9955         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9956         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9957         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9958         { BUILTIN_REGULAR       "false"   , falsecmd   },
9959 #if JOBS
9960         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9961 #endif
9962 #if ENABLE_ASH_GETOPTS
9963         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9964 #endif
9965         { BUILTIN_REGULAR       "hash"    , hashcmd    },
9966 #if ENABLE_ASH_HELP
9967         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9968 #endif
9969 #if MAX_HISTORY
9970         { BUILTIN_NOSPEC        "history" , historycmd },
9971 #endif
9972 #if JOBS
9973         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9974         { BUILTIN_REGULAR       "kill"    , killcmd    },
9975 #endif
9976 #if ENABLE_FEATURE_SH_MATH
9977         { BUILTIN_NOSPEC        "let"     , letcmd     },
9978 #endif
9979         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9980 #if ENABLE_ASH_PRINTF
9981         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9982 #endif
9983         { BUILTIN_REGULAR       "pwd"     , pwdcmd     },
9984         { BUILTIN_REGULAR       "read"    , readcmd    },
9985         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9986         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9987         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9988         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9989 #if BASH_SOURCE
9990         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9991 #endif
9992 #if ENABLE_ASH_TEST
9993         { BUILTIN_REGULAR       "test"    , testcmd    },
9994 #endif
9995         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9996         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9997         { BUILTIN_REGULAR       "true"    , truecmd    },
9998         { BUILTIN_REGULAR       "type"    , typecmd    },
9999         { BUILTIN_REGULAR       "ulimit"  , ulimitcmd  },
10000         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
10001 #if ENABLE_ASH_ALIAS
10002         { BUILTIN_REGULAR       "unalias" , unaliascmd },
10003 #endif
10004         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
10005         { BUILTIN_REGULAR       "wait"    , waitcmd    },
10006 };
10007
10008 /* Should match the above table! */
10009 #define COMMANDCMD (builtintab + \
10010         /* . : */       2 + \
10011         /* [ */         1 * ENABLE_ASH_TEST + \
10012         /* [[ */        1 * BASH_TEST2 + \
10013         /* alias */     1 * ENABLE_ASH_ALIAS + \
10014         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
10015         /* break cd cddir  */   3)
10016 #define EVALCMD (COMMANDCMD + \
10017         /* command */   1 * ENABLE_ASH_CMDCMD + \
10018         /* continue */  1 + \
10019         /* echo */      1 * ENABLE_ASH_ECHO + \
10020         0)
10021 #define EXECCMD (EVALCMD + \
10022         /* eval */      1)
10023
10024 /*
10025  * Search the table of builtin commands.
10026  */
10027 static int
10028 pstrcmp1(const void *a, const void *b)
10029 {
10030         return strcmp((char*)a, *(char**)b + 1);
10031 }
10032 static struct builtincmd *
10033 find_builtin(const char *name)
10034 {
10035         struct builtincmd *bp;
10036
10037         bp = bsearch(
10038                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
10039                 pstrcmp1
10040         );
10041         return bp;
10042 }
10043
10044 #if EDITING_HAS_get_exe_name
10045 static const char * FAST_FUNC
10046 get_builtin_name(int i)
10047 {
10048         return /*i >= 0 &&*/ i < ARRAY_SIZE(builtintab) ? builtintab[i].name + 1 : NULL;
10049 }
10050 #endif
10051
10052 /*
10053  * Execute a simple command.
10054  */
10055 static void unwindfiles(struct parsefile *stop);
10056 static int
10057 isassignment(const char *p)
10058 {
10059         const char *q = endofname(p);
10060         if (p == q)
10061                 return 0;
10062         return *q == '=';
10063 }
10064 static int FAST_FUNC
10065 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10066 {
10067         /* Preserve exitstatus of a previous possible redirection
10068          * as POSIX mandates */
10069         return back_exitstatus;
10070 }
10071 static int
10072 evalcommand(union node *cmd, int flags)
10073 {
10074         static const struct builtincmd null_bltin = {
10075                 "\0\0", bltincmd /* why three NULs? */
10076         };
10077         struct localvar_list *localvar_stop;
10078         struct parsefile *file_stop;
10079         struct redirtab *redir_stop;
10080         union node *argp;
10081         struct arglist arglist;
10082         struct arglist varlist;
10083         char **argv;
10084         int argc;
10085         const struct strlist *sp;
10086         struct cmdentry cmdentry;
10087         struct job *jp;
10088         char *lastarg;
10089         const char *path;
10090         int spclbltin;
10091         int status;
10092         char **nargv;
10093         smallint cmd_is_exec;
10094
10095         errlinno = lineno = cmd->ncmd.linno;
10096         if (funcline)
10097                 lineno -= funcline - 1;
10098
10099         /* First expand the arguments. */
10100         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
10101         localvar_stop = pushlocalvars();
10102         file_stop = g_parsefile;
10103         back_exitstatus = 0;
10104
10105         cmdentry.cmdtype = CMDBUILTIN;
10106         cmdentry.u.cmd = &null_bltin;
10107         varlist.lastp = &varlist.list;
10108         *varlist.lastp = NULL;
10109         arglist.lastp = &arglist.list;
10110         *arglist.lastp = NULL;
10111
10112         argc = 0;
10113         if (cmd->ncmd.args) {
10114                 struct builtincmd *bcmd;
10115                 smallint pseudovarflag;
10116
10117                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
10118                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
10119
10120                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
10121                         struct strlist **spp;
10122
10123                         spp = arglist.lastp;
10124                         if (pseudovarflag && isassignment(argp->narg.text))
10125                                 expandarg(argp, &arglist, EXP_VARTILDE);
10126                         else
10127                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
10128
10129                         for (sp = *spp; sp; sp = sp->next)
10130                                 argc++;
10131                 }
10132         }
10133
10134         /* Reserve one extra spot at the front for shellexec. */
10135         nargv = stalloc(sizeof(char *) * (argc + 2));
10136         argv = ++nargv;
10137         for (sp = arglist.list; sp; sp = sp->next) {
10138                 TRACE(("evalcommand arg: %s\n", sp->text));
10139                 *nargv++ = sp->text;
10140         }
10141         *nargv = NULL;
10142
10143         lastarg = NULL;
10144         if (iflag && funcline == 0 && argc > 0)
10145                 lastarg = nargv[-1];
10146
10147         expredir(cmd->ncmd.redirect);
10148         redir_stop = pushredir(cmd->ncmd.redirect);
10149         preverrout_fd = 2;
10150         if (BASH_XTRACEFD && xflag) {
10151                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10152                  * we do not emulate this. We only use its value.
10153                  */
10154                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
10155                 if (xtracefd && is_number(xtracefd))
10156                         preverrout_fd = atoi(xtracefd);
10157
10158         }
10159         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10160
10161         path = vpath.var_text;
10162         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10163                 struct strlist **spp;
10164                 char *p;
10165
10166                 spp = varlist.lastp;
10167                 expandarg(argp, &varlist, EXP_VARTILDE);
10168
10169                 mklocal((*spp)->text);
10170
10171                 /*
10172                  * Modify the command lookup path, if a PATH= assignment
10173                  * is present
10174                  */
10175                 p = (*spp)->text;
10176                 if (varcmp(p, path) == 0)
10177                         path = p;
10178         }
10179
10180         /* Print the command if xflag is set. */
10181         if (xflag) {
10182                 const char *pfx = "";
10183
10184                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10185
10186                 sp = varlist.list;
10187                 while (sp) {
10188                         char *varval = sp->text;
10189                         char *eq = strchrnul(varval, '=');
10190                         if (*eq)
10191                                 eq++;
10192                         fdprintf(preverrout_fd, "%s%.*s%s",
10193                                 pfx,
10194                                 (int)(eq - varval), varval,
10195                                 maybe_single_quote(eq)
10196                         );
10197                         sp = sp->next;
10198                         pfx = " ";
10199                 }
10200
10201                 sp = arglist.list;
10202                 while (sp) {
10203                         fdprintf(preverrout_fd, "%s%s",
10204                                 pfx,
10205                                 /* always quote if matches reserved word: */
10206                                 findkwd(sp->text)
10207                                 ? single_quote(sp->text)
10208                                 : maybe_single_quote(sp->text)
10209                         );
10210                         sp = sp->next;
10211                         pfx = " ";
10212                 }
10213                 safe_write(preverrout_fd, "\n", 1);
10214         }
10215
10216         cmd_is_exec = 0;
10217         spclbltin = -1;
10218
10219         /* Now locate the command. */
10220         if (argc) {
10221                 int cmd_flag = DO_ERR;
10222 #if ENABLE_ASH_CMDCMD
10223                 const char *oldpath = path + 5;
10224 #endif
10225                 path += 5;
10226                 for (;;) {
10227                         find_command(argv[0], &cmdentry, cmd_flag, path);
10228                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10229                                 flush_stdout_stderr();
10230                                 status = 127;
10231                                 goto bail;
10232                         }
10233
10234                         /* implement bltin and command here */
10235                         if (cmdentry.cmdtype != CMDBUILTIN)
10236                                 break;
10237                         if (spclbltin < 0)
10238                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10239                         if (cmdentry.u.cmd == EXECCMD)
10240                                 cmd_is_exec = 1;
10241 #if ENABLE_ASH_CMDCMD
10242                         if (cmdentry.u.cmd == COMMANDCMD) {
10243                                 path = oldpath;
10244                                 nargv = parse_command_args(argv, &path);
10245                                 if (!nargv)
10246                                         break;
10247                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10248                                  * nargv => "PROG". path is updated if -p.
10249                                  */
10250                                 argc -= nargv - argv;
10251                                 argv = nargv;
10252                                 cmd_flag |= DO_NOFUNC;
10253                         } else
10254 #endif
10255                                 break;
10256                 }
10257         }
10258
10259         if (status) {
10260  bail:
10261                 exitstatus = status;
10262
10263                 /* We have a redirection error. */
10264                 if (spclbltin > 0)
10265                         raise_exception(EXERROR);
10266
10267                 goto out;
10268         }
10269
10270         /* Execute the command. */
10271         switch (cmdentry.cmdtype) {
10272         default: {
10273
10274 #if ENABLE_FEATURE_SH_STANDALONE \
10275  && ENABLE_FEATURE_SH_NOFORK \
10276  && NUM_APPLETS > 1
10277 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10278  *     around run_nofork_applet() call.
10279  * (2) Should this check also be done in forkshell()?
10280  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10281  */
10282                 /* find_command() encodes applet_no as (-2 - applet_no) */
10283                 int applet_no = (- cmdentry.u.index - 2);
10284                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10285                         char **sv_environ;
10286
10287                         INT_OFF;
10288                         sv_environ = environ;
10289                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10290                         /*
10291                          * Run <applet>_main().
10292                          * Signals (^C) can't interrupt here.
10293                          * Otherwise we can mangle stdio or malloc internal state.
10294                          * This makes applets which can run for a long time
10295                          * and/or wait for user input ineligible for NOFORK:
10296                          * for example, "yes" or "rm" (rm -i waits for input).
10297                          */
10298                         status = run_nofork_applet(applet_no, argv);
10299                         environ = sv_environ;
10300                         /*
10301                          * Try enabling NOFORK for "yes" applet.
10302                          * ^C _will_ stop it (write returns EINTR),
10303                          * but this causes stdout FILE to be stuck
10304                          * and needing clearerr(). What if other applets
10305                          * also can get EINTRs? Do we need to switch
10306                          * our signals to SA_RESTART?
10307                          */
10308                         /*clearerr(stdout);*/
10309                         INT_ON;
10310                         break;
10311                 }
10312 #endif
10313                 /* Can we avoid forking? For example, very last command
10314                  * in a script or a subshell does not need forking,
10315                  * we can just exec it.
10316                  */
10317                 if (!(flags & EV_EXIT) || may_have_traps) {
10318                         /* No, forking off a child is necessary */
10319                         INT_OFF;
10320                         get_tty_state();
10321                         jp = makejob(/*cmd,*/ 1);
10322                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10323                                 /* parent */
10324                                 status = waitforjob(jp);
10325                                 INT_ON;
10326                                 TRACE(("forked child exited with %d\n", status));
10327                                 break;
10328                         }
10329                         /* child */
10330                         FORCE_INT_ON;
10331                         /* fall through to exec'ing external program */
10332                 }
10333                 listsetvar(varlist.list, VEXPORT|VSTACK);
10334                 shellexec(argv[0], argv, path, cmdentry.u.index);
10335                 /* NOTREACHED */
10336         } /* default */
10337         case CMDBUILTIN:
10338                 if (spclbltin > 0 || argc == 0) {
10339                         poplocalvars(1);
10340                         if (cmd_is_exec && argc > 1)
10341                                 listsetvar(varlist.list, VEXPORT);
10342                 }
10343
10344                 /* Tight loop with builtins only:
10345                  * "while kill -0 $child; do true; done"
10346                  * will never exit even if $child died, unless we do this
10347                  * to reap the zombie and make kill detect that it's gone: */
10348                 dowait(DOWAIT_NONBLOCK, NULL);
10349
10350                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10351                         if (exception_type == EXERROR && spclbltin <= 0) {
10352                                 FORCE_INT_ON;
10353                                 goto readstatus;
10354                         }
10355  raise:
10356                         longjmp(exception_handler->loc, 1);
10357                 }
10358                 goto readstatus;
10359
10360         case CMDFUNCTION:
10361                 /* See above for the rationale */
10362                 dowait(DOWAIT_NONBLOCK, NULL);
10363                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10364                         goto raise;
10365  readstatus:
10366                 status = exitstatus;
10367                 break;
10368         } /* switch */
10369
10370  out:
10371         if (cmd->ncmd.redirect)
10372                 popredir(/*drop:*/ cmd_is_exec);
10373         unwindredir(redir_stop);
10374         unwindfiles(file_stop);
10375         unwindlocalvars(localvar_stop);
10376         if (lastarg) {
10377                 /* dsl: I think this is intended to be used to support
10378                  * '_' in 'vi' command mode during line editing...
10379                  * However I implemented that within libedit itself.
10380                  */
10381                 setvar0("_", lastarg);
10382         }
10383
10384         return status;
10385 }
10386
10387 static int
10388 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10389 {
10390         char *volatile savecmdname;
10391         struct jmploc *volatile savehandler;
10392         struct jmploc jmploc;
10393         int status;
10394         int i;
10395
10396         savecmdname = commandname;
10397         savehandler = exception_handler;
10398         i = setjmp(jmploc.loc);
10399         if (i)
10400                 goto cmddone;
10401         exception_handler = &jmploc;
10402         commandname = argv[0];
10403         argptr = argv + 1;
10404         optptr = NULL;                  /* initialize nextopt */
10405         if (cmd == EVALCMD)
10406                 status = evalcmd(argc, argv, flags);
10407         else
10408                 status = (*cmd->builtin)(argc, argv);
10409         flush_stdout_stderr();
10410         status |= ferror(stdout);
10411         exitstatus = status;
10412  cmddone:
10413         clearerr(stdout);
10414         commandname = savecmdname;
10415         exception_handler = savehandler;
10416
10417         return i;
10418 }
10419
10420 static int
10421 goodname(const char *p)
10422 {
10423         return endofname(p)[0] == '\0';
10424 }
10425
10426
10427 /*
10428  * Search for a command.  This is called before we fork so that the
10429  * location of the command will be available in the parent as well as
10430  * the child.  The check for "goodname" is an overly conservative
10431  * check that the name will not be subject to expansion.
10432  */
10433 static void
10434 prehash(union node *n)
10435 {
10436         struct cmdentry entry;
10437
10438         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10439                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10440 }
10441
10442
10443 /* ============ Builtin commands
10444  *
10445  * Builtin commands whose functions are closely tied to evaluation
10446  * are implemented here.
10447  */
10448
10449 /*
10450  * Handle break and continue commands.  Break, continue, and return are
10451  * all handled by setting the evalskip flag.  The evaluation routines
10452  * above all check this flag, and if it is set they start skipping
10453  * commands rather than executing them.  The variable skipcount is
10454  * the number of loops to break/continue, or the number of function
10455  * levels to return.  (The latter is always 1.)  It should probably
10456  * be an error to break out of more loops than exist, but it isn't
10457  * in the standard shell so we don't make it one here.
10458  */
10459 static int FAST_FUNC
10460 breakcmd(int argc UNUSED_PARAM, char **argv)
10461 {
10462         int n = argv[1] ? number(argv[1]) : 1;
10463
10464         if (n <= 0)
10465                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10466         if (n > loopnest)
10467                 n = loopnest;
10468         if (n > 0) {
10469                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10470                 skipcount = n;
10471         }
10472         return 0;
10473 }
10474
10475
10476 /*
10477  * This implements the input routines used by the parser.
10478  */
10479
10480 enum {
10481         INPUT_PUSH_FILE = 1,
10482         INPUT_NOFILE_OK = 2,
10483 };
10484
10485 static smallint checkkwd;
10486 /* values of checkkwd variable */
10487 #define CHKALIAS        0x1
10488 #define CHKKWD          0x2
10489 #define CHKNL           0x4
10490 #define CHKEOFMARK      0x8
10491
10492 /*
10493  * Push a string back onto the input at this current parsefile level.
10494  * We handle aliases this way.
10495  */
10496 #if !ENABLE_ASH_ALIAS
10497 #define pushstring(s, ap) pushstring(s)
10498 #endif
10499 static void
10500 pushstring(char *s, struct alias *ap)
10501 {
10502         struct strpush *sp;
10503         int len;
10504
10505         len = strlen(s);
10506         INT_OFF;
10507         if (g_parsefile->strpush) {
10508                 sp = ckzalloc(sizeof(*sp));
10509                 sp->prev = g_parsefile->strpush;
10510         } else {
10511                 sp = &(g_parsefile->basestrpush);
10512         }
10513         g_parsefile->strpush = sp;
10514         sp->prev_string = g_parsefile->next_to_pgetc;
10515         sp->prev_left_in_line = g_parsefile->left_in_line;
10516         sp->unget = g_parsefile->unget;
10517         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10518 #if ENABLE_ASH_ALIAS
10519         sp->ap = ap;
10520         if (ap) {
10521                 ap->flag |= ALIASINUSE;
10522                 sp->string = s;
10523         }
10524 #endif
10525         g_parsefile->next_to_pgetc = s;
10526         g_parsefile->left_in_line = len;
10527         g_parsefile->unget = 0;
10528         INT_ON;
10529 }
10530
10531 static void
10532 popstring(void)
10533 {
10534         struct strpush *sp = g_parsefile->strpush;
10535
10536         INT_OFF;
10537 #if ENABLE_ASH_ALIAS
10538         if (sp->ap) {
10539                 if (g_parsefile->next_to_pgetc[-1] == ' '
10540                  || g_parsefile->next_to_pgetc[-1] == '\t'
10541                 ) {
10542                         checkkwd |= CHKALIAS;
10543                 }
10544                 if (sp->string != sp->ap->val) {
10545                         free(sp->string);
10546                 }
10547                 sp->ap->flag &= ~ALIASINUSE;
10548                 if (sp->ap->flag & ALIASDEAD) {
10549                         unalias(sp->ap->name);
10550                 }
10551         }
10552 #endif
10553         g_parsefile->next_to_pgetc = sp->prev_string;
10554         g_parsefile->left_in_line = sp->prev_left_in_line;
10555         g_parsefile->unget = sp->unget;
10556         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10557         g_parsefile->strpush = sp->prev;
10558         if (sp != &(g_parsefile->basestrpush))
10559                 free(sp);
10560         INT_ON;
10561 }
10562
10563 static int
10564 preadfd(void)
10565 {
10566         int nr;
10567         char *buf = g_parsefile->buf;
10568
10569         g_parsefile->next_to_pgetc = buf;
10570 #if ENABLE_FEATURE_EDITING
10571  retry:
10572         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10573                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10574         else {
10575 # if ENABLE_ASH_IDLE_TIMEOUT
10576                 int timeout = -1;
10577                 const char *tmout_var = lookupvar("TMOUT");
10578                 if (tmout_var) {
10579                         timeout = atoi(tmout_var) * 1000;
10580                         if (timeout <= 0)
10581                                 timeout = -1;
10582                 }
10583                 line_input_state->timeout = timeout;
10584 # endif
10585 # if ENABLE_FEATURE_TAB_COMPLETION
10586                 line_input_state->path_lookup = pathval();
10587 # endif
10588                 reinit_unicode_for_ash();
10589                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10590                 if (nr == 0) {
10591                         /* ^C pressed, "convert" to SIGINT */
10592                         write(STDOUT_FILENO, "^C", 2);
10593                         if (trap[SIGINT]) {
10594                                 buf[0] = '\n';
10595                                 buf[1] = '\0';
10596                                 raise(SIGINT);
10597                                 return 1;
10598                         }
10599                         exitstatus = 128 + SIGINT;
10600                         bb_putchar('\n');
10601                         goto retry;
10602                 }
10603                 if (nr < 0) {
10604                         if (errno == 0) {
10605                                 /* Ctrl+D pressed */
10606                                 nr = 0;
10607                         }
10608 # if ENABLE_ASH_IDLE_TIMEOUT
10609                         else if (errno == EAGAIN && timeout > 0) {
10610                                 puts("\007timed out waiting for input: auto-logout");
10611                                 exitshell();
10612                         }
10613 # endif
10614                 }
10615         }
10616 #else
10617         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10618 #endif
10619
10620 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10621         if (nr < 0) {
10622                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10623                         int flags = fcntl(0, F_GETFL);
10624                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10625                                 flags &= ~O_NONBLOCK;
10626                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10627                                         out2str("sh: turning off NDELAY mode\n");
10628                                         goto retry;
10629                                 }
10630                         }
10631                 }
10632         }
10633 #endif
10634         return nr;
10635 }
10636
10637 /*
10638  * Refill the input buffer and return the next input character:
10639  *
10640  * 1) If a string was pushed back on the input, pop it;
10641  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10642  *    or we are reading from a string so we can't refill the buffer,
10643  *    return EOF.
10644  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10645  * 4) Process input up to the next newline, deleting nul characters.
10646  */
10647 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10648 #define pgetc_debug(...) ((void)0)
10649 static int pgetc(void);
10650 static int
10651 preadbuffer(void)
10652 {
10653         char *q;
10654         int more;
10655
10656         if (g_parsefile->strpush) {
10657 #if ENABLE_ASH_ALIAS
10658                 if (g_parsefile->left_in_line == -1
10659                  && g_parsefile->strpush->ap
10660                  && g_parsefile->next_to_pgetc[-1] != ' '
10661                  && g_parsefile->next_to_pgetc[-1] != '\t'
10662                 ) {
10663                         pgetc_debug("preadbuffer PEOA");
10664                         return PEOA;
10665                 }
10666 #endif
10667                 popstring();
10668                 return pgetc();
10669         }
10670         /* on both branches above g_parsefile->left_in_line < 0.
10671          * "pgetc" needs refilling.
10672          */
10673
10674         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10675          * pungetc() may increment it a few times.
10676          * Assuming it won't increment it to less than -90.
10677          */
10678         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10679                 pgetc_debug("preadbuffer PEOF1");
10680                 /* even in failure keep left_in_line and next_to_pgetc
10681                  * in lock step, for correct multi-layer pungetc.
10682                  * left_in_line was decremented before preadbuffer(),
10683                  * must inc next_to_pgetc: */
10684                 g_parsefile->next_to_pgetc++;
10685                 return PEOF;
10686         }
10687
10688         more = g_parsefile->left_in_buffer;
10689         if (more <= 0) {
10690                 flush_stdout_stderr();
10691  again:
10692                 more = preadfd();
10693                 if (more <= 0) {
10694                         /* don't try reading again */
10695                         g_parsefile->left_in_line = -99;
10696                         pgetc_debug("preadbuffer PEOF2");
10697                         g_parsefile->next_to_pgetc++;
10698                         return PEOF;
10699                 }
10700         }
10701
10702         /* Find out where's the end of line.
10703          * Set g_parsefile->left_in_line
10704          * and g_parsefile->left_in_buffer acordingly.
10705          * NUL chars are deleted.
10706          */
10707         q = g_parsefile->next_to_pgetc;
10708         for (;;) {
10709                 char c;
10710
10711                 more--;
10712
10713                 c = *q;
10714                 if (c == '\0') {
10715                         memmove(q, q + 1, more);
10716                 } else {
10717                         q++;
10718                         if (c == '\n') {
10719                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10720                                 break;
10721                         }
10722                 }
10723
10724                 if (more <= 0) {
10725                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10726                         if (g_parsefile->left_in_line < 0)
10727                                 goto again;
10728                         break;
10729                 }
10730         }
10731         g_parsefile->left_in_buffer = more;
10732
10733         if (vflag) {
10734                 char save = *q;
10735                 *q = '\0';
10736                 out2str(g_parsefile->next_to_pgetc);
10737                 *q = save;
10738         }
10739
10740         pgetc_debug("preadbuffer at %d:%p'%s'",
10741                         g_parsefile->left_in_line,
10742                         g_parsefile->next_to_pgetc,
10743                         g_parsefile->next_to_pgetc);
10744         return (unsigned char)*g_parsefile->next_to_pgetc++;
10745 }
10746
10747 static void
10748 nlprompt(void)
10749 {
10750         g_parsefile->linno++;
10751         setprompt_if(doprompt, 2);
10752 }
10753 static void
10754 nlnoprompt(void)
10755 {
10756         g_parsefile->linno++;
10757         needprompt = doprompt;
10758 }
10759
10760 static int
10761 pgetc(void)
10762 {
10763         int c;
10764
10765         pgetc_debug("pgetc at %d:%p'%s'",
10766                         g_parsefile->left_in_line,
10767                         g_parsefile->next_to_pgetc,
10768                         g_parsefile->next_to_pgetc);
10769         if (g_parsefile->unget)
10770                 return g_parsefile->lastc[--g_parsefile->unget];
10771
10772         if (--g_parsefile->left_in_line >= 0)
10773                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10774         else
10775                 c = preadbuffer();
10776
10777         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10778         g_parsefile->lastc[0] = c;
10779
10780         return c;
10781 }
10782
10783 #if ENABLE_ASH_ALIAS
10784 static int
10785 pgetc_without_PEOA(void)
10786 {
10787         int c;
10788         do {
10789                 pgetc_debug("pgetc at %d:%p'%s'",
10790                                 g_parsefile->left_in_line,
10791                                 g_parsefile->next_to_pgetc,
10792                                 g_parsefile->next_to_pgetc);
10793                 c = pgetc();
10794         } while (c == PEOA);
10795         return c;
10796 }
10797 #else
10798 # define pgetc_without_PEOA() pgetc()
10799 #endif
10800
10801 /*
10802  * Undo a call to pgetc.  Only two characters may be pushed back.
10803  * PEOF may be pushed back.
10804  */
10805 static void
10806 pungetc(void)
10807 {
10808         g_parsefile->unget++;
10809 }
10810
10811 /* This one eats backslash+newline */
10812 static int
10813 pgetc_eatbnl(void)
10814 {
10815         int c;
10816
10817         while ((c = pgetc()) == '\\') {
10818                 if (pgetc() != '\n') {
10819                         pungetc();
10820                         break;
10821                 }
10822
10823                 nlprompt();
10824         }
10825
10826         return c;
10827 }
10828
10829 struct synstack {
10830         smalluint syntax;
10831         uint8_t innerdq   :1;
10832         uint8_t varpushed :1;
10833         uint8_t dblquote  :1;
10834         int varnest;            /* levels of variables expansion */
10835         int dqvarnest;          /* levels of variables expansion within double quotes */
10836         int parenlevel;         /* levels of parens in arithmetic */
10837         struct synstack *prev;
10838         struct synstack *next;
10839 };
10840
10841 static int
10842 pgetc_top(struct synstack *stack)
10843 {
10844         return stack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
10845 }
10846
10847 static void
10848 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10849 {
10850         memset(next, 0, sizeof(*next));
10851         next->syntax = syntax;
10852         next->next = *stack;
10853         (*stack)->prev = next;
10854         *stack = next;
10855 }
10856
10857 static ALWAYS_INLINE void
10858 synstack_pop(struct synstack **stack)
10859 {
10860         *stack = (*stack)->next;
10861 }
10862
10863 /*
10864  * To handle the "." command, a stack of input files is used.  Pushfile
10865  * adds a new entry to the stack and popfile restores the previous level.
10866  */
10867 static void
10868 pushfile(void)
10869 {
10870         struct parsefile *pf;
10871
10872         pf = ckzalloc(sizeof(*pf));
10873         pf->prev = g_parsefile;
10874         pf->pf_fd = -1;
10875         /*pf->strpush = NULL; - ckzalloc did it */
10876         /*pf->basestrpush.prev = NULL;*/
10877         /*pf->unget = 0;*/
10878         g_parsefile = pf;
10879 }
10880
10881 static void
10882 popfile(void)
10883 {
10884         struct parsefile *pf = g_parsefile;
10885
10886         if (pf == &basepf)
10887                 return;
10888
10889         INT_OFF;
10890         if (pf->pf_fd >= 0)
10891                 close(pf->pf_fd);
10892         free(pf->buf);
10893         while (pf->strpush)
10894                 popstring();
10895         g_parsefile = pf->prev;
10896         free(pf);
10897         INT_ON;
10898 }
10899
10900 static void
10901 unwindfiles(struct parsefile *stop)
10902 {
10903         while (g_parsefile != stop)
10904                 popfile();
10905 }
10906
10907 /*
10908  * Return to top level.
10909  */
10910 static void
10911 popallfiles(void)
10912 {
10913         unwindfiles(&basepf);
10914 }
10915
10916 /*
10917  * Close the file(s) that the shell is reading commands from.  Called
10918  * after a fork is done.
10919  */
10920 static void
10921 closescript(void)
10922 {
10923         popallfiles();
10924         if (g_parsefile->pf_fd > 0) {
10925                 close(g_parsefile->pf_fd);
10926                 g_parsefile->pf_fd = 0;
10927         }
10928 }
10929
10930 /*
10931  * Like setinputfile, but takes an open file descriptor.  Call this with
10932  * interrupts off.
10933  */
10934 static void
10935 setinputfd(int fd, int push)
10936 {
10937         if (push) {
10938                 pushfile();
10939                 g_parsefile->buf = NULL;
10940         }
10941         g_parsefile->pf_fd = fd;
10942         if (g_parsefile->buf == NULL)
10943                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10944         g_parsefile->left_in_buffer = 0;
10945         g_parsefile->left_in_line = 0;
10946         g_parsefile->linno = 1;
10947 }
10948
10949 /*
10950  * Set the input to take input from a file.  If push is set, push the
10951  * old input onto the stack first.
10952  */
10953 static int
10954 setinputfile(const char *fname, int flags)
10955 {
10956         int fd;
10957
10958         INT_OFF;
10959         fd = open(fname, O_RDONLY | O_CLOEXEC);
10960         if (fd < 0) {
10961                 if (flags & INPUT_NOFILE_OK)
10962                         goto out;
10963                 exitstatus = 127;
10964                 ash_msg_and_raise_perror("can't open '%s'", fname);
10965         }
10966         if (fd < 10)
10967                 fd = savefd(fd);
10968         else if (O_CLOEXEC == 0) /* old libc */
10969                 close_on_exec_on(fd);
10970
10971         setinputfd(fd, flags & INPUT_PUSH_FILE);
10972  out:
10973         INT_ON;
10974         return fd;
10975 }
10976
10977 /*
10978  * Like setinputfile, but takes input from a string.
10979  */
10980 static void
10981 setinputstring(char *string)
10982 {
10983         INT_OFF;
10984         pushfile();
10985         g_parsefile->next_to_pgetc = string;
10986         g_parsefile->left_in_line = strlen(string);
10987         g_parsefile->buf = NULL;
10988         g_parsefile->linno = 1;
10989         INT_ON;
10990 }
10991
10992
10993 /*
10994  * Routines to check for mail.
10995  */
10996
10997 #if ENABLE_ASH_MAIL
10998
10999 /* Hash of mtimes of mailboxes */
11000 static unsigned mailtime_hash;
11001 /* Set if MAIL or MAILPATH is changed. */
11002 static smallint mail_var_path_changed;
11003
11004 /*
11005  * Print appropriate message(s) if mail has arrived.
11006  * If mail_var_path_changed is set,
11007  * then the value of MAIL has mail_var_path_changed,
11008  * so we just update the values.
11009  */
11010 static void
11011 chkmail(void)
11012 {
11013         const char *mpath;
11014         char *p;
11015         char *q;
11016         unsigned new_hash;
11017         struct stackmark smark;
11018         struct stat statb;
11019
11020         setstackmark(&smark);
11021         mpath = mpathset() ? mpathval() : mailval();
11022         new_hash = 0;
11023         for (;;) {
11024                 p = path_advance(&mpath, nullstr);
11025                 if (p == NULL)
11026                         break;
11027                 if (*p == '\0')
11028                         continue;
11029                 for (q = p; *q; q++)
11030                         continue;
11031 #if DEBUG
11032                 if (q[-1] != '/')
11033                         abort();
11034 #endif
11035                 q[-1] = '\0';                   /* delete trailing '/' */
11036                 if (stat(p, &statb) < 0) {
11037                         continue;
11038                 }
11039                 /* Very simplistic "hash": just a sum of all mtimes */
11040                 new_hash += (unsigned)statb.st_mtime;
11041         }
11042         if (!mail_var_path_changed && mailtime_hash != new_hash) {
11043                 if (mailtime_hash != 0)
11044                         out2str("you have mail\n");
11045                 mailtime_hash = new_hash;
11046         }
11047         mail_var_path_changed = 0;
11048         popstackmark(&smark);
11049 }
11050
11051 static void FAST_FUNC
11052 changemail(const char *val UNUSED_PARAM)
11053 {
11054         mail_var_path_changed = 1;
11055 }
11056
11057 #endif /* ASH_MAIL */
11058
11059
11060 /* ============ ??? */
11061
11062 /*
11063  * Set the shell parameters.
11064  */
11065 static void
11066 setparam(char **argv)
11067 {
11068         char **newparam;
11069         char **ap;
11070         int nparam;
11071
11072         for (nparam = 0; argv[nparam]; nparam++)
11073                 continue;
11074         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
11075         while (*argv) {
11076                 *ap++ = ckstrdup(*argv++);
11077         }
11078         *ap = NULL;
11079         freeparam(&shellparam);
11080         shellparam.malloced = 1;
11081         shellparam.nparam = nparam;
11082         shellparam.p = newparam;
11083 #if ENABLE_ASH_GETOPTS
11084         shellparam.optind = 1;
11085         shellparam.optoff = -1;
11086 #endif
11087 }
11088
11089 /*
11090  * Process shell options.  The global variable argptr contains a pointer
11091  * to the argument list; we advance it past the options.
11092  *
11093  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
11094  * For a non-interactive shell, an error condition encountered
11095  * by a special built-in ... shall cause the shell to write a diagnostic message
11096  * to standard error and exit as shown in the following table:
11097  * Error                                           Special Built-In
11098  * ...
11099  * Utility syntax error (option or operand error)  Shall exit
11100  * ...
11101  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
11102  * we see that bash does not do that (set "finishes" with error code 1 instead,
11103  * and shell continues), and people rely on this behavior!
11104  * Testcase:
11105  * set -o barfoo 2>/dev/null
11106  * echo $?
11107  *
11108  * Oh well. Let's mimic that.
11109  */
11110 static int
11111 plus_minus_o(char *name, int val)
11112 {
11113         int i;
11114
11115         if (name) {
11116                 for (i = 0; i < NOPTS; i++) {
11117                         if (strcmp(name, optnames(i)) == 0) {
11118                                 optlist[i] = val;
11119                                 return 0;
11120                         }
11121                 }
11122                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
11123                 return 1;
11124         }
11125         for (i = 0; i < NOPTS; i++) {
11126                 if (optnames(i)[0] == '\0')
11127                         continue;
11128                 if (val) {
11129                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
11130                 } else {
11131                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
11132                 }
11133         }
11134         return 0;
11135 }
11136 static void
11137 setoption(int flag, int val)
11138 {
11139         int i;
11140
11141         for (i = 0; i < NOPTS; i++) {
11142                 if (optletters(i) == flag && optnames(i)[0] != '\0') {
11143                         optlist[i] = val;
11144                         return;
11145                 }
11146         }
11147         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
11148         /* NOTREACHED */
11149 }
11150 /* If login_sh is not NULL, we are called to parse command line opts,
11151  * not "set -opts"
11152  */
11153 static int
11154 options(int *login_sh)
11155 {
11156         char *p;
11157         int val;
11158         int c;
11159
11160         if (login_sh)
11161                 minusc = NULL;
11162         while ((p = *argptr) != NULL) {
11163                 c = *p++;
11164                 if (c != '-' && c != '+')
11165                         break;
11166                 argptr++;
11167                 val = 0; /* val = 0 if c == '+' */
11168                 if (c == '-') {
11169                         val = 1;
11170                         if (p[0] == '\0' || LONE_DASH(p)) {
11171                                 if (!login_sh) {
11172                                         /* "-" means turn off -x and -v */
11173                                         if (p[0] == '\0')
11174                                                 xflag = vflag = 0;
11175                                         /* "--" means reset params */
11176                                         else if (*argptr == NULL)
11177                                                 setparam(argptr);
11178                                 }
11179                                 break;    /* "-" or "--" terminates options */
11180                         }
11181                 }
11182                 /* first char was + or - */
11183                 while ((c = *p++) != '\0') {
11184                         if (login_sh) {
11185                                 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11186                                 if (c == 'c') {
11187                                         minusc = p; /* command is after shell args */
11188                                         cflag = 1;
11189                                         continue;
11190                                 }
11191                                 if (c == 's') { /* -s, +s */
11192                                         sflag = 1;
11193                                         continue;
11194                                 }
11195                                 if (c == 'i') { /* -i, +i */
11196                                         iflag = 1;
11197                                         continue;
11198                                 }
11199                                 if (c == 'l') {
11200                                         *login_sh = 1; /* -l or +l == --login */
11201                                         continue;
11202                                 }
11203                                 /* bash does not accept +-login, we also won't */
11204                                 if (val && (c == '-')) { /* long options */
11205                                         if (strcmp(p, "login") == 0) {
11206                                                 *login_sh = 1;
11207                                         }
11208                                         break;
11209                                 }
11210                         }
11211                         if (c == 'o') {
11212                                 if (plus_minus_o(*argptr, val)) {
11213                                         /* it already printed err message */
11214                                         return 1; /* error */
11215                                 }
11216                                 if (*argptr)
11217                                         argptr++;
11218                         } else {
11219                                 setoption(c, val);
11220                         }
11221                 }
11222         }
11223         return 0;
11224 }
11225
11226 /*
11227  * The shift builtin command.
11228  */
11229 static int FAST_FUNC
11230 shiftcmd(int argc UNUSED_PARAM, char **argv)
11231 {
11232         int n;
11233         char **ap1, **ap2;
11234
11235         n = 1;
11236         if (argv[1])
11237                 n = number(argv[1]);
11238         if (n > shellparam.nparam)
11239                 return 1;
11240         INT_OFF;
11241         shellparam.nparam -= n;
11242         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11243                 if (shellparam.malloced)
11244                         free(*ap1);
11245         }
11246         ap2 = shellparam.p;
11247         while ((*ap2++ = *ap1++) != NULL)
11248                 continue;
11249 #if ENABLE_ASH_GETOPTS
11250         shellparam.optind = 1;
11251         shellparam.optoff = -1;
11252 #endif
11253         INT_ON;
11254         return 0;
11255 }
11256
11257 /*
11258  * POSIX requires that 'set' (but not export or readonly) output the
11259  * variables in lexicographic order - by the locale's collating order (sigh).
11260  * Maybe we could keep them in an ordered balanced binary tree
11261  * instead of hashed lists.
11262  * For now just roll 'em through qsort for printing...
11263  */
11264 static int
11265 showvars(const char *sep_prefix, int on, int off)
11266 {
11267         const char *sep;
11268         char **ep, **epend;
11269
11270         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11271         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11272
11273         sep = *sep_prefix ? " " : sep_prefix;
11274
11275         for (; ep < epend; ep++) {
11276                 const char *p;
11277                 const char *q;
11278
11279                 p = endofname(*ep);
11280 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11281  * makes "export -p" to have output not suitable for "eval":
11282  * import os
11283  * os.environ["test-test"]="test"
11284  * if os.fork() == 0:
11285  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11286  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11287  */
11288                 q = nullstr;
11289                 if (*p == '=')
11290                         q = single_quote(++p);
11291                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11292         }
11293         return 0;
11294 }
11295
11296 /*
11297  * The set command builtin.
11298  */
11299 static int FAST_FUNC
11300 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11301 {
11302         int retval;
11303
11304         if (!argv[1])
11305                 return showvars(nullstr, 0, VUNSET);
11306
11307         INT_OFF;
11308         retval = options(/*login_sh:*/ NULL);
11309         if (retval == 0) { /* if no parse error... */
11310                 optschanged();
11311                 if (*argptr != NULL) {
11312                         setparam(argptr);
11313                 }
11314         }
11315         INT_ON;
11316         return retval;
11317 }
11318
11319 #if ENABLE_ASH_RANDOM_SUPPORT
11320 static void FAST_FUNC
11321 change_random(const char *value)
11322 {
11323         uint32_t t;
11324
11325         if (value == NULL) {
11326                 /* "get", generate */
11327                 t = next_random(&random_gen);
11328                 /* set without recursion */
11329                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11330                 vrandom.flags &= ~VNOFUNC;
11331         } else {
11332                 /* set/reset */
11333                 t = strtoul(value, NULL, 10);
11334                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11335         }
11336 }
11337 #endif
11338
11339 #if BASH_EPOCH_VARS
11340 static void FAST_FUNC
11341 change_epoch(struct var *vepoch, const char *fmt)
11342 {
11343         struct timeval tv;
11344         char buffer[sizeof("%lu.nnnnnn") + sizeof(long)*3];
11345
11346         gettimeofday(&tv, NULL);
11347         sprintf(buffer, fmt, (unsigned long)tv.tv_sec, (unsigned)tv.tv_usec);
11348         setvar(vepoch->var_text, buffer, VNOFUNC);
11349         vepoch->flags &= ~VNOFUNC;
11350 }
11351
11352 static void FAST_FUNC
11353 change_seconds(const char *value UNUSED_PARAM)
11354 {
11355         change_epoch(&vepochs, "%lu");
11356 }
11357
11358 static void FAST_FUNC
11359 change_realtime(const char *value UNUSED_PARAM)
11360 {
11361         change_epoch(&vepochr, "%lu.%06u");
11362 }
11363 #endif
11364
11365 #if ENABLE_ASH_GETOPTS
11366 static int
11367 getopts(char *optstr, char *optvar, char **optfirst)
11368 {
11369         char *p, *q;
11370         char c = '?';
11371         int done = 0;
11372         char sbuf[2];
11373         char **optnext;
11374         int ind = shellparam.optind;
11375         int off = shellparam.optoff;
11376
11377         sbuf[1] = '\0';
11378
11379         shellparam.optind = -1;
11380         optnext = optfirst + ind - 1;
11381
11382         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11383                 p = NULL;
11384         else
11385                 p = optnext[-1] + off;
11386         if (p == NULL || *p == '\0') {
11387                 /* Current word is done, advance */
11388                 p = *optnext;
11389                 if (p == NULL || *p != '-' || *++p == '\0') {
11390  atend:
11391                         unsetvar("OPTARG");
11392                         p = NULL;
11393                         done = 1;
11394                         goto out;
11395                 }
11396                 optnext++;
11397                 if (LONE_DASH(p))        /* check for "--" */
11398                         goto atend;
11399         }
11400
11401         c = *p++;
11402         for (q = optstr; *q != c;) {
11403                 if (*q == '\0') {
11404                         /* OPTERR is a bashism */
11405                         const char *cp = lookupvar("OPTERR");
11406                         if ((cp && LONE_CHAR(cp, '0'))
11407                          || (optstr[0] == ':')
11408                         ) {
11409                                 sbuf[0] = c;
11410                                 /*sbuf[1] = '\0'; - already is */
11411                                 setvar0("OPTARG", sbuf);
11412                         } else {
11413                                 fprintf(stderr, "Illegal option -%c\n", c);
11414                                 unsetvar("OPTARG");
11415                         }
11416                         c = '?';
11417                         goto out;
11418                 }
11419                 if (*++q == ':')
11420                         q++;
11421         }
11422
11423         if (*++q == ':') {
11424                 if (*p == '\0' && (p = *optnext) == NULL) {
11425                         /* OPTERR is a bashism */
11426                         const char *cp = lookupvar("OPTERR");
11427                         if ((cp && LONE_CHAR(cp, '0'))
11428                          || (optstr[0] == ':')
11429                         ) {
11430                                 sbuf[0] = c;
11431                                 /*sbuf[1] = '\0'; - already is */
11432                                 setvar0("OPTARG", sbuf);
11433                                 c = ':';
11434                         } else {
11435                                 fprintf(stderr, "No arg for -%c option\n", c);
11436                                 unsetvar("OPTARG");
11437                                 c = '?';
11438                         }
11439                         goto out;
11440                 }
11441
11442                 if (p == *optnext)
11443                         optnext++;
11444                 setvar0("OPTARG", p);
11445                 p = NULL;
11446         } else
11447                 setvar0("OPTARG", nullstr);
11448  out:
11449         ind = optnext - optfirst + 1;
11450         setvar("OPTIND", itoa(ind), VNOFUNC);
11451         sbuf[0] = c;
11452         /*sbuf[1] = '\0'; - already is */
11453         setvar0(optvar, sbuf);
11454
11455         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11456         shellparam.optind = ind;
11457
11458         return done;
11459 }
11460
11461 /*
11462  * The getopts builtin.  Shellparam.optnext points to the next argument
11463  * to be processed.  Shellparam.optptr points to the next character to
11464  * be processed in the current argument.  If shellparam.optnext is NULL,
11465  * then it's the first time getopts has been called.
11466  */
11467 static int FAST_FUNC
11468 getoptscmd(int argc, char **argv)
11469 {
11470         char **optbase;
11471
11472         if (argc < 3)
11473                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11474         if (argc == 3) {
11475                 optbase = shellparam.p;
11476                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11477                         shellparam.optind = 1;
11478                         shellparam.optoff = -1;
11479                 }
11480         } else {
11481                 optbase = &argv[3];
11482                 if ((unsigned)shellparam.optind > argc - 2) {
11483                         shellparam.optind = 1;
11484                         shellparam.optoff = -1;
11485                 }
11486         }
11487
11488         return getopts(argv[1], argv[2], optbase);
11489 }
11490 #endif /* ASH_GETOPTS */
11491
11492
11493 /* ============ Shell parser */
11494
11495 struct heredoc {
11496         struct heredoc *next;   /* next here document in list */
11497         union node *here;       /* redirection node */
11498         char *eofmark;          /* string indicating end of input */
11499         smallint striptabs;     /* if set, strip leading tabs */
11500 };
11501
11502 static smallint tokpushback;           /* last token pushed back */
11503 static smallint quoteflag;             /* set if (part of) last token was quoted */
11504 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11505 static struct heredoc *heredoclist;    /* list of here documents to read */
11506 static char *wordtext;                 /* text of last word returned by readtoken */
11507 static struct nodelist *backquotelist;
11508 static union node *redirnode;
11509 static struct heredoc *heredoc;
11510
11511 static const char *
11512 tokname(char *buf, int tok)
11513 {
11514         if (tok < TSEMI)
11515                 return tokname_array[tok];
11516         sprintf(buf, "\"%s\"", tokname_array[tok]);
11517         return buf;
11518 }
11519
11520 /* raise_error_unexpected_syntax:
11521  * Called when an unexpected token is read during the parse.  The argument
11522  * is the token that is expected, or -1 if more than one type of token can
11523  * occur at this point.
11524  */
11525 static void raise_error_unexpected_syntax(int) NORETURN;
11526 static void
11527 raise_error_unexpected_syntax(int token)
11528 {
11529         char msg[64];
11530         char buf[16];
11531         int l;
11532
11533         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11534         if (token >= 0)
11535                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11536         raise_error_syntax(msg);
11537         /* NOTREACHED */
11538 }
11539
11540 /* parsing is heavily cross-recursive, need these forward decls */
11541 static union node *andor(void);
11542 static union node *pipeline(void);
11543 static union node *parse_command(void);
11544 static void parseheredoc(void);
11545 static int peektoken(void);
11546 static int readtoken(void);
11547
11548 static union node *
11549 list(int nlflag)
11550 {
11551         union node *n1, *n2, *n3;
11552         int tok;
11553
11554         n1 = NULL;
11555         for (;;) {
11556                 switch (peektoken()) {
11557                 case TNL:
11558                         if (!(nlflag & 1))
11559                                 break;
11560                         parseheredoc();
11561                         return n1;
11562
11563                 case TEOF:
11564                         if (!n1 && (nlflag & 1))
11565                                 n1 = NODE_EOF;
11566                         parseheredoc();
11567                         return n1;
11568                 }
11569
11570                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11571                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11572                         return n1;
11573                 nlflag |= 2;
11574
11575                 n2 = andor();
11576                 tok = readtoken();
11577                 if (tok == TBACKGND) {
11578                         if (n2->type == NPIPE) {
11579                                 n2->npipe.pipe_backgnd = 1;
11580                         } else {
11581                                 if (n2->type != NREDIR) {
11582                                         n3 = stzalloc(sizeof(struct nredir));
11583                                         n3->nredir.n = n2;
11584                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11585                                         n2 = n3;
11586                                 }
11587                                 n2->type = NBACKGND;
11588                         }
11589                 }
11590                 if (n1 == NULL) {
11591                         n1 = n2;
11592                 } else {
11593                         n3 = stzalloc(sizeof(struct nbinary));
11594                         n3->type = NSEMI;
11595                         n3->nbinary.ch1 = n1;
11596                         n3->nbinary.ch2 = n2;
11597                         n1 = n3;
11598                 }
11599                 switch (tok) {
11600                 case TNL:
11601                 case TEOF:
11602                         tokpushback = 1;
11603                         /* fall through */
11604                 case TBACKGND:
11605                 case TSEMI:
11606                         break;
11607                 default:
11608                         if ((nlflag & 1))
11609                                 raise_error_unexpected_syntax(-1);
11610                         tokpushback = 1;
11611                         return n1;
11612                 }
11613         }
11614 }
11615
11616 static union node *
11617 andor(void)
11618 {
11619         union node *n1, *n2, *n3;
11620         int t;
11621
11622         n1 = pipeline();
11623         for (;;) {
11624                 t = readtoken();
11625                 if (t == TAND) {
11626                         t = NAND;
11627                 } else if (t == TOR) {
11628                         t = NOR;
11629                 } else {
11630                         tokpushback = 1;
11631                         return n1;
11632                 }
11633                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11634                 n2 = pipeline();
11635                 n3 = stzalloc(sizeof(struct nbinary));
11636                 n3->type = t;
11637                 n3->nbinary.ch1 = n1;
11638                 n3->nbinary.ch2 = n2;
11639                 n1 = n3;
11640         }
11641 }
11642
11643 static union node *
11644 pipeline(void)
11645 {
11646         union node *n1, *n2, *pipenode;
11647         struct nodelist *lp, *prev;
11648         int negate;
11649
11650         negate = 0;
11651         TRACE(("pipeline: entered\n"));
11652         if (readtoken() == TNOT) {
11653                 negate = !negate;
11654                 checkkwd = CHKKWD | CHKALIAS;
11655         } else
11656                 tokpushback = 1;
11657         n1 = parse_command();
11658         if (readtoken() == TPIPE) {
11659                 pipenode = stzalloc(sizeof(struct npipe));
11660                 pipenode->type = NPIPE;
11661                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11662                 lp = stzalloc(sizeof(struct nodelist));
11663                 pipenode->npipe.cmdlist = lp;
11664                 lp->n = n1;
11665                 do {
11666                         prev = lp;
11667                         lp = stzalloc(sizeof(struct nodelist));
11668                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11669                         lp->n = parse_command();
11670                         prev->next = lp;
11671                 } while (readtoken() == TPIPE);
11672                 lp->next = NULL;
11673                 n1 = pipenode;
11674         }
11675         tokpushback = 1;
11676         if (negate) {
11677                 n2 = stzalloc(sizeof(struct nnot));
11678                 n2->type = NNOT;
11679                 n2->nnot.com = n1;
11680                 return n2;
11681         }
11682         return n1;
11683 }
11684
11685 static union node *
11686 makename(void)
11687 {
11688         union node *n;
11689
11690         n = stzalloc(sizeof(struct narg));
11691         n->type = NARG;
11692         /*n->narg.next = NULL; - stzalloc did it */
11693         n->narg.text = wordtext;
11694         n->narg.backquote = backquotelist;
11695         return n;
11696 }
11697
11698 static void
11699 fixredir(union node *n, const char *text, int err)
11700 {
11701         int fd;
11702
11703         TRACE(("Fix redir %s %d\n", text, err));
11704         if (!err)
11705                 n->ndup.vname = NULL;
11706
11707         fd = bb_strtou(text, NULL, 10);
11708         if (!errno && fd >= 0)
11709                 n->ndup.dupfd = fd;
11710         else if (LONE_DASH(text))
11711                 n->ndup.dupfd = -1;
11712         else {
11713                 if (err)
11714                         raise_error_syntax("bad fd number");
11715                 n->ndup.vname = makename();
11716         }
11717 }
11718
11719 static void
11720 parsefname(void)
11721 {
11722         union node *n = redirnode;
11723
11724         if (n->type == NHERE)
11725                 checkkwd = CHKEOFMARK;
11726         if (readtoken() != TWORD)
11727                 raise_error_unexpected_syntax(-1);
11728         if (n->type == NHERE) {
11729                 struct heredoc *here = heredoc;
11730                 struct heredoc *p;
11731
11732                 if (quoteflag == 0)
11733                         n->type = NXHERE;
11734                 TRACE(("Here document %d\n", n->type));
11735                 rmescapes(wordtext, 0, NULL);
11736                 here->eofmark = wordtext;
11737                 here->next = NULL;
11738                 if (heredoclist == NULL)
11739                         heredoclist = here;
11740                 else {
11741                         for (p = heredoclist; p->next; p = p->next)
11742                                 continue;
11743                         p->next = here;
11744                 }
11745         } else if (n->type == NTOFD || n->type == NFROMFD) {
11746                 fixredir(n, wordtext, 0);
11747         } else {
11748                 n->nfile.fname = makename();
11749         }
11750 }
11751
11752 static union node *
11753 simplecmd(void)
11754 {
11755         union node *args, **app;
11756         union node *n = NULL;
11757         union node *vars, **vpp;
11758         union node **rpp, *redir;
11759         int savecheckkwd;
11760         int savelinno;
11761 #if BASH_TEST2
11762         smallint double_brackets_flag = 0;
11763 #endif
11764         IF_BASH_FUNCTION(smallint function_flag = 0;)
11765
11766         args = NULL;
11767         app = &args;
11768         vars = NULL;
11769         vpp = &vars;
11770         redir = NULL;
11771         rpp = &redir;
11772
11773         savecheckkwd = CHKALIAS;
11774         savelinno = g_parsefile->linno;
11775         for (;;) {
11776                 int t;
11777                 checkkwd = savecheckkwd;
11778                 t = readtoken();
11779                 switch (t) {
11780 #if BASH_FUNCTION
11781                 case TFUNCTION:
11782                         if (peektoken() != TWORD)
11783                                 raise_error_unexpected_syntax(TWORD);
11784                         function_flag = 1;
11785                         break;
11786 #endif
11787 #if BASH_TEST2
11788                 case TAND: /* "&&" */
11789                 case TOR: /* "||" */
11790                         if (!double_brackets_flag) {
11791                                 tokpushback = 1;
11792                                 goto out;
11793                         }
11794                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11795 #endif
11796                 case TWORD:
11797                         n = stzalloc(sizeof(struct narg));
11798                         n->type = NARG;
11799                         /*n->narg.next = NULL; - stzalloc did it */
11800                         n->narg.text = wordtext;
11801 #if BASH_TEST2
11802                         if (strcmp("[[", wordtext) == 0)
11803                                 double_brackets_flag = 1;
11804                         else if (strcmp("]]", wordtext) == 0)
11805                                 double_brackets_flag = 0;
11806 #endif
11807                         n->narg.backquote = backquotelist;
11808                         if (savecheckkwd && isassignment(wordtext)) {
11809                                 *vpp = n;
11810                                 vpp = &n->narg.next;
11811                         } else {
11812                                 *app = n;
11813                                 app = &n->narg.next;
11814                                 savecheckkwd = 0;
11815                         }
11816 #if BASH_FUNCTION
11817                         if (function_flag) {
11818                                 checkkwd = CHKNL | CHKKWD;
11819                                 switch (peektoken()) {
11820                                 case TBEGIN:
11821                                 case TIF:
11822                                 case TCASE:
11823                                 case TUNTIL:
11824                                 case TWHILE:
11825                                 case TFOR:
11826                                         goto do_func;
11827                                 case TLP:
11828                                         function_flag = 0;
11829                                         break;
11830 # if BASH_TEST2
11831                                 case TWORD:
11832                                         if (strcmp("[[", wordtext) == 0)
11833                                                 goto do_func;
11834                                         /* fall through */
11835 # endif
11836                                 default:
11837                                         raise_error_unexpected_syntax(-1);
11838                                 }
11839                         }
11840 #endif
11841                         break;
11842                 case TREDIR:
11843                         *rpp = n = redirnode;
11844                         rpp = &n->nfile.next;
11845                         parsefname();   /* read name of redirection file */
11846                         break;
11847                 case TLP:
11848  IF_BASH_FUNCTION(do_func:)
11849                         if (args && app == &args->narg.next
11850                          && !vars && !redir
11851                         ) {
11852                                 struct builtincmd *bcmd;
11853                                 const char *name;
11854
11855                                 /* We have a function */
11856                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11857                                         raise_error_unexpected_syntax(TRP);
11858                                 name = n->narg.text;
11859                                 if (!goodname(name)
11860                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11861                                 ) {
11862                                         raise_error_syntax("bad function name");
11863                                 }
11864                                 n->type = NDEFUN;
11865                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11866                                 n->ndefun.text = n->narg.text;
11867                                 n->ndefun.linno = g_parsefile->linno;
11868                                 n->ndefun.body = parse_command();
11869                                 return n;
11870                         }
11871                         IF_BASH_FUNCTION(function_flag = 0;)
11872                         /* fall through */
11873                 default:
11874                         tokpushback = 1;
11875                         goto out;
11876                 }
11877         }
11878  out:
11879         *app = NULL;
11880         *vpp = NULL;
11881         *rpp = NULL;
11882         n = stzalloc(sizeof(struct ncmd));
11883         if (NCMD != 0)
11884                 n->type = NCMD;
11885         n->ncmd.linno = savelinno;
11886         n->ncmd.args = args;
11887         n->ncmd.assign = vars;
11888         n->ncmd.redirect = redir;
11889         return n;
11890 }
11891
11892 static union node *
11893 parse_command(void)
11894 {
11895         union node *n1, *n2;
11896         union node *ap, **app;
11897         union node *cp, **cpp;
11898         union node *redir, **rpp;
11899         union node **rpp2;
11900         int t;
11901         int savelinno;
11902
11903         redir = NULL;
11904         rpp2 = &redir;
11905
11906         savelinno = g_parsefile->linno;
11907
11908         switch (readtoken()) {
11909         default:
11910                 raise_error_unexpected_syntax(-1);
11911                 /* NOTREACHED */
11912         case TIF:
11913                 n1 = stzalloc(sizeof(struct nif));
11914                 n1->type = NIF;
11915                 n1->nif.test = list(0);
11916                 if (readtoken() != TTHEN)
11917                         raise_error_unexpected_syntax(TTHEN);
11918                 n1->nif.ifpart = list(0);
11919                 n2 = n1;
11920                 while (readtoken() == TELIF) {
11921                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11922                         n2 = n2->nif.elsepart;
11923                         n2->type = NIF;
11924                         n2->nif.test = list(0);
11925                         if (readtoken() != TTHEN)
11926                                 raise_error_unexpected_syntax(TTHEN);
11927                         n2->nif.ifpart = list(0);
11928                 }
11929                 if (lasttoken == TELSE)
11930                         n2->nif.elsepart = list(0);
11931                 else {
11932                         n2->nif.elsepart = NULL;
11933                         tokpushback = 1;
11934                 }
11935                 t = TFI;
11936                 break;
11937         case TWHILE:
11938         case TUNTIL: {
11939                 int got;
11940                 n1 = stzalloc(sizeof(struct nbinary));
11941                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11942                 n1->nbinary.ch1 = list(0);
11943                 got = readtoken();
11944                 if (got != TDO) {
11945                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11946                                         got == TWORD ? wordtext : ""));
11947                         raise_error_unexpected_syntax(TDO);
11948                 }
11949                 n1->nbinary.ch2 = list(0);
11950                 t = TDONE;
11951                 break;
11952         }
11953         case TFOR:
11954                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11955                         raise_error_syntax("bad for loop variable");
11956                 n1 = stzalloc(sizeof(struct nfor));
11957                 n1->type = NFOR;
11958                 n1->nfor.linno = savelinno;
11959                 n1->nfor.var = wordtext;
11960                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11961                 if (readtoken() == TIN) {
11962                         app = &ap;
11963                         while (readtoken() == TWORD) {
11964                                 n2 = stzalloc(sizeof(struct narg));
11965                                 n2->type = NARG;
11966                                 /*n2->narg.next = NULL; - stzalloc did it */
11967                                 n2->narg.text = wordtext;
11968                                 n2->narg.backquote = backquotelist;
11969                                 *app = n2;
11970                                 app = &n2->narg.next;
11971                         }
11972                         *app = NULL;
11973                         n1->nfor.args = ap;
11974                         if (lasttoken != TNL && lasttoken != TSEMI)
11975                                 raise_error_unexpected_syntax(-1);
11976                 } else {
11977                         n2 = stzalloc(sizeof(struct narg));
11978                         n2->type = NARG;
11979                         /*n2->narg.next = NULL; - stzalloc did it */
11980                         n2->narg.text = (char *)dolatstr;
11981                         /*n2->narg.backquote = NULL;*/
11982                         n1->nfor.args = n2;
11983                         /*
11984                          * Newline or semicolon here is optional (but note
11985                          * that the original Bourne shell only allowed NL).
11986                          */
11987                         if (lasttoken != TSEMI)
11988                                 tokpushback = 1;
11989                 }
11990                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11991                 if (readtoken() != TDO)
11992                         raise_error_unexpected_syntax(TDO);
11993                 n1->nfor.body = list(0);
11994                 t = TDONE;
11995                 break;
11996         case TCASE:
11997                 n1 = stzalloc(sizeof(struct ncase));
11998                 n1->type = NCASE;
11999                 n1->ncase.linno = savelinno;
12000                 if (readtoken() != TWORD)
12001                         raise_error_unexpected_syntax(TWORD);
12002                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
12003                 n2->type = NARG;
12004                 /*n2->narg.next = NULL; - stzalloc did it */
12005                 n2->narg.text = wordtext;
12006                 n2->narg.backquote = backquotelist;
12007                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
12008                 if (readtoken() != TIN)
12009                         raise_error_unexpected_syntax(TIN);
12010                 cpp = &n1->ncase.cases;
12011  next_case:
12012                 checkkwd = CHKNL | CHKKWD;
12013                 t = readtoken();
12014                 while (t != TESAC) {
12015                         if (lasttoken == TLP)
12016                                 readtoken();
12017                         *cpp = cp = stzalloc(sizeof(struct nclist));
12018                         cp->type = NCLIST;
12019                         app = &cp->nclist.pattern;
12020                         for (;;) {
12021                                 *app = ap = stzalloc(sizeof(struct narg));
12022                                 ap->type = NARG;
12023                                 /*ap->narg.next = NULL; - stzalloc did it */
12024                                 ap->narg.text = wordtext;
12025                                 ap->narg.backquote = backquotelist;
12026                                 if (readtoken() != TPIPE)
12027                                         break;
12028                                 app = &ap->narg.next;
12029                                 readtoken();
12030                         }
12031                         //ap->narg.next = NULL;
12032                         if (lasttoken != TRP)
12033                                 raise_error_unexpected_syntax(TRP);
12034                         cp->nclist.body = list(2);
12035
12036                         cpp = &cp->nclist.next;
12037
12038                         checkkwd = CHKNL | CHKKWD;
12039                         t = readtoken();
12040                         if (t != TESAC) {
12041                                 if (t != TENDCASE)
12042                                         raise_error_unexpected_syntax(TENDCASE);
12043                                 goto next_case;
12044                         }
12045                 }
12046                 *cpp = NULL;
12047                 goto redir;
12048         case TLP:
12049                 n1 = stzalloc(sizeof(struct nredir));
12050                 n1->type = NSUBSHELL;
12051                 n1->nredir.linno = savelinno;
12052                 n1->nredir.n = list(0);
12053                 /*n1->nredir.redirect = NULL; - stzalloc did it */
12054                 t = TRP;
12055                 break;
12056         case TBEGIN:
12057                 n1 = list(0);
12058                 t = TEND;
12059                 break;
12060         IF_BASH_FUNCTION(case TFUNCTION:)
12061         case TWORD:
12062         case TREDIR:
12063                 tokpushback = 1;
12064                 return simplecmd();
12065         }
12066
12067         if (readtoken() != t)
12068                 raise_error_unexpected_syntax(t);
12069
12070  redir:
12071         /* Now check for redirection which may follow command */
12072         checkkwd = CHKKWD | CHKALIAS;
12073         rpp = rpp2;
12074         while (readtoken() == TREDIR) {
12075                 *rpp = n2 = redirnode;
12076                 rpp = &n2->nfile.next;
12077                 parsefname();
12078         }
12079         tokpushback = 1;
12080         *rpp = NULL;
12081         if (redir) {
12082                 if (n1->type != NSUBSHELL) {
12083                         n2 = stzalloc(sizeof(struct nredir));
12084                         n2->type = NREDIR;
12085                         n2->nredir.linno = savelinno;
12086                         n2->nredir.n = n1;
12087                         n1 = n2;
12088                 }
12089                 n1->nredir.redirect = redir;
12090         }
12091         return n1;
12092 }
12093
12094 #if BASH_DOLLAR_SQUOTE
12095 static int
12096 decode_dollar_squote(void)
12097 {
12098         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
12099         int c, cnt;
12100         char *p;
12101         char buf[4];
12102
12103         c = pgetc();
12104         p = strchr(C_escapes, c);
12105         if (p) {
12106                 buf[0] = c;
12107                 p = buf;
12108                 cnt = 3;
12109                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
12110                         do {
12111                                 c = pgetc();
12112                                 *++p = c;
12113                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
12114                         pungetc();
12115                 } else if (c == 'x') { /* \xHH */
12116                         do {
12117                                 c = pgetc();
12118                                 *++p = c;
12119                         } while (isxdigit(c) && --cnt);
12120                         pungetc();
12121                         if (cnt == 3) { /* \x but next char is "bad" */
12122                                 c = 'x';
12123                                 goto unrecognized;
12124                         }
12125                 } else { /* simple seq like \\ or \t */
12126                         p++;
12127                 }
12128                 *p = '\0';
12129                 p = buf;
12130                 c = bb_process_escape_sequence((void*)&p);
12131         } else { /* unrecognized "\z": print both chars unless ' or " */
12132                 if (c != '\'' && c != '"') {
12133  unrecognized:
12134                         c |= 0x100; /* "please encode \, then me" */
12135                 }
12136         }
12137         return c;
12138 }
12139 #endif
12140
12141 /* Used by expandstr to get here-doc like behaviour. */
12142 #define FAKEEOFMARK ((char*)(uintptr_t)1)
12143
12144 static ALWAYS_INLINE int
12145 realeofmark(const char *eofmark)
12146 {
12147         return eofmark && eofmark != FAKEEOFMARK;
12148 }
12149
12150 /*
12151  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
12152  * is not NULL, read a here document.  In the latter case, eofmark is the
12153  * word which marks the end of the document and striptabs is true if
12154  * leading tabs should be stripped from the document.  The argument c
12155  * is the first character of the input token or document.
12156  *
12157  * Because C does not have internal subroutines, I have simulated them
12158  * using goto's to implement the subroutine linkage.  The following macros
12159  * will run code that appears at the end of readtoken1.
12160  */
12161 #define CHECKEND()      {goto checkend; checkend_return:;}
12162 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
12163 #define PARSESUB()      {goto parsesub; parsesub_return:;}
12164 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
12165 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
12166 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
12167 static int
12168 readtoken1(int c, int syntax, char *eofmark, int striptabs)
12169 {
12170         /* NB: syntax parameter fits into smallint */
12171         /* c parameter is an unsigned char or PEOF or PEOA */
12172         char *out;
12173         size_t len;
12174         struct nodelist *bqlist;
12175         smallint quotef;
12176         smallint oldstyle;
12177         smallint pssyntax;   /* we are expanding a prompt string */
12178         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
12179         /* syntax stack */
12180         struct synstack synbase = { };
12181         struct synstack *synstack = &synbase;
12182
12183 #if ENABLE_ASH_EXPAND_PRMT
12184         pssyntax = (syntax == PSSYNTAX);
12185         if (pssyntax)
12186                 syntax = DQSYNTAX;
12187 #else
12188         pssyntax = 0; /* constant */
12189 #endif
12190         synstack->syntax = syntax;
12191
12192         if (syntax == DQSYNTAX)
12193                 synstack->dblquote = 1;
12194         quotef = 0;
12195         bqlist = NULL;
12196
12197         STARTSTACKSTR(out);
12198  loop:
12199         /* For each line, until end of word */
12200         CHECKEND();     /* set c to PEOF if at end of here document */
12201         for (;;) {      /* until end of line or end of word */
12202                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12203                 switch (SIT(c, synstack->syntax)) {
12204                 case CNL:       /* '\n' */
12205                         if (synstack->syntax == BASESYNTAX
12206                          && !synstack->varnest
12207                         ) {
12208                                 goto endword;   /* exit outer loop */
12209                         }
12210                         USTPUTC(c, out);
12211                         nlprompt();
12212                         c = pgetc_top(synstack);
12213                         goto loop;              /* continue outer loop */
12214                 case CWORD:
12215                         USTPUTC(c, out);
12216                         break;
12217                 case CCTL:
12218 #if BASH_DOLLAR_SQUOTE
12219                         if (c == '\\' && bash_dollar_squote) {
12220                                 c = decode_dollar_squote();
12221                                 if (c == '\0') {
12222                                         /* skip $'\000', $'\x00' (like bash) */
12223                                         break;
12224                                 }
12225                                 if (c & 0x100) {
12226                                         /* Unknown escape. Encode as '\z' */
12227                                         c = (unsigned char)c;
12228                                         if (eofmark == NULL || synstack->dblquote)
12229                                                 USTPUTC(CTLESC, out);
12230                                         USTPUTC('\\', out);
12231                                 }
12232                         }
12233 #endif
12234                         if (!eofmark || synstack->dblquote || synstack->varnest)
12235                                 USTPUTC(CTLESC, out);
12236                         USTPUTC(c, out);
12237                         break;
12238                 case CBACK:     /* backslash */
12239                         c = pgetc_without_PEOA();
12240                         if (c == PEOF) {
12241                                 USTPUTC(CTLESC, out);
12242                                 USTPUTC('\\', out);
12243                                 pungetc();
12244                         } else {
12245                                 if (pssyntax && c == '$') {
12246                                         USTPUTC(CTLESC, out);
12247                                         USTPUTC('\\', out);
12248                                 }
12249                                 /* Backslash is retained if we are in "str"
12250                                  * and next char isn't dquote-special.
12251                                  */
12252                                 if (synstack->dblquote
12253                                  && c != '\\'
12254                                  && c != '`'
12255                                  && c != '$'
12256                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12257                                  && (c != '}' || !synstack->varnest)
12258                                 ) {
12259                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12260                                         USTPUTC('\\', out);
12261                                 }
12262                                 USTPUTC(CTLESC, out);
12263                                 USTPUTC(c, out);
12264                                 quotef = 1;
12265                         }
12266                         break;
12267                 case CSQUOTE:
12268                         synstack->syntax = SQSYNTAX;
12269  quotemark:
12270                         if (eofmark == NULL) {
12271                                 USTPUTC(CTLQUOTEMARK, out);
12272                         }
12273                         break;
12274                 case CDQUOTE:
12275                         synstack->syntax = DQSYNTAX;
12276                         synstack->dblquote = 1;
12277  toggledq:
12278                         if (synstack->varnest)
12279                                 synstack->innerdq ^= 1;
12280                         goto quotemark;
12281                 case CENDQUOTE:
12282                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12283                         if (eofmark != NULL && synstack->varnest == 0) {
12284                                 USTPUTC(c, out);
12285                                 break;
12286                         }
12287
12288                         if (synstack->dqvarnest == 0) {
12289                                 synstack->syntax = BASESYNTAX;
12290                                 synstack->dblquote = 0;
12291                         }
12292
12293                         quotef = 1;
12294
12295                         if (c == '"')
12296                                 goto toggledq;
12297
12298                         goto quotemark;
12299                 case CVAR:      /* '$' */
12300                         PARSESUB();             /* parse substitution */
12301                         break;
12302                 case CENDVAR:   /* '}' */
12303                         if (!synstack->innerdq && synstack->varnest > 0) {
12304                                 if (!--synstack->varnest && synstack->varpushed)
12305                                         synstack_pop(&synstack);
12306                                 else if (synstack->dqvarnest > 0)
12307                                         synstack->dqvarnest--;
12308                                 c = CTLENDVAR;
12309                         }
12310                         USTPUTC(c, out);
12311                         break;
12312 #if ENABLE_FEATURE_SH_MATH
12313                 case CLP:       /* '(' in arithmetic */
12314                         synstack->parenlevel++;
12315                         USTPUTC(c, out);
12316                         break;
12317                 case CRP:       /* ')' in arithmetic */
12318                         if (synstack->parenlevel > 0) {
12319                                 synstack->parenlevel--;
12320                         } else {
12321                                 if (pgetc_eatbnl() == ')') {
12322                                         c = CTLENDARI;
12323                                         synstack_pop(&synstack);
12324                                 } else {
12325                                         /*
12326                                          * unbalanced parens
12327                                          * (don't 2nd guess - no error)
12328                                          */
12329                                         pungetc();
12330                                 }
12331                         }
12332                         USTPUTC(c, out);
12333                         break;
12334 #endif
12335                 case CBQUOTE:   /* '`' */
12336                         if (checkkwd & CHKEOFMARK) {
12337                                 quotef = 1;
12338                                 USTPUTC('`', out);
12339                                 break;
12340                         }
12341
12342                         PARSEBACKQOLD();
12343                         break;
12344                 case CENDFILE:
12345                         goto endword;           /* exit outer loop */
12346                 case CIGN:
12347                         break;
12348                 default:
12349                         if (synstack->varnest == 0) {
12350 #if BASH_REDIR_OUTPUT
12351                                 if (c == '&') {
12352 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12353                                         if (pgetc() == '>')
12354                                                 c = 0x100 + '>'; /* flag &> */
12355                                         pungetc();
12356                                 }
12357 #endif
12358                                 goto endword;   /* exit outer loop */
12359                         }
12360                         IF_ASH_ALIAS(if (c != PEOA))
12361                                 USTPUTC(c, out);
12362                 }
12363                 c = pgetc_top(synstack);
12364         } /* for (;;) */
12365  endword:
12366
12367 #if ENABLE_FEATURE_SH_MATH
12368         if (synstack->syntax == ARISYNTAX)
12369                 raise_error_syntax("missing '))'");
12370 #endif
12371         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12372                 raise_error_syntax("unterminated quoted string");
12373         if (synstack->varnest != 0) {
12374                 /* { */
12375                 raise_error_syntax("missing '}'");
12376         }
12377         USTPUTC('\0', out);
12378         len = out - (char *)stackblock();
12379         out = stackblock();
12380         if (eofmark == NULL) {
12381                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12382                  && quotef == 0
12383                 ) {
12384                         if (isdigit_str9(out)) {
12385                                 PARSEREDIR(); /* passed as params: out, c */
12386                                 lasttoken = TREDIR;
12387                                 return lasttoken;
12388                         }
12389                         /* else: non-number X seen, interpret it
12390                          * as "NNNX>file" = "NNNX >file" */
12391                 }
12392                 pungetc();
12393         }
12394         quoteflag = quotef;
12395         backquotelist = bqlist;
12396         grabstackblock(len);
12397         wordtext = out;
12398         lasttoken = TWORD;
12399         return lasttoken;
12400 /* end of readtoken routine */
12401
12402 /*
12403  * Check to see whether we are at the end of the here document.  When this
12404  * is called, c is set to the first character of the next input line.  If
12405  * we are at the end of the here document, this routine sets the c to PEOF.
12406  */
12407 checkend: {
12408         if (realeofmark(eofmark)) {
12409                 int markloc;
12410                 char *p;
12411
12412 #if ENABLE_ASH_ALIAS
12413                 if (c == PEOA)
12414                         c = pgetc_without_PEOA();
12415 #endif
12416                 if (striptabs) {
12417                         while (c == '\t') {
12418                                 c = pgetc_without_PEOA();
12419                         }
12420                 }
12421
12422                 markloc = out - (char *)stackblock();
12423                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12424                         if (c != *p)
12425                                 goto more_heredoc;
12426                         /* FIXME: fails for backslash-newlined terminator:
12427                          * cat <<EOF
12428                          * ...
12429                          * EO\
12430                          * F
12431                          * (see heredoc_bkslash_newline2.tests)
12432                          */
12433                         c = pgetc_without_PEOA();
12434                 }
12435
12436                 if (c == '\n' || c == PEOF) {
12437                         c = PEOF;
12438                         g_parsefile->linno++;
12439                         needprompt = doprompt;
12440                 } else {
12441                         int len_here;
12442
12443  more_heredoc:
12444                         p = (char *)stackblock() + markloc + 1;
12445                         len_here = out - p;
12446
12447                         if (len_here) {
12448                                 len_here -= (c >= PEOF);
12449                                 c = p[-1];
12450
12451                                 if (len_here) {
12452                                         char *str;
12453
12454                                         str = alloca(len_here + 1);
12455                                         *(char *)mempcpy(str, p, len_here) = '\0';
12456
12457                                         pushstring(str, NULL);
12458                                 }
12459                         }
12460                 }
12461
12462                 STADJUST((char *)stackblock() + markloc - out, out);
12463         }
12464         goto checkend_return;
12465 }
12466
12467 /*
12468  * Parse a redirection operator.  The variable "out" points to a string
12469  * specifying the fd to be redirected.  The variable "c" contains the
12470  * first character of the redirection operator.
12471  */
12472 parseredir: {
12473         /* out is already checked to be a valid number or "" */
12474         int fd = (*out == '\0' ? -1 : atoi(out));
12475         union node *np;
12476
12477         np = stzalloc(sizeof(struct nfile));
12478         if (c == '>') {
12479                 np->nfile.fd = 1;
12480                 c = pgetc_eatbnl();
12481                 if (c == '>')
12482                         np->type = NAPPEND;
12483                 else if (c == '|')
12484                         np->type = NCLOBBER;
12485                 else if (c == '&')
12486                         np->type = NTOFD;
12487                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12488                 else {
12489                         np->type = NTO;
12490                         pungetc();
12491                 }
12492         }
12493 #if BASH_REDIR_OUTPUT
12494         else if (c == 0x100 + '>') { /* this flags &> redirection */
12495                 np->nfile.fd = 1;
12496                 pgetc(); /* this is '>', no need to check */
12497                 np->type = NTO2;
12498         }
12499 #endif
12500         else { /* c == '<' */
12501                 /*np->nfile.fd = 0; - stzalloc did it */
12502                 c = pgetc_eatbnl();
12503                 switch (c) {
12504                 case '<':
12505                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12506                                 np = stzalloc(sizeof(struct nhere));
12507                                 /*np->nfile.fd = 0; - stzalloc did it */
12508                         }
12509                         np->type = NHERE;
12510                         heredoc = stzalloc(sizeof(struct heredoc));
12511                         heredoc->here = np;
12512                         c = pgetc_eatbnl();
12513                         if (c == '-') {
12514                                 heredoc->striptabs = 1;
12515                         } else {
12516                                 /*heredoc->striptabs = 0; - stzalloc did it */
12517                                 pungetc();
12518                         }
12519                         break;
12520
12521                 case '&':
12522                         np->type = NFROMFD;
12523                         break;
12524
12525                 case '>':
12526                         np->type = NFROMTO;
12527                         break;
12528
12529                 default:
12530                         np->type = NFROM;
12531                         pungetc();
12532                         break;
12533                 }
12534         }
12535         if (fd >= 0)
12536                 np->nfile.fd = fd;
12537         redirnode = np;
12538         goto parseredir_return;
12539 }
12540
12541 /*
12542  * Parse a substitution.  At this point, we have read the dollar sign
12543  * and nothing else.
12544  */
12545
12546 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12547  * (assuming ascii char codes, as the original implementation did) */
12548 #define is_special(c) \
12549         (((unsigned)(c) - 33 < 32) \
12550                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12551 parsesub: {
12552         unsigned char subtype;
12553         int typeloc;
12554
12555         c = pgetc_eatbnl();
12556         if ((checkkwd & CHKEOFMARK)
12557          || c > 255 /* PEOA or PEOF */
12558          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12559         ) {
12560 #if BASH_DOLLAR_SQUOTE
12561                 if (synstack->syntax != DQSYNTAX && c == '\'')
12562                         bash_dollar_squote = 1;
12563                 else
12564 #endif
12565                         USTPUTC('$', out);
12566                 pungetc();
12567         } else if (c == '(') {
12568                 /* $(command) or $((arith)) */
12569                 if (pgetc_eatbnl() == '(') {
12570 #if ENABLE_FEATURE_SH_MATH
12571                         PARSEARITH();
12572 #else
12573                         raise_error_syntax("support for $((arith)) is disabled");
12574 #endif
12575                 } else {
12576                         pungetc();
12577                         PARSEBACKQNEW();
12578                 }
12579         } else {
12580                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12581                 smalluint newsyn = synstack->syntax;
12582
12583                 USTPUTC(CTLVAR, out);
12584                 typeloc = out - (char *)stackblock();
12585                 STADJUST(1, out);
12586                 subtype = VSNORMAL;
12587                 if (c == '{') {
12588                         c = pgetc_eatbnl();
12589                         subtype = 0;
12590                 }
12591  varname:
12592                 if (is_name(c)) {
12593                         /* $[{[#]]NAME[}] */
12594                         do {
12595                                 STPUTC(c, out);
12596                                 c = pgetc_eatbnl();
12597                         } while (is_in_name(c));
12598                 } else if (isdigit(c)) {
12599                         /* $[{[#]]NUM[}] */
12600                         do {
12601                                 STPUTC(c, out);
12602                                 c = pgetc_eatbnl();
12603                         } while (isdigit(c));
12604                 } else if (c != '}') {
12605                         /* $[{[#]]<specialchar>[}] */
12606                         int cc = c;
12607
12608                         c = pgetc_eatbnl();
12609                         if (!subtype && cc == '#') {
12610                                 subtype = VSLENGTH;
12611                                 if (c == '_' || isalnum(c))
12612                                         goto varname;
12613                                 cc = c;
12614                                 c = pgetc_eatbnl();
12615                                 if (cc == '}' || c != '}') {
12616                                         pungetc();
12617                                         subtype = 0;
12618                                         c = cc;
12619                                         cc = '#';
12620                                 }
12621                         }
12622
12623                         if (!is_special(cc)) {
12624                                 if (subtype == VSLENGTH)
12625                                         subtype = 0;
12626                                 goto badsub;
12627                         }
12628
12629                         USTPUTC(cc, out);
12630                 } else
12631                         goto badsub;
12632
12633                 if (c != '}' && subtype == VSLENGTH) {
12634                         /* ${#VAR didn't end with } */
12635                         goto badsub;
12636                 }
12637
12638                 if (subtype == 0) {
12639                         static const char types[] ALIGN1 = "}-+?=";
12640                         /* ${VAR...} but not $VAR or ${#VAR} */
12641                         /* c == first char after VAR */
12642                         int cc = c;
12643
12644                         switch (c) {
12645                         case ':':
12646                                 c = pgetc_eatbnl();
12647 #if BASH_SUBSTR
12648                                 /* This check is only needed to not misinterpret
12649                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12650                                  * constructs.
12651                                  */
12652                                 if (!strchr(types, c)) {
12653                                         subtype = VSSUBSTR;
12654                                         pungetc();
12655                                         break; /* "goto badsub" is bigger (!) */
12656                                 }
12657 #endif
12658                                 subtype = VSNUL;
12659                                 /*FALLTHROUGH*/
12660                         default: {
12661                                 const char *p = strchr(types, c);
12662                                 if (p == NULL)
12663                                         break;
12664                                 subtype |= p - types + VSNORMAL;
12665                                 break;
12666                         }
12667                         case '%':
12668                         case '#':
12669                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12670                                 c = pgetc_eatbnl();
12671                                 if (c == cc)
12672                                         subtype++;
12673                                 else
12674                                         pungetc();
12675
12676                                 newsyn = BASESYNTAX;
12677                                 break;
12678 #if BASH_PATTERN_SUBST
12679                         case '/':
12680                                 /* ${v/[/]pattern/repl} */
12681 //TODO: encode pattern and repl separately.
12682 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12683 // are broken (should print "ONE")
12684                                 subtype = VSREPLACE;
12685                                 newsyn = BASESYNTAX;
12686                                 c = pgetc_eatbnl();
12687                                 if (c != '/')
12688                                         goto badsub;
12689                                 subtype++; /* VSREPLACEALL */
12690                                 break;
12691 #endif
12692                         }
12693                 } else {
12694  badsub:
12695                         pungetc();
12696                 }
12697
12698                 if (newsyn == ARISYNTAX)
12699                         newsyn = DQSYNTAX;
12700
12701                 if ((newsyn != synstack->syntax || synstack->innerdq)
12702                  && subtype != VSNORMAL
12703                 ) {
12704                         synstack_push(&synstack,
12705                                 synstack->prev ?: alloca(sizeof(*synstack)),
12706                                 newsyn);
12707
12708                         synstack->varpushed = 1;
12709                         synstack->dblquote = newsyn != BASESYNTAX;
12710                 }
12711
12712                 ((unsigned char *)stackblock())[typeloc] = subtype;
12713                 if (subtype != VSNORMAL) {
12714                         synstack->varnest++;
12715                         if (synstack->dblquote)
12716                                 synstack->dqvarnest++;
12717                 }
12718                 STPUTC('=', out);
12719         }
12720         goto parsesub_return;
12721 }
12722
12723 /*
12724  * Called to parse command substitutions.  Newstyle is set if the command
12725  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12726  * list of commands (passed by reference), and savelen is the number of
12727  * characters on the top of the stack which must be preserved.
12728  */
12729 parsebackq: {
12730         struct nodelist **nlpp;
12731         union node *n;
12732         char *str;
12733         size_t savelen;
12734         smallint saveprompt = 0;
12735
12736         str = NULL;
12737         savelen = out - (char *)stackblock();
12738         if (savelen > 0) {
12739                 /*
12740                  * FIXME: this can allocate very large block on stack and SEGV.
12741                  * Example:
12742                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12743                  * allocates 100kb for every command subst. With about
12744                  * a hundred command substitutions stack overflows.
12745                  * With larger prepended string, SEGV happens sooner.
12746                  */
12747                 str = alloca(savelen);
12748                 memcpy(str, stackblock(), savelen);
12749         }
12750
12751         if (oldstyle) {
12752                 /* We must read until the closing backquote, giving special
12753                  * treatment to some slashes, and then push the string and
12754                  * reread it as input, interpreting it normally.
12755                  */
12756                 char *pout;
12757                 size_t psavelen;
12758                 char *pstr;
12759
12760                 STARTSTACKSTR(pout);
12761                 for (;;) {
12762                         int pc;
12763
12764                         setprompt_if(needprompt, 2);
12765                         pc = pgetc_eatbnl();
12766                         switch (pc) {
12767                         case '`':
12768                                 goto done;
12769
12770                         case '\\':
12771                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12772                                 if (pc != '\\' && pc != '`' && pc != '$'
12773                                  && (!synstack->dblquote || pc != '"')
12774                                 ) {
12775                                         STPUTC('\\', pout);
12776                                 }
12777                                 if (pc <= 255 /* not PEOA or PEOF */) {
12778                                         break;
12779                                 }
12780                                 /* fall through */
12781
12782                         case PEOF:
12783                         IF_ASH_ALIAS(case PEOA:)
12784                                 raise_error_syntax("EOF in backquote substitution");
12785
12786                         case '\n':
12787                                 nlnoprompt();
12788                                 break;
12789
12790                         default:
12791                                 break;
12792                         }
12793                         STPUTC(pc, pout);
12794                 }
12795  done:
12796                 STPUTC('\0', pout);
12797                 psavelen = pout - (char *)stackblock();
12798                 if (psavelen > 0) {
12799                         pstr = grabstackstr(pout);
12800                         setinputstring(pstr);
12801                 }
12802         }
12803         nlpp = &bqlist;
12804         while (*nlpp)
12805                 nlpp = &(*nlpp)->next;
12806         *nlpp = stzalloc(sizeof(**nlpp));
12807         /* (*nlpp)->next = NULL; - stzalloc did it */
12808
12809         if (oldstyle) {
12810                 saveprompt = doprompt;
12811                 doprompt = 0;
12812         }
12813
12814         n = list(2);
12815
12816         if (oldstyle)
12817                 doprompt = saveprompt;
12818         else if (readtoken() != TRP)
12819                 raise_error_unexpected_syntax(TRP);
12820
12821         (*nlpp)->n = n;
12822         if (oldstyle) {
12823                 /*
12824                  * Start reading from old file again, ignoring any pushed back
12825                  * tokens left from the backquote parsing
12826                  */
12827                 popfile();
12828                 tokpushback = 0;
12829         }
12830         while (stackblocksize() <= savelen)
12831                 growstackblock();
12832         STARTSTACKSTR(out);
12833         if (str) {
12834                 memcpy(out, str, savelen);
12835                 STADJUST(savelen, out);
12836         }
12837         USTPUTC(CTLBACKQ, out);
12838         if (oldstyle)
12839                 goto parsebackq_oldreturn;
12840         goto parsebackq_newreturn;
12841 }
12842
12843 #if ENABLE_FEATURE_SH_MATH
12844 /*
12845  * Parse an arithmetic expansion (indicate start of one and set state)
12846  */
12847 parsearith: {
12848
12849         synstack_push(&synstack,
12850                         synstack->prev ?: alloca(sizeof(*synstack)),
12851                         ARISYNTAX);
12852         synstack->dblquote = 1;
12853         USTPUTC(CTLARI, out);
12854         goto parsearith_return;
12855 }
12856 #endif
12857 } /* end of readtoken */
12858
12859 /*
12860  * Read the next input token.
12861  * If the token is a word, we set backquotelist to the list of cmds in
12862  *      backquotes.  We set quoteflag to true if any part of the word was
12863  *      quoted.
12864  * If the token is TREDIR, then we set redirnode to a structure containing
12865  *      the redirection.
12866  *
12867  * [Change comment:  here documents and internal procedures]
12868  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12869  *  word parsing code into a separate routine.  In this case, readtoken
12870  *  doesn't need to have any internal procedures, but parseword does.
12871  *  We could also make parseoperator in essence the main routine, and
12872  *  have parseword (readtoken1?) handle both words and redirection.]
12873  */
12874 #define NEW_xxreadtoken
12875 #ifdef NEW_xxreadtoken
12876 /* singles must be first! */
12877 static const char xxreadtoken_chars[7] ALIGN1 = {
12878         '\n', '(', ')', /* singles */
12879         '&', '|', ';',  /* doubles */
12880         0
12881 };
12882
12883 #define xxreadtoken_singles 3
12884 #define xxreadtoken_doubles 3
12885
12886 static const char xxreadtoken_tokens[] ALIGN1 = {
12887         TNL, TLP, TRP,          /* only single occurrence allowed */
12888         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12889         TEOF,                   /* corresponds to trailing nul */
12890         TAND, TOR, TENDCASE     /* if double occurrence */
12891 };
12892
12893 static int
12894 xxreadtoken(void)
12895 {
12896         int c;
12897
12898         if (tokpushback) {
12899                 tokpushback = 0;
12900                 return lasttoken;
12901         }
12902         setprompt_if(needprompt, 2);
12903         for (;;) {                      /* until token or start of word found */
12904                 c = pgetc_eatbnl();
12905                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12906                         continue;
12907
12908                 if (c == '#') {
12909                         while ((c = pgetc()) != '\n' && c != PEOF)
12910                                 continue;
12911                         pungetc();
12912                 } else if (c == '\\') {
12913                         break; /* return readtoken1(...) */
12914                 } else {
12915                         const char *p;
12916
12917                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12918                         if (c != PEOF) {
12919                                 if (c == '\n') {
12920                                         nlnoprompt();
12921                                 }
12922
12923                                 p = strchr(xxreadtoken_chars, c);
12924                                 if (p == NULL)
12925                                         break; /* return readtoken1(...) */
12926
12927                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12928                                         int cc = pgetc_eatbnl();
12929                                         if (cc == c) {    /* double occurrence? */
12930                                                 p += xxreadtoken_doubles + 1;
12931                                         } else {
12932                                                 pungetc();
12933 #if BASH_REDIR_OUTPUT
12934                                                 if (c == '&' && cc == '>') /* &> */
12935                                                         break; /* return readtoken1(...) */
12936 #endif
12937                                         }
12938                                 }
12939                         }
12940                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12941                         return lasttoken;
12942                 }
12943         } /* for (;;) */
12944
12945         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12946 }
12947 #else /* old xxreadtoken */
12948 #define RETURN(token)   return lasttoken = token
12949 static int
12950 xxreadtoken(void)
12951 {
12952         int c;
12953
12954         if (tokpushback) {
12955                 tokpushback = 0;
12956                 return lasttoken;
12957         }
12958         setprompt_if(needprompt, 2);
12959         for (;;) {      /* until token or start of word found */
12960                 c = pgetc_eatbnl();
12961                 switch (c) {
12962                 case ' ': case '\t':
12963                 IF_ASH_ALIAS(case PEOA:)
12964                         continue;
12965                 case '#':
12966                         while ((c = pgetc()) != '\n' && c != PEOF)
12967                                 continue;
12968                         pungetc();
12969                         continue;
12970                 case '\n':
12971                         nlnoprompt();
12972                         RETURN(TNL);
12973                 case PEOF:
12974                         RETURN(TEOF);
12975                 case '&':
12976                         if (pgetc_eatbnl() == '&')
12977                                 RETURN(TAND);
12978                         pungetc();
12979                         RETURN(TBACKGND);
12980                 case '|':
12981                         if (pgetc_eatbnl() == '|')
12982                                 RETURN(TOR);
12983                         pungetc();
12984                         RETURN(TPIPE);
12985                 case ';':
12986                         if (pgetc_eatbnl() == ';')
12987                                 RETURN(TENDCASE);
12988                         pungetc();
12989                         RETURN(TSEMI);
12990                 case '(':
12991                         RETURN(TLP);
12992                 case ')':
12993                         RETURN(TRP);
12994                 }
12995                 break;
12996         }
12997         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12998 #undef RETURN
12999 }
13000 #endif /* old xxreadtoken */
13001
13002 static int
13003 readtoken(void)
13004 {
13005         int t;
13006         int kwd = checkkwd;
13007 #if DEBUG
13008         smallint alreadyseen = tokpushback;
13009 #endif
13010
13011 #if ENABLE_ASH_ALIAS
13012  top:
13013 #endif
13014
13015         t = xxreadtoken();
13016
13017         /*
13018          * eat newlines
13019          */
13020         if (kwd & CHKNL) {
13021                 while (t == TNL) {
13022                         parseheredoc();
13023                         t = xxreadtoken();
13024                 }
13025         }
13026
13027         if (t != TWORD || quoteflag) {
13028                 goto out;
13029         }
13030
13031         /*
13032          * check for keywords
13033          */
13034         if (kwd & CHKKWD) {
13035                 const char *const *pp;
13036
13037                 pp = findkwd(wordtext);
13038                 if (pp) {
13039                         lasttoken = t = pp - tokname_array;
13040                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
13041                         goto out;
13042                 }
13043         }
13044
13045         if (checkkwd & CHKALIAS) {
13046 #if ENABLE_ASH_ALIAS
13047                 struct alias *ap;
13048                 ap = lookupalias(wordtext, 1);
13049                 if (ap != NULL) {
13050                         if (*ap->val) {
13051                                 pushstring(ap->val, ap);
13052                         }
13053                         goto top;
13054                 }
13055 #endif
13056         }
13057  out:
13058         checkkwd = 0;
13059 #if DEBUG
13060         if (!alreadyseen)
13061                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13062         else
13063                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13064 #endif
13065         return t;
13066 }
13067
13068 static int
13069 peektoken(void)
13070 {
13071         int t;
13072
13073         t = readtoken();
13074         tokpushback = 1;
13075         return t;
13076 }
13077
13078 /*
13079  * Read and parse a command.  Returns NODE_EOF on end of file.
13080  * (NULL is a valid parse tree indicating a blank line.)
13081  */
13082 static union node *
13083 parsecmd(int interact)
13084 {
13085         tokpushback = 0;
13086         checkkwd = 0;
13087         heredoclist = 0;
13088         doprompt = interact;
13089         setprompt_if(doprompt, doprompt);
13090         needprompt = 0;
13091         return list(1);
13092 }
13093
13094 /*
13095  * Input any here documents.
13096  */
13097 static void
13098 parseheredoc(void)
13099 {
13100         struct heredoc *here;
13101         union node *n;
13102
13103         here = heredoclist;
13104         heredoclist = NULL;
13105
13106         while (here) {
13107                 tokpushback = 0;
13108                 setprompt_if(needprompt, 2);
13109                 if (here->here->type == NHERE)
13110                         readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
13111                 else
13112                         readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
13113                 n = stzalloc(sizeof(struct narg));
13114                 n->narg.type = NARG;
13115                 /*n->narg.next = NULL; - stzalloc did it */
13116                 n->narg.text = wordtext;
13117                 n->narg.backquote = backquotelist;
13118                 here->here->nhere.doc = n;
13119                 here = here->next;
13120         }
13121 }
13122
13123
13124 static const char *
13125 expandstr(const char *ps, int syntax_type)
13126 {
13127         union node n;
13128         int saveprompt;
13129         struct parsefile *file_stop = g_parsefile;
13130         volatile int saveint;
13131         struct jmploc *volatile savehandler = exception_handler;
13132         struct jmploc jmploc;
13133         const char *volatile result;
13134         int err;
13135
13136         /* XXX Fix (char *) cast. */
13137         setinputstring((char *)ps);
13138
13139         saveprompt = doprompt;
13140         doprompt = 0;
13141         result = ps;
13142
13143         SAVE_INT(saveint);
13144         err = setjmp(jmploc.loc);
13145         if (err)
13146                 goto out;
13147
13148         /* readtoken1() might die horribly.
13149          * Try a prompt with syntactically wrong command:
13150          * PS1='$(date "+%H:%M:%S) > '
13151          */
13152         exception_handler = &jmploc;
13153         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
13154
13155         n.narg.type = NARG;
13156         n.narg.next = NULL;
13157         n.narg.text = wordtext;
13158         n.narg.backquote = backquotelist;
13159
13160         /* expandarg() might fail too:
13161          * PS1='$((123+))'
13162          */
13163         expandarg(&n, NULL, EXP_QUOTED);
13164         result = stackblock();
13165
13166 out:
13167         exception_handler = savehandler;
13168         if (err && exception_type != EXERROR)
13169                 longjmp(exception_handler->loc, 1);
13170         RESTORE_INT(saveint);
13171
13172         doprompt = saveprompt;
13173         /* Try: PS1='`xxx(`' */
13174         unwindfiles(file_stop);
13175
13176         return result;
13177 }
13178
13179 static inline int
13180 parser_eof(void)
13181 {
13182         return tokpushback && lasttoken == TEOF;
13183 }
13184
13185 /*
13186  * Execute a command or commands contained in a string.
13187  */
13188 static int
13189 evalstring(char *s, int flags)
13190 {
13191         struct jmploc *volatile savehandler;
13192         struct jmploc jmploc;
13193         int ex;
13194
13195         union node *n;
13196         struct stackmark smark;
13197         int status;
13198
13199         s = sstrdup(s);
13200         setinputstring(s);
13201         setstackmark(&smark);
13202
13203         status = 0;
13204         /* On exception inside execution loop, we must popfile().
13205          * Try interactively:
13206          *      readonly a=a
13207          *      command eval "a=b"  # throws "is read only" error
13208          * "command BLTIN" is not supposed to abort (even in non-interactive use).
13209          * But if we skip popfile(), we hit EOF in eval's string, and exit.
13210          */
13211         savehandler = exception_handler;
13212         ex = setjmp(jmploc.loc);
13213         if (ex)
13214                 goto out;
13215         exception_handler = &jmploc;
13216
13217         while ((n = parsecmd(0)) != NODE_EOF) {
13218                 int i;
13219
13220                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13221                 if (n)
13222                         status = i;
13223                 popstackmark(&smark);
13224                 if (evalskip)
13225                         break;
13226         }
13227  out:
13228         popstackmark(&smark);
13229         popfile();
13230         stunalloc(s);
13231
13232         exception_handler = savehandler;
13233         if (ex)
13234                 longjmp(exception_handler->loc, ex);
13235
13236         return status;
13237 }
13238
13239 /*
13240  * The eval command.
13241  */
13242 static int FAST_FUNC
13243 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13244 {
13245         char *p;
13246         char *concat;
13247
13248         if (argv[1]) {
13249                 p = argv[1];
13250                 argv += 2;
13251                 if (argv[0]) {
13252                         STARTSTACKSTR(concat);
13253                         for (;;) {
13254                                 concat = stack_putstr(p, concat);
13255                                 p = *argv++;
13256                                 if (p == NULL)
13257                                         break;
13258                                 STPUTC(' ', concat);
13259                         }
13260                         STPUTC('\0', concat);
13261                         p = grabstackstr(concat);
13262                 }
13263                 return evalstring(p, flags & EV_TESTED);
13264         }
13265         return 0;
13266 }
13267
13268 /*
13269  * Read and execute commands.
13270  * "Top" is nonzero for the top level command loop;
13271  * it turns on prompting if the shell is interactive.
13272  */
13273 static int
13274 cmdloop(int top)
13275 {
13276         union node *n;
13277         struct stackmark smark;
13278         int inter;
13279         int status = 0;
13280         int numeof = 0;
13281
13282         TRACE(("cmdloop(%d) called\n", top));
13283         for (;;) {
13284                 int skip;
13285
13286                 setstackmark(&smark);
13287 #if JOBS
13288                 if (doing_jobctl)
13289                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13290 #endif
13291                 inter = 0;
13292                 if (iflag && top) {
13293                         inter++;
13294                         chkmail();
13295                 }
13296                 n = parsecmd(inter);
13297 #if DEBUG
13298                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13299                         showtree(n);
13300 #endif
13301                 if (n == NODE_EOF) {
13302                         if (!top || numeof >= 50)
13303                                 break;
13304                         if (!stoppedjobs()) {
13305                                 if (!Iflag)
13306                                         break;
13307                                 out2str("\nUse \"exit\" to leave shell.\n");
13308                         }
13309                         numeof++;
13310                 } else if (nflag == 0) {
13311                         int i;
13312
13313                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13314                         job_warning >>= 1;
13315                         numeof = 0;
13316                         i = evaltree(n, 0);
13317                         if (n)
13318                                 status = i;
13319                 }
13320                 popstackmark(&smark);
13321                 skip = evalskip;
13322
13323                 if (skip) {
13324                         evalskip &= ~SKIPFUNC;
13325                         break;
13326                 }
13327         }
13328         return status;
13329 }
13330
13331 /*
13332  * Take commands from a file.  To be compatible we should do a path
13333  * search for the file, which is necessary to find sub-commands.
13334  */
13335 static char *
13336 find_dot_file(char *name)
13337 {
13338         char *fullname;
13339         const char *path = pathval();
13340         struct stat statb;
13341
13342         /* don't try this for absolute or relative paths */
13343         if (strchr(name, '/'))
13344                 return name;
13345
13346         while ((fullname = path_advance(&path, name)) != NULL) {
13347                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13348                         /*
13349                          * Don't bother freeing here, since it will
13350                          * be freed by the caller.
13351                          */
13352                         return fullname;
13353                 }
13354                 if (fullname != name)
13355                         stunalloc(fullname);
13356         }
13357         /* not found in PATH */
13358
13359 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13360         return name;
13361 #else
13362         ash_msg_and_raise_error("%s: not found", name);
13363         /* NOTREACHED */
13364 #endif
13365 }
13366
13367 static int FAST_FUNC
13368 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13369 {
13370         /* "false; . empty_file; echo $?" should print 0, not 1: */
13371         int status = 0;
13372         char *fullname;
13373         char **argv;
13374         char *args_need_save;
13375         volatile struct shparam saveparam;
13376
13377 //???
13378 //      struct strlist *sp;
13379 //      for (sp = cmdenviron; sp; sp = sp->next)
13380 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13381
13382         nextopt(nullstr); /* handle possible "--" */
13383         argv = argptr;
13384
13385         if (!argv[0]) {
13386                 /* bash says: "bash: .: filename argument required" */
13387                 return 2; /* bash compat */
13388         }
13389
13390         /* This aborts if file isn't found, which is POSIXly correct.
13391          * bash returns exitcode 1 instead.
13392          */
13393         fullname = find_dot_file(argv[0]);
13394         argv++;
13395         args_need_save = argv[0];
13396         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13397                 int argc;
13398                 saveparam = shellparam;
13399                 shellparam.malloced = 0;
13400                 argc = 1;
13401                 while (argv[argc])
13402                         argc++;
13403                 shellparam.nparam = argc;
13404                 shellparam.p = argv;
13405         };
13406
13407         /* This aborts if file can't be opened, which is POSIXly correct.
13408          * bash returns exitcode 1 instead.
13409          */
13410         setinputfile(fullname, INPUT_PUSH_FILE);
13411         commandname = fullname;
13412         status = cmdloop(0);
13413         popfile();
13414
13415         if (args_need_save) {
13416                 freeparam(&shellparam);
13417                 shellparam = saveparam;
13418         };
13419
13420         return status;
13421 }
13422
13423 static int FAST_FUNC
13424 exitcmd(int argc UNUSED_PARAM, char **argv)
13425 {
13426         if (stoppedjobs())
13427                 return 0;
13428
13429         if (argv[1])
13430                 savestatus = number(argv[1]);
13431
13432         raise_exception(EXEXIT);
13433         /* NOTREACHED */
13434 }
13435
13436 /*
13437  * Read a file containing shell functions.
13438  */
13439 static void
13440 readcmdfile(char *name)
13441 {
13442         setinputfile(name, INPUT_PUSH_FILE);
13443         cmdloop(0);
13444         popfile();
13445 }
13446
13447
13448 /* ============ find_command inplementation */
13449
13450 /*
13451  * Resolve a command name.  If you change this routine, you may have to
13452  * change the shellexec routine as well.
13453  */
13454 static void
13455 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13456 {
13457         struct tblentry *cmdp;
13458         int idx;
13459         int prev;
13460         char *fullname;
13461         struct stat statb;
13462         int e;
13463         int updatetbl;
13464         struct builtincmd *bcmd;
13465
13466         /* If name contains a slash, don't use PATH or hash table */
13467         if (strchr(name, '/') != NULL) {
13468                 entry->u.index = -1;
13469                 if (act & DO_ABS) {
13470                         while (stat(name, &statb) < 0) {
13471 #ifdef SYSV
13472                                 if (errno == EINTR)
13473                                         continue;
13474 #endif
13475                                 entry->cmdtype = CMDUNKNOWN;
13476                                 return;
13477                         }
13478                 }
13479                 entry->cmdtype = CMDNORMAL;
13480                 return;
13481         }
13482
13483 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13484
13485         updatetbl = (path == pathval());
13486         if (!updatetbl) {
13487                 act |= DO_ALTPATH;
13488                 if (strstr(path, "%builtin") != NULL)
13489                         act |= DO_ALTBLTIN;
13490         }
13491
13492         /* If name is in the table, check answer will be ok */
13493         cmdp = cmdlookup(name, 0);
13494         if (cmdp != NULL) {
13495                 int bit;
13496
13497                 switch (cmdp->cmdtype) {
13498                 default:
13499 #if DEBUG
13500                         abort();
13501 #endif
13502                 case CMDNORMAL:
13503                         bit = DO_ALTPATH;
13504                         break;
13505                 case CMDFUNCTION:
13506                         bit = DO_NOFUNC;
13507                         break;
13508                 case CMDBUILTIN:
13509                         bit = DO_ALTBLTIN;
13510                         break;
13511                 }
13512                 if (act & bit) {
13513                         updatetbl = 0;
13514                         cmdp = NULL;
13515                 } else if (cmdp->rehash == 0)
13516                         /* if not invalidated by cd, we're done */
13517                         goto success;
13518         }
13519
13520         /* If %builtin not in path, check for builtin next */
13521         bcmd = find_builtin(name);
13522         if (bcmd) {
13523                 if (IS_BUILTIN_REGULAR(bcmd))
13524                         goto builtin_success;
13525                 if (act & DO_ALTPATH) {
13526                         if (!(act & DO_ALTBLTIN))
13527                                 goto builtin_success;
13528                 } else if (builtinloc <= 0) {
13529                         goto builtin_success;
13530                 }
13531         }
13532
13533 #if ENABLE_FEATURE_SH_STANDALONE
13534         {
13535                 int applet_no = find_applet_by_name(name);
13536                 if (applet_no >= 0) {
13537                         entry->cmdtype = CMDNORMAL;
13538                         entry->u.index = -2 - applet_no;
13539                         return;
13540                 }
13541         }
13542 #endif
13543
13544         /* We have to search path. */
13545         prev = -1;              /* where to start */
13546         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13547                 if (cmdp->cmdtype == CMDBUILTIN)
13548                         prev = builtinloc;
13549                 else
13550                         prev = cmdp->param.index;
13551         }
13552
13553         e = ENOENT;
13554         idx = -1;
13555  loop:
13556         while ((fullname = path_advance(&path, name)) != NULL) {
13557                 stunalloc(fullname);
13558                 /* NB: code below will still use fullname
13559                  * despite it being "unallocated" */
13560                 idx++;
13561                 if (pathopt) {
13562                         if (prefix(pathopt, "builtin")) {
13563                                 if (bcmd)
13564                                         goto builtin_success;
13565                                 continue;
13566                         }
13567                         if ((act & DO_NOFUNC)
13568                          || !prefix(pathopt, "func")
13569                         ) {     /* ignore unimplemented options */
13570                                 continue;
13571                         }
13572                 }
13573                 /* if rehash, don't redo absolute path names */
13574                 if (fullname[0] == '/' && idx <= prev) {
13575                         if (idx < prev)
13576                                 continue;
13577                         TRACE(("searchexec \"%s\": no change\n", name));
13578                         goto success;
13579                 }
13580                 while (stat(fullname, &statb) < 0) {
13581 #ifdef SYSV
13582                         if (errno == EINTR)
13583                                 continue;
13584 #endif
13585                         if (errno != ENOENT && errno != ENOTDIR)
13586                                 e = errno;
13587                         goto loop;
13588                 }
13589                 e = EACCES;     /* if we fail, this will be the error */
13590                 if (!S_ISREG(statb.st_mode))
13591                         continue;
13592                 if (pathopt) {          /* this is a %func directory */
13593                         stalloc(strlen(fullname) + 1);
13594                         /* NB: stalloc will return space pointed by fullname
13595                          * (because we don't have any intervening allocations
13596                          * between stunalloc above and this stalloc) */
13597                         readcmdfile(fullname);
13598                         cmdp = cmdlookup(name, 0);
13599                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13600                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13601                         stunalloc(fullname);
13602                         goto success;
13603                 }
13604                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13605                 if (!updatetbl) {
13606                         entry->cmdtype = CMDNORMAL;
13607                         entry->u.index = idx;
13608                         return;
13609                 }
13610                 INT_OFF;
13611                 cmdp = cmdlookup(name, 1);
13612                 cmdp->cmdtype = CMDNORMAL;
13613                 cmdp->param.index = idx;
13614                 INT_ON;
13615                 goto success;
13616         }
13617
13618         /* We failed.  If there was an entry for this command, delete it */
13619         if (cmdp && updatetbl)
13620                 delete_cmd_entry();
13621         if (act & DO_ERR) {
13622 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13623                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13624                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13625                         char *argv[3];
13626                         argv[0] = (char*) "command_not_found_handle";
13627                         argv[1] = name;
13628                         argv[2] = NULL;
13629                         evalfun(hookp->param.func, 2, argv, 0);
13630                         entry->cmdtype = CMDUNKNOWN;
13631                         return;
13632                 }
13633 #endif
13634                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13635         }
13636         entry->cmdtype = CMDUNKNOWN;
13637         return;
13638
13639  builtin_success:
13640         if (!updatetbl) {
13641                 entry->cmdtype = CMDBUILTIN;
13642                 entry->u.cmd = bcmd;
13643                 return;
13644         }
13645         INT_OFF;
13646         cmdp = cmdlookup(name, 1);
13647         cmdp->cmdtype = CMDBUILTIN;
13648         cmdp->param.cmd = bcmd;
13649         INT_ON;
13650  success:
13651         cmdp->rehash = 0;
13652         entry->cmdtype = cmdp->cmdtype;
13653         entry->u = cmdp->param;
13654 }
13655
13656
13657 /*
13658  * The trap builtin.
13659  */
13660 static int FAST_FUNC
13661 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13662 {
13663         char *action;
13664         char **ap;
13665         int signo, exitcode;
13666
13667         nextopt(nullstr);
13668         ap = argptr;
13669         if (!*ap) {
13670                 for (signo = 0; signo < NSIG; signo++) {
13671                         char *tr = trap_ptr[signo];
13672                         if (tr) {
13673                                 /* note: bash adds "SIG", but only if invoked
13674                                  * as "bash". If called as "sh", or if set -o posix,
13675                                  * then it prints short signal names.
13676                                  * We are printing short names: */
13677                                 out1fmt("trap -- %s %s\n",
13678                                                 single_quote(tr),
13679                                                 get_signame(signo));
13680                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13681                  * In this case, we will exit very soon, no need to free(). */
13682                                 /* if (trap_ptr != trap && tp[0]) */
13683                                 /*      free(tr); */
13684                         }
13685                 }
13686                 /*
13687                 if (trap_ptr != trap) {
13688                         free(trap_ptr);
13689                         trap_ptr = trap;
13690                 }
13691                 */
13692                 return 0;
13693         }
13694
13695         /* Why the second check?
13696          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13697          * In this case, NUM is signal no, not an action.
13698          */
13699         action = NULL;
13700         if (ap[1] && !is_number(ap[0]))
13701                 action = *ap++;
13702
13703         exitcode = 0;
13704         while (*ap) {
13705                 signo = get_signum(*ap);
13706                 if (signo < 0) {
13707                         /* Mimic bash message exactly */
13708                         ash_msg("%s: invalid signal specification", *ap);
13709                         exitcode = 1;
13710                         goto next;
13711                 }
13712                 INT_OFF;
13713                 if (action) {
13714                         if (LONE_DASH(action))
13715                                 action = NULL;
13716                         else {
13717                                 if (action[0]) /* not NULL and not "" and not "-" */
13718                                         may_have_traps = 1;
13719                                 action = ckstrdup(action);
13720                         }
13721                 }
13722                 free(trap[signo]);
13723                 trap[signo] = action;
13724                 if (signo != 0)
13725                         setsignal(signo);
13726                 INT_ON;
13727  next:
13728                 ap++;
13729         }
13730         return exitcode;
13731 }
13732
13733
13734 /* ============ Builtins */
13735
13736 #if ENABLE_ASH_HELP
13737 static int FAST_FUNC
13738 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13739 {
13740         unsigned col;
13741         unsigned i;
13742
13743         out1fmt(
13744                 "Built-in commands:\n"
13745                 "------------------\n");
13746         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13747                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13748                                         builtintab[i].name + 1);
13749                 if (col > 60) {
13750                         out1fmt("\n");
13751                         col = 0;
13752                 }
13753         }
13754 # if ENABLE_FEATURE_SH_STANDALONE
13755         {
13756                 const char *a = applet_names;
13757                 while (*a) {
13758                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13759                         if (col > 60) {
13760                                 out1fmt("\n");
13761                                 col = 0;
13762                         }
13763                         while (*a++ != '\0')
13764                                 continue;
13765                 }
13766         }
13767 # endif
13768         newline_and_flush(stdout);
13769         return EXIT_SUCCESS;
13770 }
13771 #endif
13772
13773 #if MAX_HISTORY
13774 static int FAST_FUNC
13775 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13776 {
13777         if (line_input_state)
13778                 show_history(line_input_state);
13779         return EXIT_SUCCESS;
13780 }
13781 #endif
13782
13783 /*
13784  * The export and readonly commands.
13785  */
13786 static int FAST_FUNC
13787 exportcmd(int argc UNUSED_PARAM, char **argv)
13788 {
13789         struct var *vp;
13790         char *name;
13791         const char *p;
13792         char **aptr;
13793         char opt;
13794         int flag;
13795         int flag_off;
13796
13797         /* "readonly" in bash accepts, but ignores -n.
13798          * We do the same: it saves a conditional in nextopt's param.
13799          */
13800         flag_off = 0;
13801         while ((opt = nextopt("np")) != '\0') {
13802                 if (opt == 'n')
13803                         flag_off = VEXPORT;
13804         }
13805         flag = VEXPORT;
13806         if (argv[0][0] == 'r') {
13807                 flag = VREADONLY;
13808                 flag_off = 0; /* readonly ignores -n */
13809         }
13810         flag_off = ~flag_off;
13811
13812         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13813         {
13814                 aptr = argptr;
13815                 name = *aptr;
13816                 if (name) {
13817                         do {
13818                                 p = strchr(name, '=');
13819                                 if (p != NULL) {
13820                                         p++;
13821                                 } else {
13822                                         vp = *findvar(hashvar(name), name);
13823                                         if (vp) {
13824                                                 vp->flags = ((vp->flags | flag) & flag_off);
13825                                                 continue;
13826                                         }
13827                                 }
13828                                 setvar(name, p, (flag & flag_off));
13829                         } while ((name = *++aptr) != NULL);
13830                         return 0;
13831                 }
13832         }
13833
13834         /* No arguments. Show the list of exported or readonly vars.
13835          * -n is ignored.
13836          */
13837         showvars(argv[0], flag, 0);
13838         return 0;
13839 }
13840
13841 /*
13842  * Delete a function if it exists.
13843  */
13844 static void
13845 unsetfunc(const char *name)
13846 {
13847         struct tblentry *cmdp;
13848
13849         cmdp = cmdlookup(name, 0);
13850         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13851                 delete_cmd_entry();
13852 }
13853
13854 /*
13855  * The unset builtin command.  We unset the function before we unset the
13856  * variable to allow a function to be unset when there is a readonly variable
13857  * with the same name.
13858  */
13859 static int FAST_FUNC
13860 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13861 {
13862         char **ap;
13863         int i;
13864         int flag = 0;
13865
13866         while ((i = nextopt("vf")) != 0) {
13867                 flag = i;
13868         }
13869
13870         for (ap = argptr; *ap; ap++) {
13871                 if (flag != 'f') {
13872                         unsetvar(*ap);
13873                         continue;
13874                 }
13875                 if (flag != 'v')
13876                         unsetfunc(*ap);
13877         }
13878         return 0;
13879 }
13880
13881 static const unsigned char timescmd_str[] ALIGN1 = {
13882         ' ',  offsetof(struct tms, tms_utime),
13883         '\n', offsetof(struct tms, tms_stime),
13884         ' ',  offsetof(struct tms, tms_cutime),
13885         '\n', offsetof(struct tms, tms_cstime),
13886         0
13887 };
13888 static int FAST_FUNC
13889 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13890 {
13891         unsigned clk_tck;
13892         const unsigned char *p;
13893         struct tms buf;
13894
13895         clk_tck = bb_clk_tck();
13896
13897         times(&buf);
13898         p = timescmd_str;
13899         do {
13900                 unsigned sec, frac;
13901                 unsigned long t;
13902                 t = *(clock_t *)(((char *) &buf) + p[1]);
13903                 sec = t / clk_tck;
13904                 frac = t % clk_tck;
13905                 out1fmt("%um%u.%03us%c",
13906                         sec / 60, sec % 60,
13907                         (frac * 1000) / clk_tck,
13908                         p[0]);
13909                 p += 2;
13910         } while (*p);
13911
13912         return 0;
13913 }
13914
13915 #if ENABLE_FEATURE_SH_MATH
13916 /*
13917  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13918  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13919  *
13920  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13921  */
13922 static int FAST_FUNC
13923 letcmd(int argc UNUSED_PARAM, char **argv)
13924 {
13925         arith_t i;
13926
13927         argv++;
13928         if (!*argv)
13929                 ash_msg_and_raise_error("expression expected");
13930         do {
13931                 i = ash_arith(*argv);
13932         } while (*++argv);
13933
13934         return !i;
13935 }
13936 #endif
13937
13938 /*
13939  * The read builtin. Options:
13940  *      -r              Do not interpret '\' specially
13941  *      -s              Turn off echo (tty only)
13942  *      -n NCHARS       Read NCHARS max
13943  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13944  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13945  *      -u FD           Read from given FD instead of fd 0
13946  *      -d DELIM        End on DELIM char, not newline
13947  * This uses unbuffered input, which may be avoidable in some cases.
13948  * TODO: bash also has:
13949  *      -a ARRAY        Read into array[0],[1],etc
13950  *      -e              Use line editing (tty only)
13951  */
13952 static int FAST_FUNC
13953 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13954 {
13955         struct builtin_read_params params;
13956         const char *r;
13957         int i;
13958
13959         memset(&params, 0, sizeof(params));
13960
13961         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13962                 switch (i) {
13963                 case 'p':
13964                         params.opt_p = optionarg;
13965                         break;
13966                 case 'n':
13967                         params.opt_n = optionarg;
13968                         break;
13969                 case 's':
13970                         params.read_flags |= BUILTIN_READ_SILENT;
13971                         break;
13972                 case 't':
13973                         params.opt_t = optionarg;
13974                         break;
13975                 case 'r':
13976                         params.read_flags |= BUILTIN_READ_RAW;
13977                         break;
13978                 case 'u':
13979                         params.opt_u = optionarg;
13980                         break;
13981 #if BASH_READ_D
13982                 case 'd':
13983                         params.opt_d = optionarg;
13984                         break;
13985 #endif
13986                 default:
13987                         break;
13988                 }
13989         }
13990
13991         params.argv = argptr;
13992         params.setvar = setvar0;
13993         params.ifs = bltinlookup("IFS"); /* can be NULL */
13994
13995         /* "read -s" needs to save/restore termios, can't allow ^C
13996          * to jump out of it.
13997          */
13998  again:
13999         INT_OFF;
14000         r = shell_builtin_read(&params);
14001         INT_ON;
14002
14003         if ((uintptr_t)r == 1 && errno == EINTR) {
14004                 /* To get SIGCHLD: sleep 1 & read x; echo $x
14005                  * Correct behavior is to not exit "read"
14006                  */
14007                 if (pending_sig == 0)
14008                         goto again;
14009         }
14010
14011         if ((uintptr_t)r > 1)
14012                 ash_msg_and_raise_error(r);
14013
14014         return (uintptr_t)r;
14015 }
14016
14017 static int FAST_FUNC
14018 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14019 {
14020         static const char permuser[3] ALIGN1 = "ogu";
14021
14022         mode_t mask;
14023         int symbolic_mode = 0;
14024
14025         while (nextopt("S") != '\0') {
14026                 symbolic_mode = 1;
14027         }
14028
14029         INT_OFF;
14030         mask = umask(0);
14031         umask(mask);
14032         INT_ON;
14033
14034         if (*argptr == NULL) {
14035                 if (symbolic_mode) {
14036                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
14037                         char *p = buf;
14038                         int i;
14039
14040                         i = 2;
14041                         for (;;) {
14042                                 *p++ = ',';
14043                                 *p++ = permuser[i];
14044                                 *p++ = '=';
14045                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
14046                                 if (!(mask & 0400)) *p++ = 'r';
14047                                 if (!(mask & 0200)) *p++ = 'w';
14048                                 if (!(mask & 0100)) *p++ = 'x';
14049                                 mask <<= 3;
14050                                 if (--i < 0)
14051                                         break;
14052                         }
14053                         *p = '\0';
14054                         puts(buf + 1);
14055                 } else {
14056                         out1fmt("%04o\n", mask);
14057                 }
14058         } else {
14059                 char *modestr = *argptr;
14060                 /* numeric umasks are taken as-is */
14061                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
14062                 if (!isdigit(modestr[0]))
14063                         mask ^= 0777;
14064                 mask = bb_parse_mode(modestr, mask);
14065                 if ((unsigned)mask > 0777) {
14066                         ash_msg_and_raise_error("illegal mode: %s", modestr);
14067                 }
14068                 if (!isdigit(modestr[0]))
14069                         mask ^= 0777;
14070                 umask(mask);
14071         }
14072         return 0;
14073 }
14074
14075 static int FAST_FUNC
14076 ulimitcmd(int argc UNUSED_PARAM, char **argv)
14077 {
14078         return shell_builtin_ulimit(argv);
14079 }
14080
14081 /* ============ main() and helpers */
14082
14083 /*
14084  * Called to exit the shell.
14085  */
14086 static void
14087 exitshell(void)
14088 {
14089         struct jmploc loc;
14090         char *p;
14091
14092 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
14093         if (line_input_state)
14094                 save_history(line_input_state);
14095 #endif
14096         savestatus = exitstatus;
14097         TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus));
14098         if (setjmp(loc.loc))
14099                 goto out;
14100         exception_handler = &loc;
14101         p = trap[0];
14102         if (p) {
14103                 trap[0] = NULL;
14104                 evalskip = 0;
14105                 evalstring(p, 0);
14106                 /*free(p); - we'll exit soon */
14107         }
14108  out:
14109         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
14110          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
14111          */
14112         setjobctl(0);
14113         flush_stdout_stderr();
14114         _exit(savestatus);
14115         /* NOTREACHED */
14116 }
14117
14118 /* Don't inline: conserve stack of caller from having our locals too */
14119 static NOINLINE void
14120 init(void)
14121 {
14122         /* we will never free this */
14123         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
14124         basepf.linno = 1;
14125
14126         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
14127         setsignal(SIGCHLD);
14128
14129         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
14130          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
14131          */
14132         signal(SIGHUP, SIG_DFL);
14133
14134         {
14135                 char **envp;
14136                 const char *p;
14137
14138                 initvar();
14139                 for (envp = environ; envp && *envp; envp++) {
14140 /* Used to have
14141  *                      p = endofname(*envp);
14142  *                      if (p != *envp && *p == '=') {
14143  * here to weed out badly-named variables, but this breaks
14144  * scenarios where people do want them passed to children:
14145  * import os
14146  * os.environ["test-test"]="test"
14147  * if os.fork() == 0:
14148  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
14149  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
14150  */
14151                         if (strchr(*envp, '=')) {
14152                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
14153                         }
14154                 }
14155
14156                 setvareq((char*)defifsvar, VTEXTFIXED);
14157                 setvareq((char*)defoptindvar, VTEXTFIXED);
14158
14159                 setvar0("PPID", utoa(getppid()));
14160 #if BASH_SHLVL_VAR
14161                 p = lookupvar("SHLVL");
14162                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
14163 #endif
14164 #if BASH_HOSTNAME_VAR
14165                 if (!lookupvar("HOSTNAME")) {
14166                         struct utsname uts;
14167                         uname(&uts);
14168                         setvar0("HOSTNAME", uts.nodename);
14169                 }
14170 #endif
14171                 p = lookupvar("PWD");
14172                 if (p) {
14173                         struct stat st1, st2;
14174                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
14175                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
14176                         ) {
14177                                 p = NULL;
14178                         }
14179                 }
14180                 setpwd(p, 0);
14181         }
14182 }
14183
14184
14185 //usage:#define ash_trivial_usage
14186 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
14187 //usage:#define ash_full_usage "\n\n"
14188 //usage:        "Unix shell interpreter"
14189
14190 /*
14191  * Process the shell command line arguments.
14192  */
14193 static int
14194 procargs(char **argv)
14195 {
14196         int i;
14197         const char *xminusc;
14198         char **xargv;
14199         int login_sh;
14200
14201         xargv = argv;
14202         login_sh = xargv[0] && xargv[0][0] == '-';
14203 #if NUM_SCRIPTS > 0
14204         if (minusc)
14205                 goto setarg0;
14206 #endif
14207         arg0 = xargv[0];
14208         /* if (xargv[0]) - mmm, this is always true! */
14209                 xargv++;
14210         argptr = xargv;
14211         for (i = 0; i < NOPTS; i++)
14212                 optlist[i] = 2;
14213         if (options(&login_sh)) {
14214                 /* it already printed err message */
14215                 raise_exception(EXERROR);
14216         }
14217         xargv = argptr;
14218         xminusc = minusc;
14219         if (*xargv == NULL) {
14220                 if (xminusc)
14221                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
14222                 sflag = 1;
14223         }
14224         if (iflag == 2 /* no explicit -i given */
14225          && sflag == 1 /* -s given (or implied) */
14226          && !minusc /* bash compat: ash -sc 'echo $-' is not interactive (dash is) */
14227          && isatty(0) && isatty(1) /* we are on tty */
14228         ) {
14229                 iflag = 1;
14230         }
14231         if (mflag == 2)
14232                 mflag = iflag;
14233         for (i = 0; i < NOPTS; i++)
14234                 if (optlist[i] == 2)
14235                         optlist[i] = 0;
14236 #if DEBUG == 2
14237         debug = 1;
14238 #endif
14239         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14240         if (xminusc) {
14241                 minusc = *xargv++;
14242                 if (*xargv)
14243                         goto setarg0;
14244         } else if (!sflag) {
14245                 setinputfile(*xargv, 0);
14246  setarg0:
14247                 arg0 = *xargv++;
14248                 commandname = arg0;
14249         }
14250
14251         shellparam.p = xargv;
14252 #if ENABLE_ASH_GETOPTS
14253         shellparam.optind = 1;
14254         shellparam.optoff = -1;
14255 #endif
14256         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14257         while (*xargv) {
14258                 shellparam.nparam++;
14259                 xargv++;
14260         }
14261         optschanged();
14262
14263         return login_sh;
14264 }
14265
14266 /*
14267  * Read /etc/profile, ~/.profile, $ENV.
14268  */
14269 static void
14270 read_profile(const char *name)
14271 {
14272         name = expandstr(name, DQSYNTAX);
14273         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14274                 return;
14275         cmdloop(0);
14276         popfile();
14277 }
14278
14279 /*
14280  * This routine is called when an error or an interrupt occurs in an
14281  * interactive shell and control is returned to the main command loop.
14282  * (In dash, this function is auto-generated by build machinery).
14283  */
14284 static void
14285 reset(void)
14286 {
14287         /* from eval.c: */
14288         evalskip = 0;
14289         loopnest = 0;
14290         if (savestatus >= 0) {
14291                 exitstatus = savestatus;
14292                 savestatus = -1;
14293         }
14294
14295         /* from expand.c: */
14296         ifsfree();
14297
14298         /* from input.c: */
14299         g_parsefile->left_in_buffer = 0;
14300         g_parsefile->left_in_line = 0;      /* clear input buffer */
14301         popallfiles();
14302
14303         /* from redir.c: */
14304         unwindredir(NULL);
14305
14306         /* from var.c: */
14307         unwindlocalvars(NULL);
14308 }
14309
14310 #if PROFILE
14311 static short profile_buf[16384];
14312 extern int etext();
14313 #endif
14314
14315 /*
14316  * Main routine.  We initialize things, parse the arguments, execute
14317  * profiles if we're a login shell, and then call cmdloop to execute
14318  * commands.  The setjmp call sets up the location to jump to when an
14319  * exception occurs.  When an exception occurs the variable "state"
14320  * is used to figure out how far we had gotten.
14321  */
14322 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14323 #if NUM_SCRIPTS > 0
14324 int ash_main(int argc, char **argv)
14325 #else
14326 int ash_main(int argc UNUSED_PARAM, char **argv)
14327 #endif
14328 /* note: 'argc' is used only if embedded scripts are enabled */
14329 {
14330         volatile smallint state;
14331         struct jmploc jmploc;
14332         struct stackmark smark;
14333         int login_sh;
14334
14335         /* Initialize global data */
14336         INIT_G_misc();
14337         INIT_G_memstack();
14338         INIT_G_var();
14339 #if ENABLE_ASH_ALIAS
14340         INIT_G_alias();
14341 #endif
14342         INIT_G_cmdtable();
14343
14344 #if PROFILE
14345         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14346 #endif
14347
14348         state = 0;
14349         if (setjmp(jmploc.loc)) {
14350                 smallint e;
14351                 smallint s;
14352
14353                 reset();
14354
14355                 e = exception_type;
14356                 s = state;
14357                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14358                         exitshell();
14359                 }
14360                 if (e == EXINT) {
14361                         newline_and_flush(stderr);
14362                 }
14363
14364                 popstackmark(&smark);
14365                 FORCE_INT_ON; /* enable interrupts */
14366                 if (s == 1)
14367                         goto state1;
14368                 if (s == 2)
14369                         goto state2;
14370                 if (s == 3)
14371                         goto state3;
14372                 goto state4;
14373         }
14374         exception_handler = &jmploc;
14375         rootpid = getpid();
14376
14377         init();
14378         setstackmark(&smark);
14379
14380 #if NUM_SCRIPTS > 0
14381         if (argc < 0)
14382                 /* Non-NULL minusc tells procargs that an embedded script is being run */
14383                 minusc = get_script_content(-argc - 1);
14384 #endif
14385         login_sh = procargs(argv);
14386 #if DEBUG
14387         TRACE(("Shell args: "));
14388         trace_puts_args(argv);
14389 #endif
14390
14391         if (login_sh) {
14392                 const char *hp;
14393
14394                 state = 1;
14395                 read_profile("/etc/profile");
14396  state1:
14397                 state = 2;
14398                 hp = lookupvar("HOME");
14399                 if (hp)
14400                         read_profile("$HOME/.profile");
14401         }
14402  state2:
14403         state = 3;
14404         if (
14405 #ifndef linux
14406          getuid() == geteuid() && getgid() == getegid() &&
14407 #endif
14408          iflag
14409         ) {
14410                 const char *shinit = lookupvar("ENV");
14411                 if (shinit != NULL && *shinit != '\0')
14412                         read_profile(shinit);
14413         }
14414         popstackmark(&smark);
14415  state3:
14416         state = 4;
14417         if (minusc) {
14418                 /* evalstring pushes parsefile stack.
14419                  * Ensure we don't falsely claim that 0 (stdin)
14420                  * is one of stacked source fds.
14421                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14422
14423                 // if (!sflag) g_parsefile->pf_fd = -1;
14424                 // ^^ not necessary since now we special-case fd 0
14425                 // in save_fd_on_redirect()
14426
14427                 // dash: evalstring(minusc, sflag ? 0 : EV_EXIT);
14428                 // The above makes
14429                 //  ash -sc 'echo $-'
14430                 // continue reading input from stdin after running 'echo'.
14431                 // bash does not do this: it prints "hBcs" and exits.
14432                 evalstring(minusc, EV_EXIT);
14433         }
14434
14435         if (sflag || minusc == NULL) {
14436 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14437                 if (iflag) {
14438                         const char *hp = lookupvar("HISTFILE");
14439                         if (!hp) {
14440                                 hp = lookupvar("HOME");
14441                                 if (hp) {
14442                                         INT_OFF;
14443                                         hp = concat_path_file(hp, ".ash_history");
14444                                         setvar0("HISTFILE", hp);
14445                                         free((char*)hp);
14446                                         INT_ON;
14447                                         hp = lookupvar("HISTFILE");
14448                                 }
14449                         }
14450                         if (hp)
14451                                 line_input_state->hist_file = hp;
14452 # if ENABLE_FEATURE_SH_HISTFILESIZE
14453                         hp = lookupvar("HISTFILESIZE");
14454                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14455 # endif
14456                 }
14457 #endif
14458  state4: /* XXX ??? - why isn't this before the "if" statement */
14459                 cmdloop(1);
14460         }
14461 #if PROFILE
14462         monitor(0);
14463 #endif
14464 #ifdef GPROF
14465         {
14466                 extern void _mcleanup(void);
14467                 _mcleanup();
14468         }
14469 #endif
14470         TRACE(("End of main reached\n"));
14471         exitshell();
14472         /* NOTREACHED */
14473 }
14474
14475
14476 /*-
14477  * Copyright (c) 1989, 1991, 1993, 1994
14478  *      The Regents of the University of California.  All rights reserved.
14479  *
14480  * This code is derived from software contributed to Berkeley by
14481  * Kenneth Almquist.
14482  *
14483  * Redistribution and use in source and binary forms, with or without
14484  * modification, are permitted provided that the following conditions
14485  * are met:
14486  * 1. Redistributions of source code must retain the above copyright
14487  *    notice, this list of conditions and the following disclaimer.
14488  * 2. Redistributions in binary form must reproduce the above copyright
14489  *    notice, this list of conditions and the following disclaimer in the
14490  *    documentation and/or other materials provided with the distribution.
14491  * 3. Neither the name of the University nor the names of its contributors
14492  *    may be used to endorse or promote products derived from this software
14493  *    without specific prior written permission.
14494  *
14495  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14496  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14497  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14498  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14499  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14500  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14501  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14502  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14503  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14504  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14505  * SUCH DAMAGE.
14506  */