ash: ensure variables are fully initialised when unset
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_BASH_SOURCE_CURDIR
55 //config:       bool "'source' and '.' builtins search current directory after $PATH"
56 //config:       default n   # do not encourage non-standard behavior
57 //config:       depends on ASH_BASH_COMPAT
58 //config:       help
59 //config:       This is not compliant with standards. Avoid if possible.
60 //config:
61 //config:config ASH_BASH_NOT_FOUND_HOOK
62 //config:       bool "command_not_found_handle hook support"
63 //config:       default y
64 //config:       depends on ASH_BASH_COMPAT
65 //config:       help
66 //config:       Enable support for the 'command_not_found_handle' hook function,
67 //config:       from GNU bash, which allows for alternative command not found
68 //config:       handling.
69 //config:
70 //config:config ASH_JOB_CONTROL
71 //config:       bool "Job control"
72 //config:       default y
73 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
74 //config:
75 //config:config ASH_ALIAS
76 //config:       bool "Alias support"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:
80 //config:config ASH_RANDOM_SUPPORT
81 //config:       bool "Pseudorandom generator and $RANDOM variable"
82 //config:       default y
83 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
84 //config:       help
85 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
86 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
87 //config:       You can reset the generator by using a specified start value.
88 //config:       After "unset RANDOM" the generator will switch off and this
89 //config:       variable will no longer have special treatment.
90 //config:
91 //config:config ASH_EXPAND_PRMT
92 //config:       bool "Expand prompt string"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       $PS# may contain volatile content, such as backquote commands.
97 //config:       This option recreates the prompt string from the environment
98 //config:       variable each time it is displayed.
99 //config:
100 //config:config ASH_IDLE_TIMEOUT
101 //config:       bool "Idle timeout variable $TMOUT"
102 //config:       default y
103 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
104 //config:       help
105 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
106 //config:
107 //config:config ASH_MAIL
108 //config:       bool "Check for new mail in interactive shell"
109 //config:       default y
110 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
111 //config:       help
112 //config:       Enable "check for new mail" function:
113 //config:       if set, $MAIL file and $MAILPATH list of files
114 //config:       are checked for mtime changes, and "you have mail"
115 //config:       message is printed if change is detected.
116 //config:
117 //config:config ASH_ECHO
118 //config:       bool "echo builtin"
119 //config:       default y
120 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
121 //config:
122 //config:config ASH_PRINTF
123 //config:       bool "printf builtin"
124 //config:       default y
125 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
126 //config:
127 //config:config ASH_TEST
128 //config:       bool "test builtin"
129 //config:       default y
130 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
131 //config:
132 //config:config ASH_HELP
133 //config:       bool "help builtin"
134 //config:       default y
135 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
136 //config:
137 //config:config ASH_GETOPTS
138 //config:       bool "getopts builtin"
139 //config:       default y
140 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
141 //config:
142 //config:config ASH_CMDCMD
143 //config:       bool "command builtin"
144 //config:       default y
145 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
146 //config:       help
147 //config:       Enable support for the 'command' builtin, which allows
148 //config:       you to run the specified command or builtin,
149 //config:       even when there is a function with the same name.
150 //config:
151 //config:config ASH_EMBEDDED_SCRIPTS
152 //config:       bool "Embed scripts in the binary"
153 //config:       default y
154 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
155 //config:       help
156 //config:       Allow scripts to be compressed and embedded in the busybox
157 //config:       binary. The scripts should be placed in the 'embed' directory
158 //config:       at build time. Like applets, scripts can be run as
159 //config:       'busybox SCRIPT ...' or by linking their name to the binary.
160 //config:
161 //config:endif # ash options
162
163 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
164 //                      APPLET_ODDNAME:name  main location    suid_type     help
165 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
166 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
167
168 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
169 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
170 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
171 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
172
173 /*
174  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
175  * DEBUG=2 to compile in and turn on debugging.
176  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
177  * debugging info is written to ./trace, quit signal generates core dump.
178  */
179 #define DEBUG 0
180 /* Tweak debug output verbosity here */
181 #define DEBUG_TIME 0
182 #define DEBUG_PID 1
183 #define DEBUG_SIG 1
184 #define DEBUG_INTONOFF 0
185
186 #define PROFILE 0
187
188 #define JOBS ENABLE_ASH_JOB_CONTROL
189
190 #include <fnmatch.h>
191 #include <sys/times.h>
192 #include <sys/utsname.h> /* for setting $HOSTNAME */
193 #include "busybox.h" /* for applet_names */
194 #if ENABLE_ASH_EMBEDDED_SCRIPTS
195 # include "embedded_scripts.h"
196 #else
197 # define NUM_SCRIPTS 0
198 #endif
199
200 /* So far, all bash compat is controlled by one config option */
201 /* Separate defines document which part of code implements what */
202 /* function keyword */
203 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
204 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
205 /* &>file */
206 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
207 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
208 /* $'...' */
209 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
210 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
211 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
212 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
213 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
214 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
215 /* BASH_TEST2: [[ EXPR ]]
216  * Status of [[ support:
217  * We replace && and || with -a and -o
218  * TODO:
219  * singleword+noglob expansion:
220  *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
221  *   [[ /bin/n* ]]; echo 0:$?
222  * -a/-o are not AND/OR ops! (they are just strings)
223  * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
224  * = is glob match operator, not equality operator: STR = GLOB
225  * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
226  * == same as =
227  * add =~ regex match operator: STR =~ REGEX
228  */
229 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
230 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
231 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
232 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
233 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
234 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
235 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
236 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
237
238 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
239 /* Bionic at least up to version 24 has no glob() */
240 # undef  ENABLE_ASH_INTERNAL_GLOB
241 # define ENABLE_ASH_INTERNAL_GLOB 1
242 #endif
243
244 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
245 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
246 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
247 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
248 # error glob() should unbackslash them and match. uClibc does not unbackslash,
249 # error fails to match dirname, subsequently not expanding <pattern> in it.
250 // Testcase:
251 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
252 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
253 #endif
254
255 #if !ENABLE_ASH_INTERNAL_GLOB
256 # include <glob.h>
257 #endif
258
259 #include "unicode.h"
260 #include "shell_common.h"
261 #if ENABLE_FEATURE_SH_MATH
262 # include "math.h"
263 #else
264 typedef long arith_t;
265 # define ARITH_FMT "%ld"
266 #endif
267 #if ENABLE_ASH_RANDOM_SUPPORT
268 # include "random.h"
269 #else
270 # define CLEAR_RANDOM_T(rnd) ((void)0)
271 #endif
272
273 #include "NUM_APPLETS.h"
274 #if NUM_APPLETS == 1
275 /* STANDALONE does not make sense, and won't compile */
276 # undef CONFIG_FEATURE_SH_STANDALONE
277 # undef ENABLE_FEATURE_SH_STANDALONE
278 # undef IF_FEATURE_SH_STANDALONE
279 # undef IF_NOT_FEATURE_SH_STANDALONE
280 # define ENABLE_FEATURE_SH_STANDALONE 0
281 # define IF_FEATURE_SH_STANDALONE(...)
282 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
283 #endif
284
285 #ifndef F_DUPFD_CLOEXEC
286 # define F_DUPFD_CLOEXEC F_DUPFD
287 #endif
288 #ifndef O_CLOEXEC
289 # define O_CLOEXEC 0
290 #endif
291 #ifndef PIPE_BUF
292 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
293 #endif
294
295 #if !BB_MMU
296 # error "Do not even bother, ash will not run on NOMMU machine"
297 #endif
298
299 /* We use a trick to have more optimized code (fewer pointer reloads):
300  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
301  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
302  * This way, compiler in ash.c knows the pointer can not change.
303  *
304  * However, this may break on weird arches or toolchains. In this case,
305  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
306  * this optimization.
307  */
308 #ifndef BB_GLOBAL_CONST
309 # define BB_GLOBAL_CONST const
310 #endif
311
312
313 /* ============ Hash table sizes. Configurable. */
314
315 #define VTABSIZE 39
316 #define ATABSIZE 39
317 #define CMDTABLESIZE 31         /* should be prime */
318
319
320 /* ============ Shell options */
321
322 static const char *const optletters_optnames[] = {
323         "e"   "errexit",
324         "f"   "noglob",
325         "I"   "ignoreeof",
326         "i"   "interactive",
327         "m"   "monitor",
328         "n"   "noexec",
329         "s"   "stdin",
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
346 #define optletters(n)  optletters_optnames[n][0]
347 #define optnames(n)   (optletters_optnames[n] + 1)
348
349 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
350
351
352 /* ============ Misc data */
353
354 #define msg_illnum "Illegal number: %s"
355
356 /*
357  * We enclose jmp_buf in a structure so that we can declare pointers to
358  * jump locations.  The global variable handler contains the location to
359  * jump to when an exception occurs, and the global variable exception_type
360  * contains a code identifying the exception.  To implement nested
361  * exception handlers, the user should save the value of handler on entry
362  * to an inner scope, set handler to point to a jmploc structure for the
363  * inner scope, and restore handler on exit from the scope.
364  */
365 struct jmploc {
366         jmp_buf loc;
367 };
368
369 struct globals_misc {
370         uint8_t exitstatus;     /* exit status of last command */
371         uint8_t back_exitstatus;/* exit status of backquoted command */
372         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
373         int rootpid;            /* pid of main shell */
374         /* shell level: 0 for the main shell, 1 for its children, and so on */
375         int shlvl;
376 #define rootshell (!shlvl)
377         int errlinno;
378
379         char *minusc;  /* argument to -c option */
380
381         char *curdir; // = nullstr;     /* current working directory */
382         char *physdir; // = nullstr;    /* physical working directory */
383
384         char *arg0; /* value of $0 */
385
386         struct jmploc *exception_handler;
387
388         volatile int suppress_int; /* counter */
389         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
390         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
391         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
392         smallint exception_type; /* kind of exception (0..5) */
393         /* exceptions */
394 #define EXINT 0         /* SIGINT received */
395 #define EXERROR 1       /* a generic error */
396 #define EXEXIT 4        /* exit the shell */
397
398         char nullstr[1];        /* zero length string */
399
400         char optlist[NOPTS];
401 #define eflag optlist[0]
402 #define fflag optlist[1]
403 #define Iflag optlist[2]
404 #define iflag optlist[3]
405 #define mflag optlist[4]
406 #define nflag optlist[5]
407 #define sflag optlist[6]
408 #define xflag optlist[7]
409 #define vflag optlist[8]
410 #define Cflag optlist[9]
411 #define aflag optlist[10]
412 #define bflag optlist[11]
413 #define uflag optlist[12]
414 #define viflag optlist[13]
415 #if BASH_PIPEFAIL
416 # define pipefail optlist[14]
417 #else
418 # define pipefail 0
419 #endif
420 #if DEBUG
421 # define nolog optlist[14 + BASH_PIPEFAIL]
422 # define debug optlist[15 + BASH_PIPEFAIL]
423 #endif
424
425         /* trap handler commands */
426         /*
427          * Sigmode records the current value of the signal handlers for the various
428          * modes.  A value of zero means that the current handler is not known.
429          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
430          */
431         char sigmode[NSIG - 1];
432 #define S_DFL      1            /* default signal handling (SIG_DFL) */
433 #define S_CATCH    2            /* signal is caught */
434 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
435 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
436
437         /* indicates specified signal received */
438         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
439         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
440         char *trap[NSIG];
441         char **trap_ptr;        /* used only by "trap hack" */
442
443         /* Rarely referenced stuff */
444 #if ENABLE_ASH_RANDOM_SUPPORT
445         random_t random_gen;
446 #endif
447         pid_t backgndpid;        /* pid of last background process */
448 };
449 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
450 #define G_misc (*ash_ptr_to_globals_misc)
451 #define exitstatus        (G_misc.exitstatus )
452 #define back_exitstatus   (G_misc.back_exitstatus )
453 #define job_warning       (G_misc.job_warning)
454 #define rootpid     (G_misc.rootpid    )
455 #define shlvl       (G_misc.shlvl      )
456 #define errlinno    (G_misc.errlinno   )
457 #define minusc      (G_misc.minusc     )
458 #define curdir      (G_misc.curdir     )
459 #define physdir     (G_misc.physdir    )
460 #define arg0        (G_misc.arg0       )
461 #define exception_handler (G_misc.exception_handler)
462 #define exception_type    (G_misc.exception_type   )
463 #define suppress_int      (G_misc.suppress_int     )
464 #define pending_int       (G_misc.pending_int      )
465 #define got_sigchld       (G_misc.got_sigchld      )
466 #define pending_sig       (G_misc.pending_sig      )
467 #define nullstr     (G_misc.nullstr    )
468 #define optlist     (G_misc.optlist    )
469 #define sigmode     (G_misc.sigmode    )
470 #define gotsig      (G_misc.gotsig     )
471 #define may_have_traps    (G_misc.may_have_traps   )
472 #define trap        (G_misc.trap       )
473 #define trap_ptr    (G_misc.trap_ptr   )
474 #define random_gen  (G_misc.random_gen )
475 #define backgndpid  (G_misc.backgndpid )
476 #define INIT_G_misc() do { \
477         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
478         barrier(); \
479         curdir = nullstr; \
480         physdir = nullstr; \
481         trap_ptr = trap; \
482 } while (0)
483
484
485 /* ============ DEBUG */
486 #if DEBUG
487 static void trace_printf(const char *fmt, ...);
488 static void trace_vprintf(const char *fmt, va_list va);
489 # define TRACE(param)    trace_printf param
490 # define TRACEV(param)   trace_vprintf param
491 # define close(fd) do { \
492         int dfd = (fd); \
493         if (close(dfd) < 0) \
494                 bb_error_msg("bug on %d: closing %d(0x%x)", \
495                         __LINE__, dfd, dfd); \
496 } while (0)
497 #else
498 # define TRACE(param)
499 # define TRACEV(param)
500 #endif
501
502
503 /* ============ Utility functions */
504 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
505 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
506
507 static int
508 isdigit_str9(const char *str)
509 {
510         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
511         while (--maxlen && isdigit(*str))
512                 str++;
513         return (*str == '\0');
514 }
515
516 static const char *
517 var_end(const char *var)
518 {
519         while (*var)
520                 if (*var++ == '=')
521                         break;
522         return var;
523 }
524
525
526 /* ============ Interrupts / exceptions */
527
528 static void exitshell(void) NORETURN;
529
530 /*
531  * These macros allow the user to suspend the handling of interrupt signals
532  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
533  * much more efficient and portable.  (But hacking the kernel is so much
534  * more fun than worrying about efficiency and portability. :-))
535  */
536 #if DEBUG_INTONOFF
537 # define INT_OFF do { \
538         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
539         suppress_int++; \
540         barrier(); \
541 } while (0)
542 #else
543 # define INT_OFF do { \
544         suppress_int++; \
545         barrier(); \
546 } while (0)
547 #endif
548
549 /*
550  * Called to raise an exception.  Since C doesn't include exceptions, we
551  * just do a longjmp to the exception handler.  The type of exception is
552  * stored in the global variable "exception_type".
553  */
554 static void raise_exception(int) NORETURN;
555 static void
556 raise_exception(int e)
557 {
558 #if DEBUG
559         if (exception_handler == NULL)
560                 abort();
561 #endif
562         INT_OFF;
563         exception_type = e;
564         longjmp(exception_handler->loc, 1);
565 }
566 #if DEBUG
567 #define raise_exception(e) do { \
568         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
569         raise_exception(e); \
570 } while (0)
571 #endif
572
573 /*
574  * Called when a SIGINT is received.  (If the user specifies
575  * that SIGINT is to be trapped or ignored using the trap builtin, then
576  * this routine is not called.)  Suppressint is nonzero when interrupts
577  * are held using the INT_OFF macro.  (The test for iflag is just
578  * defensive programming.)
579  */
580 static void raise_interrupt(void) NORETURN;
581 static void
582 raise_interrupt(void)
583 {
584         pending_int = 0;
585         /* Signal is not automatically unmasked after it is raised,
586          * do it ourself - unmask all signals */
587         sigprocmask_allsigs(SIG_UNBLOCK);
588         /* pending_sig = 0; - now done in signal_handler() */
589
590         if (!(rootshell && iflag)) {
591                 /* Kill ourself with SIGINT */
592                 signal(SIGINT, SIG_DFL);
593                 raise(SIGINT);
594         }
595         /* bash: ^C even on empty command line sets $? */
596         exitstatus = SIGINT + 128;
597         raise_exception(EXINT);
598         /* NOTREACHED */
599 }
600 #if DEBUG
601 #define raise_interrupt() do { \
602         TRACE(("raising interrupt on line %d\n", __LINE__)); \
603         raise_interrupt(); \
604 } while (0)
605 #endif
606
607 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
608 int_on(void)
609 {
610         barrier();
611         if (--suppress_int == 0 && pending_int) {
612                 raise_interrupt();
613         }
614 }
615 #if DEBUG_INTONOFF
616 # define INT_ON do { \
617         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
618         int_on(); \
619 } while (0)
620 #else
621 # define INT_ON int_on()
622 #endif
623 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
624 force_int_on(void)
625 {
626         barrier();
627         suppress_int = 0;
628         if (pending_int)
629                 raise_interrupt();
630 }
631 #define FORCE_INT_ON force_int_on()
632
633 #define SAVE_INT(v) ((v) = suppress_int)
634
635 #define RESTORE_INT(v) do { \
636         barrier(); \
637         suppress_int = (v); \
638         if (suppress_int == 0 && pending_int) \
639                 raise_interrupt(); \
640 } while (0)
641
642
643 /* ============ Stdout/stderr output */
644
645 static void
646 outstr(const char *p, FILE *file)
647 {
648         INT_OFF;
649         fputs(p, file);
650         INT_ON;
651 }
652
653 static void
654 flush_stdout_stderr(void)
655 {
656         INT_OFF;
657         fflush_all();
658         INT_ON;
659 }
660
661 /* Was called outcslow(c,FILE*), but c was always '\n' */
662 static void
663 newline_and_flush(FILE *dest)
664 {
665         INT_OFF;
666         putc('\n', dest);
667         fflush(dest);
668         INT_ON;
669 }
670
671 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
672 static int
673 out1fmt(const char *fmt, ...)
674 {
675         va_list ap;
676         int r;
677
678         INT_OFF;
679         va_start(ap, fmt);
680         r = vprintf(fmt, ap);
681         va_end(ap);
682         INT_ON;
683         return r;
684 }
685
686 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
687 static int
688 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
689 {
690         va_list ap;
691         int ret;
692
693         INT_OFF;
694         va_start(ap, fmt);
695         ret = vsnprintf(outbuf, length, fmt, ap);
696         va_end(ap);
697         INT_ON;
698         return ret;
699 }
700
701 static void
702 out1str(const char *p)
703 {
704         outstr(p, stdout);
705 }
706
707 static void
708 out2str(const char *p)
709 {
710         outstr(p, stderr);
711         flush_stdout_stderr();
712 }
713
714
715 /* ============ Parser structures */
716
717 /* control characters in argument strings */
718 #define CTL_FIRST CTLESC
719 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
720 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
721 #define CTLENDVAR    ((unsigned char)'\203')
722 #define CTLBACKQ     ((unsigned char)'\204')
723 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
724 #define CTLENDARI    ((unsigned char)'\207')
725 #define CTLQUOTEMARK ((unsigned char)'\210')
726 #define CTL_LAST CTLQUOTEMARK
727
728 /* variable substitution byte (follows CTLVAR) */
729 #define VSTYPE  0x0f            /* type of variable substitution */
730 #define VSNUL   0x10            /* colon--treat the empty string as unset */
731
732 /* values of VSTYPE field */
733 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
734 #define VSMINUS         0x2     /* ${var-text} */
735 #define VSPLUS          0x3     /* ${var+text} */
736 #define VSQUESTION      0x4     /* ${var?message} */
737 #define VSASSIGN        0x5     /* ${var=text} */
738 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
739 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
740 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
741 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
742 #define VSLENGTH        0xa     /* ${#var} */
743 #if BASH_SUBSTR
744 #define VSSUBSTR        0xc     /* ${var:position:length} */
745 #endif
746 #if BASH_PATTERN_SUBST
747 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
748 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
749 #endif
750
751 static const char dolatstr[] ALIGN1 = {
752         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
753 };
754 #define DOLATSTRLEN 6
755
756 #define NCMD      0
757 #define NPIPE     1
758 #define NREDIR    2
759 #define NBACKGND  3
760 #define NSUBSHELL 4
761 #define NAND      5
762 #define NOR       6
763 #define NSEMI     7
764 #define NIF       8
765 #define NWHILE    9
766 #define NUNTIL   10
767 #define NFOR     11
768 #define NCASE    12
769 #define NCLIST   13
770 #define NDEFUN   14
771 #define NARG     15
772 #define NTO      16
773 #if BASH_REDIR_OUTPUT
774 #define NTO2     17
775 #endif
776 #define NCLOBBER 18
777 #define NFROM    19
778 #define NFROMTO  20
779 #define NAPPEND  21
780 #define NTOFD    22
781 #define NFROMFD  23
782 #define NHERE    24
783 #define NXHERE   25
784 #define NNOT     26
785 #define N_NUMBER 27
786
787 union node;
788
789 struct ncmd {
790         smallint type; /* Nxxxx */
791         int linno;
792         union node *assign;
793         union node *args;
794         union node *redirect;
795 };
796
797 struct npipe {
798         smallint type;
799         smallint pipe_backgnd;
800         struct nodelist *cmdlist;
801 };
802
803 struct nredir {
804         smallint type;
805         int linno;
806         union node *n;
807         union node *redirect;
808 };
809
810 struct nbinary {
811         smallint type;
812         union node *ch1;
813         union node *ch2;
814 };
815
816 struct nif {
817         smallint type;
818         union node *test;
819         union node *ifpart;
820         union node *elsepart;
821 };
822
823 struct nfor {
824         smallint type;
825         int linno;
826         union node *args;
827         union node *body;
828         char *var;
829 };
830
831 struct ncase {
832         smallint type;
833         int linno;
834         union node *expr;
835         union node *cases;
836 };
837
838 struct nclist {
839         smallint type;
840         union node *next;
841         union node *pattern;
842         union node *body;
843 };
844
845 struct ndefun {
846         smallint type;
847         int linno;
848         char *text;
849         union node *body;
850 };
851
852 struct narg {
853         smallint type;
854         union node *next;
855         char *text;
856         struct nodelist *backquote;
857 };
858
859 /* nfile and ndup layout must match!
860  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
861  * that it is actually NTO2 (>&file), and change its type.
862  */
863 struct nfile {
864         smallint type;
865         union node *next;
866         int fd;
867         int _unused_dupfd;
868         union node *fname;
869         char *expfname;
870 };
871
872 struct ndup {
873         smallint type;
874         union node *next;
875         int fd;
876         int dupfd;
877         union node *vname;
878         char *_unused_expfname;
879 };
880
881 struct nhere {
882         smallint type;
883         union node *next;
884         int fd;
885         union node *doc;
886 };
887
888 struct nnot {
889         smallint type;
890         union node *com;
891 };
892
893 union node {
894         smallint type;
895         struct ncmd ncmd;
896         struct npipe npipe;
897         struct nredir nredir;
898         struct nbinary nbinary;
899         struct nif nif;
900         struct nfor nfor;
901         struct ncase ncase;
902         struct nclist nclist;
903         struct ndefun ndefun;
904         struct narg narg;
905         struct nfile nfile;
906         struct ndup ndup;
907         struct nhere nhere;
908         struct nnot nnot;
909 };
910
911 /*
912  * NODE_EOF is returned by parsecmd when it encounters an end of file.
913  * It must be distinct from NULL.
914  */
915 #define NODE_EOF ((union node *) -1L)
916
917 struct nodelist {
918         struct nodelist *next;
919         union node *n;
920 };
921
922 struct funcnode {
923         int count;
924         union node n;
925 };
926
927 /*
928  * Free a parse tree.
929  */
930 static void
931 freefunc(struct funcnode *f)
932 {
933         if (f && --f->count < 0)
934                 free(f);
935 }
936
937
938 /* ============ Debugging output */
939
940 #if DEBUG
941
942 static FILE *tracefile;
943
944 static void
945 trace_printf(const char *fmt, ...)
946 {
947         va_list va;
948
949         if (debug != 1)
950                 return;
951         if (DEBUG_TIME)
952                 fprintf(tracefile, "%u ", (int) time(NULL));
953         if (DEBUG_PID)
954                 fprintf(tracefile, "[%u] ", (int) getpid());
955         if (DEBUG_SIG)
956                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
957         va_start(va, fmt);
958         vfprintf(tracefile, fmt, va);
959         va_end(va);
960 }
961
962 static void
963 trace_vprintf(const char *fmt, va_list va)
964 {
965         if (debug != 1)
966                 return;
967         vfprintf(tracefile, fmt, va);
968         fprintf(tracefile, "\n");
969 }
970
971 static void
972 trace_puts(const char *s)
973 {
974         if (debug != 1)
975                 return;
976         fputs(s, tracefile);
977 }
978
979 static void
980 trace_puts_quoted(char *s)
981 {
982         char *p;
983         char c;
984
985         if (debug != 1)
986                 return;
987         putc('"', tracefile);
988         for (p = s; *p; p++) {
989                 switch ((unsigned char)*p) {
990                 case '\n': c = 'n'; goto backslash;
991                 case '\t': c = 't'; goto backslash;
992                 case '\r': c = 'r'; goto backslash;
993                 case '\"': c = '\"'; goto backslash;
994                 case '\\': c = '\\'; goto backslash;
995                 case CTLESC: c = 'e'; goto backslash;
996                 case CTLVAR: c = 'v'; goto backslash;
997                 case CTLBACKQ: c = 'q'; goto backslash;
998  backslash:
999                         putc('\\', tracefile);
1000                         putc(c, tracefile);
1001                         break;
1002                 default:
1003                         if (*p >= ' ' && *p <= '~')
1004                                 putc(*p, tracefile);
1005                         else {
1006                                 putc('\\', tracefile);
1007                                 putc((*p >> 6) & 03, tracefile);
1008                                 putc((*p >> 3) & 07, tracefile);
1009                                 putc(*p & 07, tracefile);
1010                         }
1011                         break;
1012                 }
1013         }
1014         putc('"', tracefile);
1015 }
1016
1017 static void
1018 trace_puts_args(char **ap)
1019 {
1020         if (debug != 1)
1021                 return;
1022         if (!*ap)
1023                 return;
1024         while (1) {
1025                 trace_puts_quoted(*ap);
1026                 if (!*++ap) {
1027                         putc('\n', tracefile);
1028                         break;
1029                 }
1030                 putc(' ', tracefile);
1031         }
1032 }
1033
1034 static void
1035 opentrace(void)
1036 {
1037         char s[100];
1038 #ifdef O_APPEND
1039         int flags;
1040 #endif
1041
1042         if (debug != 1) {
1043                 if (tracefile)
1044                         fflush(tracefile);
1045                 /* leave open because libedit might be using it */
1046                 return;
1047         }
1048         strcpy(s, "./trace");
1049         if (tracefile) {
1050                 if (!freopen(s, "a", tracefile)) {
1051                         fprintf(stderr, "Can't re-open %s\n", s);
1052                         debug = 0;
1053                         return;
1054                 }
1055         } else {
1056                 tracefile = fopen(s, "a");
1057                 if (tracefile == NULL) {
1058                         fprintf(stderr, "Can't open %s\n", s);
1059                         debug = 0;
1060                         return;
1061                 }
1062         }
1063 #ifdef O_APPEND
1064         flags = fcntl(fileno(tracefile), F_GETFL);
1065         if (flags >= 0)
1066                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1067 #endif
1068         setlinebuf(tracefile);
1069         fputs("\nTracing started.\n", tracefile);
1070 }
1071
1072 static void
1073 indent(int amount, char *pfx, FILE *fp)
1074 {
1075         int i;
1076
1077         for (i = 0; i < amount; i++) {
1078                 if (pfx && i == amount - 1)
1079                         fputs(pfx, fp);
1080                 putc('\t', fp);
1081         }
1082 }
1083
1084 /* little circular references here... */
1085 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1086
1087 static void
1088 sharg(union node *arg, FILE *fp)
1089 {
1090         char *p;
1091         struct nodelist *bqlist;
1092         unsigned char subtype;
1093
1094         if (arg->type != NARG) {
1095                 out1fmt("<node type %d>\n", arg->type);
1096                 abort();
1097         }
1098         bqlist = arg->narg.backquote;
1099         for (p = arg->narg.text; *p; p++) {
1100                 switch ((unsigned char)*p) {
1101                 case CTLESC:
1102                         p++;
1103                         putc(*p, fp);
1104                         break;
1105                 case CTLVAR:
1106                         putc('$', fp);
1107                         putc('{', fp);
1108                         subtype = *++p;
1109                         if (subtype == VSLENGTH)
1110                                 putc('#', fp);
1111
1112                         while (*p != '=') {
1113                                 putc(*p, fp);
1114                                 p++;
1115                         }
1116
1117                         if (subtype & VSNUL)
1118                                 putc(':', fp);
1119
1120                         switch (subtype & VSTYPE) {
1121                         case VSNORMAL:
1122                                 putc('}', fp);
1123                                 break;
1124                         case VSMINUS:
1125                                 putc('-', fp);
1126                                 break;
1127                         case VSPLUS:
1128                                 putc('+', fp);
1129                                 break;
1130                         case VSQUESTION:
1131                                 putc('?', fp);
1132                                 break;
1133                         case VSASSIGN:
1134                                 putc('=', fp);
1135                                 break;
1136                         case VSTRIMLEFT:
1137                                 putc('#', fp);
1138                                 break;
1139                         case VSTRIMLEFTMAX:
1140                                 putc('#', fp);
1141                                 putc('#', fp);
1142                                 break;
1143                         case VSTRIMRIGHT:
1144                                 putc('%', fp);
1145                                 break;
1146                         case VSTRIMRIGHTMAX:
1147                                 putc('%', fp);
1148                                 putc('%', fp);
1149                                 break;
1150                         case VSLENGTH:
1151                                 break;
1152                         default:
1153                                 out1fmt("<subtype %d>", subtype);
1154                         }
1155                         break;
1156                 case CTLENDVAR:
1157                         putc('}', fp);
1158                         break;
1159                 case CTLBACKQ:
1160                         putc('$', fp);
1161                         putc('(', fp);
1162                         shtree(bqlist->n, -1, NULL, fp);
1163                         putc(')', fp);
1164                         break;
1165                 default:
1166                         putc(*p, fp);
1167                         break;
1168                 }
1169         }
1170 }
1171
1172 static void
1173 shcmd(union node *cmd, FILE *fp)
1174 {
1175         union node *np;
1176         int first;
1177         const char *s;
1178         int dftfd;
1179
1180         first = 1;
1181         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1182                 if (!first)
1183                         putc(' ', fp);
1184                 sharg(np, fp);
1185                 first = 0;
1186         }
1187         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1188                 if (!first)
1189                         putc(' ', fp);
1190                 dftfd = 0;
1191                 switch (np->nfile.type) {
1192                 case NTO:      s = ">>"+1; dftfd = 1; break;
1193                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1194                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1195 #if BASH_REDIR_OUTPUT
1196                 case NTO2:
1197 #endif
1198                 case NTOFD:    s = ">&"; dftfd = 1; break;
1199                 case NFROM:    s = "<"; break;
1200                 case NFROMFD:  s = "<&"; break;
1201                 case NFROMTO:  s = "<>"; break;
1202                 default:       s = "*error*"; break;
1203                 }
1204                 if (np->nfile.fd != dftfd)
1205                         fprintf(fp, "%d", np->nfile.fd);
1206                 fputs(s, fp);
1207                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1208                         fprintf(fp, "%d", np->ndup.dupfd);
1209                 } else {
1210                         sharg(np->nfile.fname, fp);
1211                 }
1212                 first = 0;
1213         }
1214 }
1215
1216 static void
1217 shtree(union node *n, int ind, char *pfx, FILE *fp)
1218 {
1219         struct nodelist *lp;
1220         const char *s;
1221
1222         if (n == NULL)
1223                 return;
1224
1225         indent(ind, pfx, fp);
1226
1227         if (n == NODE_EOF) {
1228                 fputs("<EOF>", fp);
1229                 return;
1230         }
1231
1232         switch (n->type) {
1233         case NSEMI:
1234                 s = "; ";
1235                 goto binop;
1236         case NAND:
1237                 s = " && ";
1238                 goto binop;
1239         case NOR:
1240                 s = " || ";
1241  binop:
1242                 shtree(n->nbinary.ch1, ind, NULL, fp);
1243                 /* if (ind < 0) */
1244                         fputs(s, fp);
1245                 shtree(n->nbinary.ch2, ind, NULL, fp);
1246                 break;
1247         case NCMD:
1248                 shcmd(n, fp);
1249                 if (ind >= 0)
1250                         putc('\n', fp);
1251                 break;
1252         case NPIPE:
1253                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1254                         shtree(lp->n, 0, NULL, fp);
1255                         if (lp->next)
1256                                 fputs(" | ", fp);
1257                 }
1258                 if (n->npipe.pipe_backgnd)
1259                         fputs(" &", fp);
1260                 if (ind >= 0)
1261                         putc('\n', fp);
1262                 break;
1263         default:
1264                 fprintf(fp, "<node type %d>", n->type);
1265                 if (ind >= 0)
1266                         putc('\n', fp);
1267                 break;
1268         }
1269 }
1270
1271 static void
1272 showtree(union node *n)
1273 {
1274         trace_puts("showtree called\n");
1275         shtree(n, 1, NULL, stderr);
1276 }
1277
1278 #endif /* DEBUG */
1279
1280
1281 /* ============ Parser data */
1282
1283 /*
1284  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1285  */
1286 struct strlist {
1287         struct strlist *next;
1288         char *text;
1289 };
1290
1291 struct alias;
1292
1293 struct strpush {
1294         struct strpush *prev;   /* preceding string on stack */
1295         char *prev_string;
1296         int prev_left_in_line;
1297 #if ENABLE_ASH_ALIAS
1298         struct alias *ap;       /* if push was associated with an alias */
1299 #endif
1300         char *string;           /* remember the string since it may change */
1301
1302         /* Remember last two characters for pungetc. */
1303         int lastc[2];
1304
1305         /* Number of outstanding calls to pungetc. */
1306         int unget;
1307 };
1308
1309 /*
1310  * The parsefile structure pointed to by the global variable parsefile
1311  * contains information about the current file being read.
1312  */
1313 struct parsefile {
1314         struct parsefile *prev; /* preceding file on stack */
1315         int linno;              /* current line */
1316         int pf_fd;              /* file descriptor (or -1 if string) */
1317         int left_in_line;       /* number of chars left in this line */
1318         int left_in_buffer;     /* number of chars left in this buffer past the line */
1319         char *next_to_pgetc;    /* next char in buffer */
1320         char *buf;              /* input buffer */
1321         struct strpush *strpush; /* for pushing strings at this level */
1322         struct strpush basestrpush; /* so pushing one is fast */
1323
1324         /* Remember last two characters for pungetc. */
1325         int lastc[2];
1326
1327         /* Number of outstanding calls to pungetc. */
1328         int unget;
1329 };
1330
1331 static struct parsefile basepf;        /* top level input file */
1332 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1333 static char *commandname;              /* currently executing command */
1334
1335
1336 /* ============ Message printing */
1337
1338 static void
1339 ash_vmsg(const char *msg, va_list ap)
1340 {
1341         fprintf(stderr, "%s: ", arg0);
1342         if (commandname) {
1343                 if (strcmp(arg0, commandname))
1344                         fprintf(stderr, "%s: ", commandname);
1345                 if (!iflag || g_parsefile->pf_fd > 0)
1346                         fprintf(stderr, "line %d: ", errlinno);
1347         }
1348         vfprintf(stderr, msg, ap);
1349         newline_and_flush(stderr);
1350 }
1351
1352 /*
1353  * Exverror is called to raise the error exception.  If the second argument
1354  * is not NULL then error prints an error message using printf style
1355  * formatting.  It then raises the error exception.
1356  */
1357 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1358 static void
1359 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1360 {
1361 #if DEBUG
1362         if (msg) {
1363                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1364                 TRACEV((msg, ap));
1365         } else
1366                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1367         if (msg)
1368 #endif
1369                 ash_vmsg(msg, ap);
1370
1371         flush_stdout_stderr();
1372         raise_exception(cond);
1373         /* NOTREACHED */
1374 }
1375
1376 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1377 static void
1378 ash_msg_and_raise_error(const char *msg, ...)
1379 {
1380         va_list ap;
1381
1382         exitstatus = 2;
1383
1384         va_start(ap, msg);
1385         ash_vmsg_and_raise(EXERROR, msg, ap);
1386         /* NOTREACHED */
1387         va_end(ap);
1388 }
1389
1390 /*
1391  * 'fmt' must be a string literal.
1392  */
1393 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1394
1395 static void raise_error_syntax(const char *) NORETURN;
1396 static void
1397 raise_error_syntax(const char *msg)
1398 {
1399         errlinno = g_parsefile->linno;
1400         ash_msg_and_raise_error("syntax error: %s", msg);
1401         /* NOTREACHED */
1402 }
1403
1404 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1405 static void
1406 ash_msg_and_raise(int cond, const char *msg, ...)
1407 {
1408         va_list ap;
1409
1410         va_start(ap, msg);
1411         ash_vmsg_and_raise(cond, msg, ap);
1412         /* NOTREACHED */
1413         va_end(ap);
1414 }
1415
1416 /*
1417  * error/warning routines for external builtins
1418  */
1419 static void
1420 ash_msg(const char *fmt, ...)
1421 {
1422         va_list ap;
1423
1424         va_start(ap, fmt);
1425         ash_vmsg(fmt, ap);
1426         va_end(ap);
1427 }
1428
1429 /*
1430  * Return a string describing an error.  The returned string may be a
1431  * pointer to a static buffer that will be overwritten on the next call.
1432  * Action describes the operation that got the error.
1433  */
1434 static const char *
1435 errmsg(int e, const char *em)
1436 {
1437         if (e == ENOENT || e == ENOTDIR) {
1438                 return em;
1439         }
1440         return strerror(e);
1441 }
1442
1443
1444 /* ============ Memory allocation */
1445
1446 #if 0
1447 /* I consider these wrappers nearly useless:
1448  * ok, they return you to nearest exception handler, but
1449  * how much memory do you leak in the process, making
1450  * memory starvation worse?
1451  */
1452 static void *
1453 ckrealloc(void * p, size_t nbytes)
1454 {
1455         p = realloc(p, nbytes);
1456         if (!p)
1457                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1458         return p;
1459 }
1460
1461 static void *
1462 ckmalloc(size_t nbytes)
1463 {
1464         return ckrealloc(NULL, nbytes);
1465 }
1466
1467 static void *
1468 ckzalloc(size_t nbytes)
1469 {
1470         return memset(ckmalloc(nbytes), 0, nbytes);
1471 }
1472
1473 static char *
1474 ckstrdup(const char *s)
1475 {
1476         char *p = strdup(s);
1477         if (!p)
1478                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1479         return p;
1480 }
1481 #else
1482 /* Using bbox equivalents. They exit if out of memory */
1483 # define ckrealloc xrealloc
1484 # define ckmalloc  xmalloc
1485 # define ckzalloc  xzalloc
1486 # define ckstrdup  xstrdup
1487 #endif
1488
1489 /*
1490  * It appears that grabstackstr() will barf with such alignments
1491  * because stalloc() will return a string allocated in a new stackblock.
1492  */
1493 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1494 enum {
1495         /* Most machines require the value returned from malloc to be aligned
1496          * in some way.  The following macro will get this right
1497          * on many machines.  */
1498         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1499         /* Minimum size of a block */
1500         MINSIZE = SHELL_ALIGN(504),
1501 };
1502
1503 struct stack_block {
1504         struct stack_block *prev;
1505         char space[MINSIZE];
1506 };
1507
1508 struct stackmark {
1509         struct stack_block *stackp;
1510         char *stacknxt;
1511         size_t stacknleft;
1512 };
1513
1514
1515 struct globals_memstack {
1516         struct stack_block *g_stackp; // = &stackbase;
1517         char *g_stacknxt; // = stackbase.space;
1518         char *sstrend; // = stackbase.space + MINSIZE;
1519         size_t g_stacknleft; // = MINSIZE;
1520         struct stack_block stackbase;
1521 };
1522 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1523 #define G_memstack (*ash_ptr_to_globals_memstack)
1524 #define g_stackp     (G_memstack.g_stackp    )
1525 #define g_stacknxt   (G_memstack.g_stacknxt  )
1526 #define sstrend      (G_memstack.sstrend     )
1527 #define g_stacknleft (G_memstack.g_stacknleft)
1528 #define stackbase    (G_memstack.stackbase   )
1529 #define INIT_G_memstack() do { \
1530         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1531         barrier(); \
1532         g_stackp = &stackbase; \
1533         g_stacknxt = stackbase.space; \
1534         g_stacknleft = MINSIZE; \
1535         sstrend = stackbase.space + MINSIZE; \
1536 } while (0)
1537
1538
1539 #define stackblock()     ((void *)g_stacknxt)
1540 #define stackblocksize() g_stacknleft
1541
1542 /*
1543  * Parse trees for commands are allocated in lifo order, so we use a stack
1544  * to make this more efficient, and also to avoid all sorts of exception
1545  * handling code to handle interrupts in the middle of a parse.
1546  *
1547  * The size 504 was chosen because the Ultrix malloc handles that size
1548  * well.
1549  */
1550 static void *
1551 stalloc(size_t nbytes)
1552 {
1553         char *p;
1554         size_t aligned;
1555
1556         aligned = SHELL_ALIGN(nbytes);
1557         if (aligned > g_stacknleft) {
1558                 size_t len;
1559                 size_t blocksize;
1560                 struct stack_block *sp;
1561
1562                 blocksize = aligned;
1563                 if (blocksize < MINSIZE)
1564                         blocksize = MINSIZE;
1565                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1566                 if (len < blocksize)
1567                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1568                 INT_OFF;
1569                 sp = ckmalloc(len);
1570                 sp->prev = g_stackp;
1571                 g_stacknxt = sp->space;
1572                 g_stacknleft = blocksize;
1573                 sstrend = g_stacknxt + blocksize;
1574                 g_stackp = sp;
1575                 INT_ON;
1576         }
1577         p = g_stacknxt;
1578         g_stacknxt += aligned;
1579         g_stacknleft -= aligned;
1580         return p;
1581 }
1582
1583 static void *
1584 stzalloc(size_t nbytes)
1585 {
1586         return memset(stalloc(nbytes), 0, nbytes);
1587 }
1588
1589 static void
1590 stunalloc(void *p)
1591 {
1592 #if DEBUG
1593         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1594                 write(STDERR_FILENO, "stunalloc\n", 10);
1595                 abort();
1596         }
1597 #endif
1598         g_stacknleft += g_stacknxt - (char *)p;
1599         g_stacknxt = p;
1600 }
1601
1602 /*
1603  * Like strdup but works with the ash stack.
1604  */
1605 static char *
1606 sstrdup(const char *p)
1607 {
1608         size_t len = strlen(p) + 1;
1609         return memcpy(stalloc(len), p, len);
1610 }
1611
1612 static ALWAYS_INLINE void
1613 grabstackblock(size_t len)
1614 {
1615         stalloc(len);
1616 }
1617
1618 static void
1619 pushstackmark(struct stackmark *mark, size_t len)
1620 {
1621         mark->stackp = g_stackp;
1622         mark->stacknxt = g_stacknxt;
1623         mark->stacknleft = g_stacknleft;
1624         grabstackblock(len);
1625 }
1626
1627 static void
1628 setstackmark(struct stackmark *mark)
1629 {
1630         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1631 }
1632
1633 static void
1634 popstackmark(struct stackmark *mark)
1635 {
1636         struct stack_block *sp;
1637
1638         if (!mark->stackp)
1639                 return;
1640
1641         INT_OFF;
1642         while (g_stackp != mark->stackp) {
1643                 sp = g_stackp;
1644                 g_stackp = sp->prev;
1645                 free(sp);
1646         }
1647         g_stacknxt = mark->stacknxt;
1648         g_stacknleft = mark->stacknleft;
1649         sstrend = mark->stacknxt + mark->stacknleft;
1650         INT_ON;
1651 }
1652
1653 /*
1654  * When the parser reads in a string, it wants to stick the string on the
1655  * stack and only adjust the stack pointer when it knows how big the
1656  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1657  * of space on top of the stack and stackblocklen returns the length of
1658  * this block.  Growstackblock will grow this space by at least one byte,
1659  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1660  * part of the block that has been used.
1661  */
1662 static void
1663 growstackblock(void)
1664 {
1665         size_t newlen;
1666
1667         newlen = g_stacknleft * 2;
1668         if (newlen < g_stacknleft)
1669                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1670         if (newlen < 128)
1671                 newlen += 128;
1672
1673         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1674                 struct stack_block *sp;
1675                 struct stack_block *prevstackp;
1676                 size_t grosslen;
1677
1678                 INT_OFF;
1679                 sp = g_stackp;
1680                 prevstackp = sp->prev;
1681                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1682                 sp = ckrealloc(sp, grosslen);
1683                 sp->prev = prevstackp;
1684                 g_stackp = sp;
1685                 g_stacknxt = sp->space;
1686                 g_stacknleft = newlen;
1687                 sstrend = sp->space + newlen;
1688                 INT_ON;
1689         } else {
1690                 char *oldspace = g_stacknxt;
1691                 size_t oldlen = g_stacknleft;
1692                 char *p = stalloc(newlen);
1693
1694                 /* free the space we just allocated */
1695                 g_stacknxt = memcpy(p, oldspace, oldlen);
1696                 g_stacknleft += newlen;
1697         }
1698 }
1699
1700 /*
1701  * The following routines are somewhat easier to use than the above.
1702  * The user declares a variable of type STACKSTR, which may be declared
1703  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1704  * the user uses the macro STPUTC to add characters to the string.  In
1705  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1706  * grown as necessary.  When the user is done, she can just leave the
1707  * string there and refer to it using stackblock().  Or she can allocate
1708  * the space for it using grabstackstr().  If it is necessary to allow
1709  * someone else to use the stack temporarily and then continue to grow
1710  * the string, the user should use grabstack to allocate the space, and
1711  * then call ungrabstr(p) to return to the previous mode of operation.
1712  *
1713  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1714  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1715  * is space for at least one character.
1716  */
1717 static void *
1718 growstackstr(void)
1719 {
1720         size_t len = stackblocksize();
1721         growstackblock();
1722         return (char *)stackblock() + len;
1723 }
1724
1725 /*
1726  * Called from CHECKSTRSPACE.
1727  */
1728 static char *
1729 makestrspace(size_t newlen, char *p)
1730 {
1731         size_t len = p - g_stacknxt;
1732         size_t size;
1733
1734         for (;;) {
1735                 size_t nleft;
1736
1737                 size = stackblocksize();
1738                 nleft = size - len;
1739                 if (nleft >= newlen)
1740                         break;
1741                 growstackblock();
1742         }
1743         return (char *)stackblock() + len;
1744 }
1745
1746 static char *
1747 stack_nputstr(const char *s, size_t n, char *p)
1748 {
1749         p = makestrspace(n, p);
1750         p = (char *)mempcpy(p, s, n);
1751         return p;
1752 }
1753
1754 static char *
1755 stack_putstr(const char *s, char *p)
1756 {
1757         return stack_nputstr(s, strlen(s), p);
1758 }
1759
1760 static char *
1761 _STPUTC(int c, char *p)
1762 {
1763         if (p == sstrend)
1764                 p = growstackstr();
1765         *p++ = c;
1766         return p;
1767 }
1768
1769 #define STARTSTACKSTR(p)        ((p) = stackblock())
1770 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1771 #define CHECKSTRSPACE(n, p) do { \
1772         char *q = (p); \
1773         size_t l = (n); \
1774         size_t m = sstrend - q; \
1775         if (l > m) \
1776                 (p) = makestrspace(l, q); \
1777 } while (0)
1778 #define USTPUTC(c, p)           (*(p)++ = (c))
1779 #define STACKSTRNUL(p) do { \
1780         if ((p) == sstrend) \
1781                 (p) = growstackstr(); \
1782         *(p) = '\0'; \
1783 } while (0)
1784 #define STUNPUTC(p)             (--(p))
1785 #define STTOPC(p)               ((p)[-1])
1786 #define STADJUST(amount, p)     ((p) += (amount))
1787
1788 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1789 #define ungrabstackstr(s, p)    stunalloc(s)
1790 #define stackstrend()           ((void *)sstrend)
1791
1792
1793 /* ============ String helpers */
1794
1795 /*
1796  * prefix -- see if pfx is a prefix of string.
1797  */
1798 static char *
1799 prefix(const char *string, const char *pfx)
1800 {
1801         while (*pfx) {
1802                 if (*pfx++ != *string++)
1803                         return NULL;
1804         }
1805         return (char *) string;
1806 }
1807
1808 /*
1809  * Check for a valid number.  This should be elsewhere.
1810  */
1811 static int
1812 is_number(const char *p)
1813 {
1814         do {
1815                 if (!isdigit(*p))
1816                         return 0;
1817         } while (*++p != '\0');
1818         return 1;
1819 }
1820
1821 /*
1822  * Convert a string of digits to an integer, printing an error message on
1823  * failure.
1824  */
1825 static int
1826 number(const char *s)
1827 {
1828         if (!is_number(s))
1829                 ash_msg_and_raise_error(msg_illnum, s);
1830         return atoi(s);
1831 }
1832
1833 /*
1834  * Produce a single quoted string suitable as input to the shell.
1835  * The return string is allocated on the stack.
1836  */
1837 static char *
1838 single_quote(const char *s)
1839 {
1840         char *p;
1841
1842         STARTSTACKSTR(p);
1843
1844         do {
1845                 char *q;
1846                 size_t len;
1847
1848                 len = strchrnul(s, '\'') - s;
1849
1850                 q = p = makestrspace(len + 3, p);
1851
1852                 *q++ = '\'';
1853                 q = (char *)mempcpy(q, s, len);
1854                 *q++ = '\'';
1855                 s += len;
1856
1857                 STADJUST(q - p, p);
1858
1859                 if (*s != '\'')
1860                         break;
1861                 len = 0;
1862                 do len++; while (*++s == '\'');
1863
1864                 q = p = makestrspace(len + 3, p);
1865
1866                 *q++ = '"';
1867                 q = (char *)mempcpy(q, s - len, len);
1868                 *q++ = '"';
1869
1870                 STADJUST(q - p, p);
1871         } while (*s);
1872
1873         USTPUTC('\0', p);
1874
1875         return stackblock();
1876 }
1877
1878 /*
1879  * Produce a possibly single quoted string suitable as input to the shell.
1880  * If quoting was done, the return string is allocated on the stack,
1881  * otherwise a pointer to the original string is returned.
1882  */
1883 static const char *
1884 maybe_single_quote(const char *s)
1885 {
1886         const char *p = s;
1887
1888         while (*p) {
1889                 /* Assuming ACSII */
1890                 /* quote ctrl_chars space !"#$%&'()* */
1891                 if (*p < '+')
1892                         goto need_quoting;
1893                 /* quote ;<=>? */
1894                 if (*p >= ';' && *p <= '?')
1895                         goto need_quoting;
1896                 /* quote `[\ */
1897                 if (*p == '`')
1898                         goto need_quoting;
1899                 if (*p == '[')
1900                         goto need_quoting;
1901                 if (*p == '\\')
1902                         goto need_quoting;
1903                 /* quote {|}~ DEL and high bytes */
1904                 if (*p > 'z')
1905                         goto need_quoting;
1906                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1907                 /* TODO: maybe avoid quoting % */
1908                 p++;
1909         }
1910         return s;
1911
1912  need_quoting:
1913         return single_quote(s);
1914 }
1915
1916
1917 /* ============ nextopt */
1918
1919 static char **argptr;                  /* argument list for builtin commands */
1920 static char *optionarg;                /* set by nextopt (like getopt) */
1921 static char *optptr;                   /* used by nextopt */
1922
1923 /*
1924  * XXX - should get rid of. Have all builtins use getopt(3).
1925  * The library getopt must have the BSD extension static variable
1926  * "optreset", otherwise it can't be used within the shell safely.
1927  *
1928  * Standard option processing (a la getopt) for builtin routines.
1929  * The only argument that is passed to nextopt is the option string;
1930  * the other arguments are unnecessary. It returns the character,
1931  * or '\0' on end of input.
1932  */
1933 static int
1934 nextopt(const char *optstring)
1935 {
1936         char *p;
1937         const char *q;
1938         char c;
1939
1940         p = optptr;
1941         if (p == NULL || *p == '\0') {
1942                 /* We ate entire "-param", take next one */
1943                 p = *argptr;
1944                 if (p == NULL)
1945                         return '\0';
1946                 if (*p != '-')
1947                         return '\0';
1948                 if (*++p == '\0') /* just "-" ? */
1949                         return '\0';
1950                 argptr++;
1951                 if (LONE_DASH(p)) /* "--" ? */
1952                         return '\0';
1953                 /* p => next "-param" */
1954         }
1955         /* p => some option char in the middle of a "-param" */
1956         c = *p++;
1957         for (q = optstring; *q != c;) {
1958                 if (*q == '\0')
1959                         ash_msg_and_raise_error("illegal option -%c", c);
1960                 if (*++q == ':')
1961                         q++;
1962         }
1963         if (*++q == ':') {
1964                 if (*p == '\0') {
1965                         p = *argptr++;
1966                         if (p == NULL)
1967                                 ash_msg_and_raise_error("no arg for -%c option", c);
1968                 }
1969                 optionarg = p;
1970                 p = NULL;
1971         }
1972         optptr = p;
1973         return c;
1974 }
1975
1976
1977 /* ============ Shell variables */
1978
1979 struct shparam {
1980         int nparam;             /* # of positional parameters (without $0) */
1981 #if ENABLE_ASH_GETOPTS
1982         int optind;             /* next parameter to be processed by getopts */
1983         int optoff;             /* used by getopts */
1984 #endif
1985         unsigned char malloced; /* if parameter list dynamically allocated */
1986         char **p;               /* parameter list */
1987 };
1988
1989 /*
1990  * Free the list of positional parameters.
1991  */
1992 static void
1993 freeparam(volatile struct shparam *param)
1994 {
1995         if (param->malloced) {
1996                 char **ap, **ap1;
1997                 ap = ap1 = param->p;
1998                 while (*ap)
1999                         free(*ap++);
2000                 free(ap1);
2001         }
2002 }
2003
2004 #if ENABLE_ASH_GETOPTS
2005 static void FAST_FUNC getoptsreset(const char *value);
2006 #endif
2007
2008 struct var {
2009         struct var *next;               /* next entry in hash list */
2010         int flags;                      /* flags are defined above */
2011         const char *var_text;           /* name=value */
2012         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
2013                                         /* the variable gets set/unset */
2014 };
2015
2016 struct localvar {
2017         struct localvar *next;          /* next local variable in list */
2018         struct var *vp;                 /* the variable that was made local */
2019         int flags;                      /* saved flags */
2020         const char *text;               /* saved text */
2021 };
2022
2023 /* flags */
2024 #define VEXPORT         0x01    /* variable is exported */
2025 #define VREADONLY       0x02    /* variable cannot be modified */
2026 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
2027 #define VTEXTFIXED      0x08    /* text is statically allocated */
2028 #define VSTACK          0x10    /* text is allocated on the stack */
2029 #define VUNSET          0x20    /* the variable is not set */
2030 #define VNOFUNC         0x40    /* don't call the callback function */
2031 #define VNOSET          0x80    /* do not set variable - just readonly test */
2032 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2033 #if ENABLE_ASH_RANDOM_SUPPORT
2034 # define VDYNAMIC       0x200   /* dynamic variable */
2035 #else
2036 # define VDYNAMIC       0
2037 #endif
2038
2039
2040 /* Need to be before varinit_data[] */
2041 #if ENABLE_LOCALE_SUPPORT
2042 static void FAST_FUNC
2043 change_lc_all(const char *value)
2044 {
2045         if (value && *value != '\0')
2046                 setlocale(LC_ALL, value);
2047 }
2048 static void FAST_FUNC
2049 change_lc_ctype(const char *value)
2050 {
2051         if (value && *value != '\0')
2052                 setlocale(LC_CTYPE, value);
2053 }
2054 #endif
2055 #if ENABLE_ASH_MAIL
2056 static void chkmail(void);
2057 static void changemail(const char *var_value) FAST_FUNC;
2058 #else
2059 # define chkmail()  ((void)0)
2060 #endif
2061 static void changepath(const char *) FAST_FUNC;
2062 #if ENABLE_ASH_RANDOM_SUPPORT
2063 static void change_random(const char *) FAST_FUNC;
2064 #endif
2065
2066 static const struct {
2067         int flags;
2068         const char *var_text;
2069         void (*var_func)(const char *) FAST_FUNC;
2070 } varinit_data[] = {
2071         /*
2072          * Note: VEXPORT would not work correctly here for NOFORK applets:
2073          * some environment strings may be constant.
2074          */
2075         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2076 #if ENABLE_ASH_MAIL
2077         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2078         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2079 #endif
2080         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2081         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2082         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2083         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2084 #if ENABLE_ASH_GETOPTS
2085         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2086 #endif
2087         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2088 #if ENABLE_ASH_RANDOM_SUPPORT
2089         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2090 #endif
2091 #if ENABLE_LOCALE_SUPPORT
2092         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2093         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2094 #endif
2095 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2096         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2097 #endif
2098 };
2099
2100 struct redirtab;
2101
2102 struct globals_var {
2103         struct shparam shellparam;      /* $@ current positional parameters */
2104         struct redirtab *redirlist;
2105         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2106         struct var *vartab[VTABSIZE];
2107         struct var varinit[ARRAY_SIZE(varinit_data)];
2108         int lineno;
2109         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2110 };
2111 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2112 #define G_var (*ash_ptr_to_globals_var)
2113 #define shellparam    (G_var.shellparam   )
2114 //#define redirlist     (G_var.redirlist    )
2115 #define preverrout_fd (G_var.preverrout_fd)
2116 #define vartab        (G_var.vartab       )
2117 #define varinit       (G_var.varinit      )
2118 #define lineno        (G_var.lineno       )
2119 #define linenovar     (G_var.linenovar    )
2120 #define vifs      varinit[0]
2121 #if ENABLE_ASH_MAIL
2122 # define vmail    (&vifs)[1]
2123 # define vmpath   (&vmail)[1]
2124 # define vpath    (&vmpath)[1]
2125 #else
2126 # define vpath    (&vifs)[1]
2127 #endif
2128 #define vps1      (&vpath)[1]
2129 #define vps2      (&vps1)[1]
2130 #define vps4      (&vps2)[1]
2131 #if ENABLE_ASH_GETOPTS
2132 # define voptind  (&vps4)[1]
2133 # define vlineno  (&voptind)[1]
2134 # if ENABLE_ASH_RANDOM_SUPPORT
2135 #  define vrandom (&vlineno)[1]
2136 # endif
2137 #else
2138 # define vlineno  (&vps4)[1]
2139 # if ENABLE_ASH_RANDOM_SUPPORT
2140 #  define vrandom (&vlineno)[1]
2141 # endif
2142 #endif
2143 #define INIT_G_var() do { \
2144         unsigned i; \
2145         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2146         barrier(); \
2147         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2148                 varinit[i].flags    = varinit_data[i].flags; \
2149                 varinit[i].var_text = varinit_data[i].var_text; \
2150                 varinit[i].var_func = varinit_data[i].var_func; \
2151         } \
2152         strcpy(linenovar, "LINENO="); \
2153         vlineno.var_text = linenovar; \
2154 } while (0)
2155
2156 /*
2157  * The following macros access the values of the above variables.
2158  * They have to skip over the name.  They return the null string
2159  * for unset variables.
2160  */
2161 #define ifsval()        (vifs.var_text + 4)
2162 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2163 #if ENABLE_ASH_MAIL
2164 # define mailval()      (vmail.var_text + 5)
2165 # define mpathval()     (vmpath.var_text + 9)
2166 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2167 #endif
2168 #define pathval()       (vpath.var_text + 5)
2169 #define ps1val()        (vps1.var_text + 4)
2170 #define ps2val()        (vps2.var_text + 4)
2171 #define ps4val()        (vps4.var_text + 4)
2172 #if ENABLE_ASH_GETOPTS
2173 # define optindval()    (voptind.var_text + 7)
2174 #endif
2175
2176 #if ENABLE_ASH_GETOPTS
2177 static void FAST_FUNC
2178 getoptsreset(const char *value)
2179 {
2180         shellparam.optind = 1;
2181         if (is_number(value))
2182                 shellparam.optind = number(value) ?: 1;
2183         shellparam.optoff = -1;
2184 }
2185 #endif
2186
2187 /*
2188  * Compares two strings up to the first = or '\0'.  The first
2189  * string must be terminated by '='; the second may be terminated by
2190  * either '=' or '\0'.
2191  */
2192 static int
2193 varcmp(const char *p, const char *q)
2194 {
2195         int c, d;
2196
2197         while ((c = *p) == (d = *q)) {
2198                 if (c == '\0' || c == '=')
2199                         goto out;
2200                 p++;
2201                 q++;
2202         }
2203         if (c == '=')
2204                 c = '\0';
2205         if (d == '=')
2206                 d = '\0';
2207  out:
2208         return c - d;
2209 }
2210
2211 /*
2212  * Find the appropriate entry in the hash table from the name.
2213  */
2214 static struct var **
2215 hashvar(const char *p)
2216 {
2217         unsigned hashval;
2218
2219         hashval = ((unsigned char) *p) << 4;
2220         while (*p && *p != '=')
2221                 hashval += (unsigned char) *p++;
2222         return &vartab[hashval % VTABSIZE];
2223 }
2224
2225 static int
2226 vpcmp(const void *a, const void *b)
2227 {
2228         return varcmp(*(const char **)a, *(const char **)b);
2229 }
2230
2231 /*
2232  * This routine initializes the builtin variables.
2233  */
2234 static void
2235 initvar(void)
2236 {
2237         struct var *vp;
2238         struct var *end;
2239         struct var **vpp;
2240
2241         /*
2242          * PS1 depends on uid
2243          */
2244 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2245         vps1.var_text = "PS1=\\w \\$ ";
2246 #else
2247         if (!geteuid())
2248                 vps1.var_text = "PS1=# ";
2249 #endif
2250         vp = varinit;
2251         end = vp + ARRAY_SIZE(varinit);
2252         do {
2253                 vpp = hashvar(vp->var_text);
2254                 vp->next = *vpp;
2255                 *vpp = vp;
2256         } while (++vp < end);
2257 }
2258
2259 static struct var **
2260 findvar(struct var **vpp, const char *name)
2261 {
2262         for (; *vpp; vpp = &(*vpp)->next) {
2263                 if (varcmp((*vpp)->var_text, name) == 0) {
2264                         break;
2265                 }
2266         }
2267         return vpp;
2268 }
2269
2270 /*
2271  * Find the value of a variable.  Returns NULL if not set.
2272  */
2273 static const char* FAST_FUNC
2274 lookupvar(const char *name)
2275 {
2276         struct var *v;
2277
2278         v = *findvar(hashvar(name), name);
2279         if (v) {
2280 #if ENABLE_ASH_RANDOM_SUPPORT
2281         /*
2282          * Dynamic variables are implemented roughly the same way they are
2283          * in bash. Namely, they're "special" so long as they aren't unset.
2284          * As soon as they're unset, they're no longer dynamic, and dynamic
2285          * lookup will no longer happen at that point. -- PFM.
2286          */
2287                 if (v->flags & VDYNAMIC)
2288                         v->var_func(NULL);
2289 #endif
2290                 if (!(v->flags & VUNSET)) {
2291                         if (v == &vlineno && v->var_text == linenovar) {
2292                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2293                         }
2294                         return var_end(v->var_text);
2295                 }
2296         }
2297         return NULL;
2298 }
2299
2300 #if ENABLE_UNICODE_SUPPORT
2301 static void
2302 reinit_unicode_for_ash(void)
2303 {
2304         /* Unicode support should be activated even if LANG is set
2305          * _during_ shell execution, not only if it was set when
2306          * shell was started. Therefore, re-check LANG every time:
2307          */
2308         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2309          || ENABLE_UNICODE_USING_LOCALE
2310         ) {
2311                 const char *s = lookupvar("LC_ALL");
2312                 if (!s) s = lookupvar("LC_CTYPE");
2313                 if (!s) s = lookupvar("LANG");
2314                 reinit_unicode(s);
2315         }
2316 }
2317 #else
2318 # define reinit_unicode_for_ash() ((void)0)
2319 #endif
2320
2321 /*
2322  * Search the environment of a builtin command.
2323  */
2324 static ALWAYS_INLINE const char *
2325 bltinlookup(const char *name)
2326 {
2327         return lookupvar(name);
2328 }
2329
2330 /*
2331  * Same as setvar except that the variable and value are passed in
2332  * the first argument as name=value.  Since the first argument will
2333  * be actually stored in the table, it should not be a string that
2334  * will go away.
2335  * Called with interrupts off.
2336  */
2337 static struct var *
2338 setvareq(char *s, int flags)
2339 {
2340         struct var *vp, **vpp;
2341
2342         vpp = hashvar(s);
2343         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2344         vpp = findvar(vpp, s);
2345         vp = *vpp;
2346         if (vp) {
2347                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2348                         const char *n;
2349
2350                         if (flags & VNOSAVE)
2351                                 free(s);
2352                         n = vp->var_text;
2353                         exitstatus = 1;
2354                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2355                 }
2356
2357                 if (flags & VNOSET)
2358                         goto out;
2359
2360                 if (vp->var_func && !(flags & VNOFUNC))
2361                         vp->var_func(var_end(s));
2362
2363                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2364                         free((char*)vp->var_text);
2365
2366                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2367                         *vpp = vp->next;
2368                         free(vp);
2369  out_free:
2370                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2371                                 free(s);
2372                         goto out;
2373                 }
2374
2375                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2376         } else {
2377                 /* variable s is not found */
2378                 if (flags & VNOSET)
2379                         goto out;
2380                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2381                         goto out_free;
2382                 vp = ckzalloc(sizeof(*vp));
2383                 vp->next = *vpp;
2384                 /*vp->func = NULL; - ckzalloc did it */
2385                 *vpp = vp;
2386         }
2387         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2388                 s = ckstrdup(s);
2389         vp->var_text = s;
2390         vp->flags = flags;
2391
2392  out:
2393         return vp;
2394 }
2395
2396 /*
2397  * Set the value of a variable.  The flags argument is ored with the
2398  * flags of the variable.  If val is NULL, the variable is unset.
2399  */
2400 static struct var *
2401 setvar(const char *name, const char *val, int flags)
2402 {
2403         const char *q;
2404         char *p;
2405         char *nameeq;
2406         size_t namelen;
2407         size_t vallen;
2408         struct var *vp;
2409
2410         q = endofname(name);
2411         p = strchrnul(q, '=');
2412         namelen = p - name;
2413         if (!namelen || p != q)
2414                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2415         vallen = 0;
2416         if (val == NULL) {
2417                 flags |= VUNSET;
2418         } else {
2419                 vallen = strlen(val);
2420         }
2421
2422         INT_OFF;
2423         nameeq = ckzalloc(namelen + vallen + 2);
2424         p = mempcpy(nameeq, name, namelen);
2425         if (val) {
2426                 *p++ = '=';
2427                 memcpy(p, val, vallen);
2428         }
2429         vp = setvareq(nameeq, flags | VNOSAVE);
2430         INT_ON;
2431
2432         return vp;
2433 }
2434
2435 static void FAST_FUNC
2436 setvar0(const char *name, const char *val)
2437 {
2438         setvar(name, val, 0);
2439 }
2440
2441 /*
2442  * Unset the specified variable.
2443  */
2444 static void
2445 unsetvar(const char *s)
2446 {
2447         setvar(s, NULL, 0);
2448 }
2449
2450 /*
2451  * Process a linked list of variable assignments.
2452  */
2453 static void
2454 listsetvar(struct strlist *list_set_var, int flags)
2455 {
2456         struct strlist *lp = list_set_var;
2457
2458         if (!lp)
2459                 return;
2460         INT_OFF;
2461         do {
2462                 setvareq(lp->text, flags);
2463                 lp = lp->next;
2464         } while (lp);
2465         INT_ON;
2466 }
2467
2468 /*
2469  * Generate a list of variables satisfying the given conditions.
2470  */
2471 #if !ENABLE_FEATURE_SH_NOFORK
2472 # define listvars(on, off, lp, end) listvars(on, off, end)
2473 #endif
2474 static char **
2475 listvars(int on, int off, struct strlist *lp, char ***end)
2476 {
2477         struct var **vpp;
2478         struct var *vp;
2479         char **ep;
2480         int mask;
2481
2482         STARTSTACKSTR(ep);
2483         vpp = vartab;
2484         mask = on | off;
2485         do {
2486                 for (vp = *vpp; vp; vp = vp->next) {
2487                         if ((vp->flags & mask) == on) {
2488 #if ENABLE_FEATURE_SH_NOFORK
2489                                 /* If variable with the same name is both
2490                                  * exported and temporarily set for a command:
2491                                  *  export ZVAR=5
2492                                  *  ZVAR=6 printenv
2493                                  * then "ZVAR=6" will be both in vartab and
2494                                  * lp lists. Do not pass it twice to printenv.
2495                                  */
2496                                 struct strlist *lp1 = lp;
2497                                 while (lp1) {
2498                                         if (strcmp(lp1->text, vp->var_text) == 0)
2499                                                 goto skip;
2500                                         lp1 = lp1->next;
2501                                 }
2502 #endif
2503                                 if (ep == stackstrend())
2504                                         ep = growstackstr();
2505                                 *ep++ = (char*)vp->var_text;
2506 #if ENABLE_FEATURE_SH_NOFORK
2507  skip: ;
2508 #endif
2509                         }
2510                 }
2511         } while (++vpp < vartab + VTABSIZE);
2512
2513 #if ENABLE_FEATURE_SH_NOFORK
2514         while (lp) {
2515                 if (ep == stackstrend())
2516                         ep = growstackstr();
2517                 *ep++ = lp->text;
2518                 lp = lp->next;
2519         }
2520 #endif
2521
2522         if (ep == stackstrend())
2523                 ep = growstackstr();
2524         if (end)
2525                 *end = ep;
2526         *ep++ = NULL;
2527         return grabstackstr(ep);
2528 }
2529
2530
2531 /* ============ Path search helper
2532  *
2533  * The variable path (passed by reference) should be set to the start
2534  * of the path before the first call; path_advance will update
2535  * this value as it proceeds.  Successive calls to path_advance will return
2536  * the possible path expansions in sequence.  If an option (indicated by
2537  * a percent sign) appears in the path entry then the global variable
2538  * pathopt will be set to point to it; otherwise pathopt will be set to
2539  * NULL.
2540  */
2541 static const char *pathopt;     /* set by path_advance */
2542
2543 static char *
2544 path_advance(const char **path, const char *name)
2545 {
2546         const char *p;
2547         char *q;
2548         const char *start;
2549         size_t len;
2550
2551         if (*path == NULL)
2552                 return NULL;
2553         start = *path;
2554         for (p = start; *p && *p != ':' && *p != '%'; p++)
2555                 continue;
2556         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2557         while (stackblocksize() < len)
2558                 growstackblock();
2559         q = stackblock();
2560         if (p != start) {
2561                 q = mempcpy(q, start, p - start);
2562                 *q++ = '/';
2563         }
2564         strcpy(q, name);
2565         pathopt = NULL;
2566         if (*p == '%') {
2567                 pathopt = ++p;
2568                 while (*p && *p != ':')
2569                         p++;
2570         }
2571         if (*p == ':')
2572                 *path = p + 1;
2573         else
2574                 *path = NULL;
2575         return stalloc(len);
2576 }
2577
2578
2579 /* ============ Prompt */
2580
2581 static smallint doprompt;                   /* if set, prompt the user */
2582 static smallint needprompt;                 /* true if interactive and at start of line */
2583
2584 #if ENABLE_FEATURE_EDITING
2585 static line_input_t *line_input_state;
2586 static const char *cmdedit_prompt;
2587 static void
2588 putprompt(const char *s)
2589 {
2590         if (ENABLE_ASH_EXPAND_PRMT) {
2591                 free((char*)cmdedit_prompt);
2592                 cmdedit_prompt = ckstrdup(s);
2593                 return;
2594         }
2595         cmdedit_prompt = s;
2596 }
2597 #else
2598 static void
2599 putprompt(const char *s)
2600 {
2601         out2str(s);
2602 }
2603 #endif
2604
2605 /* expandstr() needs parsing machinery, so it is far away ahead... */
2606 static const char *expandstr(const char *ps, int syntax_type);
2607 /* Values for syntax param */
2608 #define BASESYNTAX 0    /* not in quotes */
2609 #define DQSYNTAX   1    /* in double quotes */
2610 #define SQSYNTAX   2    /* in single quotes */
2611 #define ARISYNTAX  3    /* in arithmetic */
2612 #if ENABLE_ASH_EXPAND_PRMT
2613 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2614 #endif
2615 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2616
2617 /*
2618  * called by editline -- any expansions to the prompt should be added here.
2619  */
2620 static void
2621 setprompt_if(smallint do_set, int whichprompt)
2622 {
2623         const char *prompt;
2624         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2625
2626         if (!do_set)
2627                 return;
2628
2629         needprompt = 0;
2630
2631         switch (whichprompt) {
2632         case 1:
2633                 prompt = ps1val();
2634                 break;
2635         case 2:
2636                 prompt = ps2val();
2637                 break;
2638         default:                        /* 0 */
2639                 prompt = nullstr;
2640         }
2641 #if ENABLE_ASH_EXPAND_PRMT
2642         pushstackmark(&smark, stackblocksize());
2643         putprompt(expandstr(prompt, PSSYNTAX));
2644         popstackmark(&smark);
2645 #else
2646         putprompt(prompt);
2647 #endif
2648 }
2649
2650
2651 /* ============ The cd and pwd commands */
2652
2653 #define CD_PHYSICAL 1
2654 #define CD_PRINT 2
2655
2656 static int
2657 cdopt(void)
2658 {
2659         int flags = 0;
2660         int i, j;
2661
2662         j = 'L';
2663         while ((i = nextopt("LP")) != '\0') {
2664                 if (i != j) {
2665                         flags ^= CD_PHYSICAL;
2666                         j = i;
2667                 }
2668         }
2669
2670         return flags;
2671 }
2672
2673 /*
2674  * Update curdir (the name of the current directory) in response to a
2675  * cd command.
2676  */
2677 static const char *
2678 updatepwd(const char *dir)
2679 {
2680         char *new;
2681         char *p;
2682         char *cdcomppath;
2683         const char *lim;
2684
2685         cdcomppath = sstrdup(dir);
2686         STARTSTACKSTR(new);
2687         if (*dir != '/') {
2688                 if (curdir == nullstr)
2689                         return 0;
2690                 new = stack_putstr(curdir, new);
2691         }
2692         new = makestrspace(strlen(dir) + 2, new);
2693         lim = (char *)stackblock() + 1;
2694         if (*dir != '/') {
2695                 if (new[-1] != '/')
2696                         USTPUTC('/', new);
2697                 if (new > lim && *lim == '/')
2698                         lim++;
2699         } else {
2700                 USTPUTC('/', new);
2701                 cdcomppath++;
2702                 if (dir[1] == '/' && dir[2] != '/') {
2703                         USTPUTC('/', new);
2704                         cdcomppath++;
2705                         lim++;
2706                 }
2707         }
2708         p = strtok(cdcomppath, "/");
2709         while (p) {
2710                 switch (*p) {
2711                 case '.':
2712                         if (p[1] == '.' && p[2] == '\0') {
2713                                 while (new > lim) {
2714                                         STUNPUTC(new);
2715                                         if (new[-1] == '/')
2716                                                 break;
2717                                 }
2718                                 break;
2719                         }
2720                         if (p[1] == '\0')
2721                                 break;
2722                         /* fall through */
2723                 default:
2724                         new = stack_putstr(p, new);
2725                         USTPUTC('/', new);
2726                 }
2727                 p = strtok(NULL, "/");
2728         }
2729         if (new > lim)
2730                 STUNPUTC(new);
2731         *new = 0;
2732         return stackblock();
2733 }
2734
2735 /*
2736  * Find out what the current directory is. If we already know the current
2737  * directory, this routine returns immediately.
2738  */
2739 static char *
2740 getpwd(void)
2741 {
2742         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2743         return dir ? dir : nullstr;
2744 }
2745
2746 static void
2747 setpwd(const char *val, int setold)
2748 {
2749         char *oldcur, *dir;
2750
2751         oldcur = dir = curdir;
2752
2753         if (setold) {
2754                 setvar("OLDPWD", oldcur, VEXPORT);
2755         }
2756         INT_OFF;
2757         if (physdir != nullstr) {
2758                 if (physdir != oldcur)
2759                         free(physdir);
2760                 physdir = nullstr;
2761         }
2762         if (oldcur == val || !val) {
2763                 char *s = getpwd();
2764                 physdir = s;
2765                 if (!val)
2766                         dir = s;
2767         } else
2768                 dir = ckstrdup(val);
2769         if (oldcur != dir && oldcur != nullstr) {
2770                 free(oldcur);
2771         }
2772         curdir = dir;
2773         INT_ON;
2774         setvar("PWD", dir, VEXPORT);
2775 }
2776
2777 static void hashcd(void);
2778
2779 /*
2780  * Actually do the chdir.  We also call hashcd to let other routines
2781  * know that the current directory has changed.
2782  */
2783 static int
2784 docd(const char *dest, int flags)
2785 {
2786         const char *dir = NULL;
2787         int err;
2788
2789         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2790
2791         INT_OFF;
2792         if (!(flags & CD_PHYSICAL)) {
2793                 dir = updatepwd(dest);
2794                 if (dir)
2795                         dest = dir;
2796         }
2797         err = chdir(dest);
2798         if (err)
2799                 goto out;
2800         setpwd(dir, 1);
2801         hashcd();
2802  out:
2803         INT_ON;
2804         return err;
2805 }
2806
2807 static int FAST_FUNC
2808 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2809 {
2810         const char *dest;
2811         const char *path;
2812         const char *p;
2813         char c;
2814         struct stat statb;
2815         int flags;
2816
2817         flags = cdopt();
2818         dest = *argptr;
2819         if (!dest)
2820                 dest = bltinlookup("HOME");
2821         else if (LONE_DASH(dest)) {
2822                 dest = bltinlookup("OLDPWD");
2823                 flags |= CD_PRINT;
2824         }
2825         if (!dest)
2826                 dest = nullstr;
2827         if (*dest == '/')
2828                 goto step6;
2829         if (*dest == '.') {
2830                 c = dest[1];
2831  dotdot:
2832                 switch (c) {
2833                 case '\0':
2834                 case '/':
2835                         goto step6;
2836                 case '.':
2837                         c = dest[2];
2838                         if (c != '.')
2839                                 goto dotdot;
2840                 }
2841         }
2842         if (!*dest)
2843                 dest = ".";
2844         path = bltinlookup("CDPATH");
2845         while (path) {
2846                 c = *path;
2847                 p = path_advance(&path, dest);
2848                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2849                         if (c && c != ':')
2850                                 flags |= CD_PRINT;
2851  docd:
2852                         if (!docd(p, flags))
2853                                 goto out;
2854                         goto err;
2855                 }
2856         }
2857
2858  step6:
2859         p = dest;
2860         goto docd;
2861
2862  err:
2863         ash_msg_and_raise_perror("can't cd to %s", dest);
2864         /* NOTREACHED */
2865  out:
2866         if (flags & CD_PRINT)
2867                 out1fmt("%s\n", curdir);
2868         return 0;
2869 }
2870
2871 static int FAST_FUNC
2872 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2873 {
2874         int flags;
2875         const char *dir = curdir;
2876
2877         flags = cdopt();
2878         if (flags) {
2879                 if (physdir == nullstr)
2880                         setpwd(dir, 0);
2881                 dir = physdir;
2882         }
2883         out1fmt("%s\n", dir);
2884         return 0;
2885 }
2886
2887
2888 /* ============ ... */
2889
2890
2891 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2892
2893 /* Syntax classes */
2894 #define CWORD     0             /* character is nothing special */
2895 #define CNL       1             /* newline character */
2896 #define CBACK     2             /* a backslash character */
2897 #define CSQUOTE   3             /* single quote */
2898 #define CDQUOTE   4             /* double quote */
2899 #define CENDQUOTE 5             /* a terminating quote */
2900 #define CBQUOTE   6             /* backwards single quote */
2901 #define CVAR      7             /* a dollar sign */
2902 #define CENDVAR   8             /* a '}' character */
2903 #define CLP       9             /* a left paren in arithmetic */
2904 #define CRP      10             /* a right paren in arithmetic */
2905 #define CENDFILE 11             /* end of file */
2906 #define CCTL     12             /* like CWORD, except it must be escaped */
2907 #define CSPCL    13             /* these terminate a word */
2908 #define CIGN     14             /* character should be ignored */
2909
2910 #define PEOF     256
2911 #if ENABLE_ASH_ALIAS
2912 # define PEOA    257
2913 #endif
2914
2915 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2916
2917 #if ENABLE_FEATURE_SH_MATH
2918 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2919 #else
2920 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2921 #endif
2922 static const uint16_t S_I_T[] ALIGN2 = {
2923 #if ENABLE_ASH_ALIAS
2924         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2925 #endif
2926         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2927         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2928         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2929         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2930         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2931         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2932         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2933         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2934         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2935         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2936         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2937 #if !USE_SIT_FUNCTION
2938         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2939         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2940         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2941 #endif
2942 #undef SIT_ITEM
2943 };
2944 /* Constants below must match table above */
2945 enum {
2946 #if ENABLE_ASH_ALIAS
2947         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2948 #endif
2949         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2950         CNL_CNL_CNL_CNL                    , /*  2 */
2951         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2952         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2953         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2954         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2955         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2956         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2957         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2958         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2959         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2960         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2961         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2962         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2963 };
2964
2965 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2966  * caller must ensure proper cast on it if c is *char_ptr!
2967  */
2968 #if USE_SIT_FUNCTION
2969
2970 static int
2971 SIT(int c, int syntax)
2972 {
2973         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2974         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2975         /*
2976          * This causes '/' to be prepended with CTLESC in dquoted string,
2977          * making "./file"* treated incorrectly because we feed
2978          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2979          * The "homegrown" glob implementation is okay with that,
2980          * but glibc one isn't. With '/' always treated as CWORD,
2981          * both work fine.
2982          */
2983 # if ENABLE_ASH_ALIAS
2984         static const uint8_t syntax_index_table[] ALIGN1 = {
2985                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2986                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2987                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2988                 11, 3                           /* "}~" */
2989         };
2990 # else
2991         static const uint8_t syntax_index_table[] ALIGN1 = {
2992                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2993                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2994                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2995                 10, 2                           /* "}~" */
2996         };
2997 # endif
2998         const char *s;
2999         int indx;
3000
3001         if (c == PEOF)
3002                 return CENDFILE;
3003 # if ENABLE_ASH_ALIAS
3004         if (c == PEOA)
3005                 indx = 0;
3006         else
3007 # endif
3008         {
3009                 /* Cast is purely for paranoia here,
3010                  * just in case someone passed signed char to us */
3011                 if ((unsigned char)c >= CTL_FIRST
3012                  && (unsigned char)c <= CTL_LAST
3013                 ) {
3014                         return CCTL;
3015                 }
3016                 s = strchrnul(spec_symbls, c);
3017                 if (*s == '\0')
3018                         return CWORD;
3019                 indx = syntax_index_table[s - spec_symbls];
3020         }
3021         return (S_I_T[indx] >> (syntax*4)) & 0xf;
3022 }
3023
3024 #else   /* !USE_SIT_FUNCTION */
3025
3026 static const uint8_t syntax_index_table[] ALIGN1 = {
3027         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3028         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3029         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3030         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3031         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3032         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3033         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3034         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3035         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3036         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3037         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3038         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3039         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3040         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3041         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3042         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3043         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3044         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3045         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3046         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3047         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3048         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3049         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3050         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3051         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3052         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3053         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3054         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3055         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3056         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3057         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3058         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3059         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3060         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3061         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3062         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3063         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3064         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3065         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3066         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3067         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3068         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3069         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3070         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3071         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3072         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3073         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3074         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3075 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3076         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3077         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3078         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3079         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3080         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3081         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3082         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3083         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3084         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3085         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3086         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3087         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3088         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3089         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3090         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3091         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3092         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3093         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3094         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3095         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3096         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3097         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3098         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3099         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3100         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3101         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3102         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3103         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3104         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3105         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3106         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3107         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3108         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3109         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3110         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3111         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3112         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3113         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3114         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3115         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3116         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3117         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3118         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3119         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3120         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3121         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3122         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3123         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3124         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3125         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3126         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3127         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3128         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3129         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3130         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3131         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3132         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3133         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3134         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3135         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3136         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3137         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3138         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3139         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3140         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3141         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3142         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3143         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3144         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3145         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3146         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3147         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3148         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3149         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3150         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3151         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3152         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3153         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3154         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3155         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3156         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3157         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3158         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3159         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3160         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3161         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3162         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3163         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3164         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3165         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3166         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3258         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3259         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3260         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3261         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3262         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3263         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3264         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3265         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3266         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3267         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3268         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3269         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3270         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3271         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3272         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3273         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3274         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3275         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3276         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3277         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3278         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3279         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3280         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3281         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3282         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3283         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3284         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3285         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3286 # if ENABLE_ASH_ALIAS
3287         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3288 # endif
3289 };
3290
3291 #if 1
3292 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3293 #else /* debug version, caught one signed char bug */
3294 # define SIT(c, syntax) \
3295         ({ \
3296                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3297                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3298                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3299                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3300                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3301         })
3302 #endif
3303
3304 #endif  /* !USE_SIT_FUNCTION */
3305
3306
3307 /* ============ Alias handling */
3308
3309 #if ENABLE_ASH_ALIAS
3310
3311 #define ALIASINUSE 1
3312 #define ALIASDEAD  2
3313
3314 struct alias {
3315         struct alias *next;
3316         char *name;
3317         char *val;
3318         int flag;
3319 };
3320
3321
3322 static struct alias **atab; // [ATABSIZE];
3323 #define INIT_G_alias() do { \
3324         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3325 } while (0)
3326
3327
3328 static struct alias **
3329 __lookupalias(const char *name)
3330 {
3331         unsigned int hashval;
3332         struct alias **app;
3333         const char *p;
3334         unsigned int ch;
3335
3336         p = name;
3337
3338         ch = (unsigned char)*p;
3339         hashval = ch << 4;
3340         while (ch) {
3341                 hashval += ch;
3342                 ch = (unsigned char)*++p;
3343         }
3344         app = &atab[hashval % ATABSIZE];
3345
3346         for (; *app; app = &(*app)->next) {
3347                 if (strcmp(name, (*app)->name) == 0) {
3348                         break;
3349                 }
3350         }
3351
3352         return app;
3353 }
3354
3355 static struct alias *
3356 lookupalias(const char *name, int check)
3357 {
3358         struct alias *ap = *__lookupalias(name);
3359
3360         if (check && ap && (ap->flag & ALIASINUSE))
3361                 return NULL;
3362         return ap;
3363 }
3364
3365 static struct alias *
3366 freealias(struct alias *ap)
3367 {
3368         struct alias *next;
3369
3370         if (ap->flag & ALIASINUSE) {
3371                 ap->flag |= ALIASDEAD;
3372                 return ap;
3373         }
3374
3375         next = ap->next;
3376         free(ap->name);
3377         free(ap->val);
3378         free(ap);
3379         return next;
3380 }
3381
3382 static void
3383 setalias(const char *name, const char *val)
3384 {
3385         struct alias *ap, **app;
3386
3387         app = __lookupalias(name);
3388         ap = *app;
3389         INT_OFF;
3390         if (ap) {
3391                 if (!(ap->flag & ALIASINUSE)) {
3392                         free(ap->val);
3393                 }
3394                 ap->val = ckstrdup(val);
3395                 ap->flag &= ~ALIASDEAD;
3396         } else {
3397                 /* not found */
3398                 ap = ckzalloc(sizeof(struct alias));
3399                 ap->name = ckstrdup(name);
3400                 ap->val = ckstrdup(val);
3401                 /*ap->flag = 0; - ckzalloc did it */
3402                 /*ap->next = NULL;*/
3403                 *app = ap;
3404         }
3405         INT_ON;
3406 }
3407
3408 static int
3409 unalias(const char *name)
3410 {
3411         struct alias **app;
3412
3413         app = __lookupalias(name);
3414
3415         if (*app) {
3416                 INT_OFF;
3417                 *app = freealias(*app);
3418                 INT_ON;
3419                 return 0;
3420         }
3421
3422         return 1;
3423 }
3424
3425 static void
3426 rmaliases(void)
3427 {
3428         struct alias *ap, **app;
3429         int i;
3430
3431         INT_OFF;
3432         for (i = 0; i < ATABSIZE; i++) {
3433                 app = &atab[i];
3434                 for (ap = *app; ap; ap = *app) {
3435                         *app = freealias(*app);
3436                         if (ap == *app) {
3437                                 app = &ap->next;
3438                         }
3439                 }
3440         }
3441         INT_ON;
3442 }
3443
3444 static void
3445 printalias(const struct alias *ap)
3446 {
3447         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3448 }
3449
3450 /*
3451  * TODO - sort output
3452  */
3453 static int FAST_FUNC
3454 aliascmd(int argc UNUSED_PARAM, char **argv)
3455 {
3456         char *n, *v;
3457         int ret = 0;
3458         struct alias *ap;
3459
3460         if (!argv[1]) {
3461                 int i;
3462
3463                 for (i = 0; i < ATABSIZE; i++) {
3464                         for (ap = atab[i]; ap; ap = ap->next) {
3465                                 printalias(ap);
3466                         }
3467                 }
3468                 return 0;
3469         }
3470         while ((n = *++argv) != NULL) {
3471                 v = strchr(n+1, '=');
3472                 if (v == NULL) { /* n+1: funny ksh stuff */
3473                         ap = *__lookupalias(n);
3474                         if (ap == NULL) {
3475                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3476                                 ret = 1;
3477                         } else
3478                                 printalias(ap);
3479                 } else {
3480                         *v++ = '\0';
3481                         setalias(n, v);
3482                 }
3483         }
3484
3485         return ret;
3486 }
3487
3488 static int FAST_FUNC
3489 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3490 {
3491         int i;
3492
3493         while (nextopt("a") != '\0') {
3494                 rmaliases();
3495                 return 0;
3496         }
3497         for (i = 0; *argptr; argptr++) {
3498                 if (unalias(*argptr)) {
3499                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3500                         i = 1;
3501                 }
3502         }
3503
3504         return i;
3505 }
3506
3507 #endif /* ASH_ALIAS */
3508
3509
3510 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3511 #define FORK_FG    0
3512 #define FORK_BG    1
3513 #define FORK_NOJOB 2
3514
3515 /* mode flags for showjob(s) */
3516 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3517 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3518 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3519 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3520
3521 /*
3522  * A job structure contains information about a job.  A job is either a
3523  * single process or a set of processes contained in a pipeline.  In the
3524  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3525  * array of pids.
3526  */
3527 struct procstat {
3528         pid_t   ps_pid;         /* process id */
3529         int     ps_status;      /* last process status from wait() */
3530         char    *ps_cmd;        /* text of command being run */
3531 };
3532
3533 struct job {
3534         struct procstat ps0;    /* status of process */
3535         struct procstat *ps;    /* status or processes when more than one */
3536 #if JOBS
3537         int stopstatus;         /* status of a stopped job */
3538 #endif
3539         unsigned nprocs;        /* number of processes */
3540
3541 #define JOBRUNNING      0       /* at least one proc running */
3542 #define JOBSTOPPED      1       /* all procs are stopped */
3543 #define JOBDONE         2       /* all procs are completed */
3544         unsigned
3545                 state: 8,
3546 #if JOBS
3547                 sigint: 1,      /* job was killed by SIGINT */
3548                 jobctl: 1,      /* job running under job control */
3549 #endif
3550                 waited: 1,      /* true if this entry has been waited for */
3551                 used: 1,        /* true if this entry is in used */
3552                 changed: 1;     /* true if status has changed */
3553         struct job *prev_job;   /* previous job */
3554 };
3555
3556 static struct job *makejob(/*union node *,*/ int);
3557 static int forkshell(struct job *, union node *, int);
3558 static int waitforjob(struct job *);
3559
3560 #if !JOBS
3561 enum { doing_jobctl = 0 };
3562 #define setjobctl(on) do {} while (0)
3563 #else
3564 static smallint doing_jobctl; //references:8
3565 static void setjobctl(int);
3566 #endif
3567
3568 /*
3569  * Ignore a signal.
3570  */
3571 static void
3572 ignoresig(int signo)
3573 {
3574         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3575         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3576                 /* No, need to do it */
3577                 signal(signo, SIG_IGN);
3578         }
3579         sigmode[signo - 1] = S_HARD_IGN;
3580 }
3581
3582 /*
3583  * Only one usage site - in setsignal()
3584  */
3585 static void
3586 signal_handler(int signo)
3587 {
3588         if (signo == SIGCHLD) {
3589                 got_sigchld = 1;
3590                 if (!trap[SIGCHLD])
3591                         return;
3592         }
3593
3594         gotsig[signo - 1] = 1;
3595         pending_sig = signo;
3596
3597         if (signo == SIGINT && !trap[SIGINT]) {
3598                 if (!suppress_int) {
3599                         pending_sig = 0;
3600                         raise_interrupt(); /* does not return */
3601                 }
3602                 pending_int = 1;
3603         }
3604 }
3605
3606 /*
3607  * Set the signal handler for the specified signal.  The routine figures
3608  * out what it should be set to.
3609  */
3610 static void
3611 setsignal(int signo)
3612 {
3613         char *t;
3614         char cur_act, new_act;
3615         struct sigaction act;
3616
3617         t = trap[signo];
3618         new_act = S_DFL;
3619         if (t != NULL) { /* trap for this sig is set */
3620                 new_act = S_CATCH;
3621                 if (t[0] == '\0') /* trap is "": ignore this sig */
3622                         new_act = S_IGN;
3623         }
3624
3625         if (rootshell && new_act == S_DFL) {
3626                 switch (signo) {
3627                 case SIGINT:
3628                         if (iflag || minusc || sflag == 0)
3629                                 new_act = S_CATCH;
3630                         break;
3631                 case SIGQUIT:
3632 #if DEBUG
3633                         if (debug)
3634                                 break;
3635 #endif
3636                         /* man bash:
3637                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3638                          * commands run by bash have signal handlers
3639                          * set to the values inherited by the shell
3640                          * from its parent". */
3641                         new_act = S_IGN;
3642                         break;
3643                 case SIGTERM:
3644                         if (iflag)
3645                                 new_act = S_IGN;
3646                         break;
3647 #if JOBS
3648                 case SIGTSTP:
3649                 case SIGTTOU:
3650                         if (mflag)
3651                                 new_act = S_IGN;
3652                         break;
3653 #endif
3654                 }
3655         }
3656         /* if !rootshell, we reset SIGQUIT to DFL,
3657          * whereas we have to restore it to what shell got on entry.
3658          * This is handled by the fact that if signal was IGNored on entry,
3659          * then cur_act is S_HARD_IGN and we never change its sigaction
3660          * (see code below).
3661          */
3662
3663         if (signo == SIGCHLD)
3664                 new_act = S_CATCH;
3665
3666         t = &sigmode[signo - 1];
3667         cur_act = *t;
3668         if (cur_act == 0) {
3669                 /* current setting is not yet known */
3670                 if (sigaction(signo, NULL, &act)) {
3671                         /* pretend it worked; maybe we should give a warning,
3672                          * but other shells don't. We don't alter sigmode,
3673                          * so we retry every time.
3674                          * btw, in Linux it never fails. --vda */
3675                         return;
3676                 }
3677                 if (act.sa_handler == SIG_IGN) {
3678                         cur_act = S_HARD_IGN;
3679                         if (mflag
3680                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3681                         ) {
3682                                 cur_act = S_IGN;   /* don't hard ignore these */
3683                         }
3684                 }
3685                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3686                         /* installing SIG_DFL over SIG_DFL is a no-op */
3687                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3688                         *t = S_DFL;
3689                         return;
3690                 }
3691         }
3692         if (cur_act == S_HARD_IGN || cur_act == new_act)
3693                 return;
3694
3695         *t = new_act;
3696
3697         act.sa_handler = SIG_DFL;
3698         switch (new_act) {
3699         case S_CATCH:
3700                 act.sa_handler = signal_handler;
3701                 break;
3702         case S_IGN:
3703                 act.sa_handler = SIG_IGN;
3704                 break;
3705         }
3706         /* flags and mask matter only if !DFL and !IGN, but we do it
3707          * for all cases for more deterministic behavior:
3708          */
3709         act.sa_flags = 0; //TODO: why not SA_RESTART?
3710         sigfillset(&act.sa_mask);
3711
3712         sigaction_set(signo, &act);
3713 }
3714
3715 /* mode flags for set_curjob */
3716 #define CUR_DELETE 2
3717 #define CUR_RUNNING 1
3718 #define CUR_STOPPED 0
3719
3720 #if JOBS
3721 /* pgrp of shell on invocation */
3722 static int initialpgrp; //references:2
3723 static int ttyfd = -1; //5
3724 #endif
3725 /* array of jobs */
3726 static struct job *jobtab; //5
3727 /* size of array */
3728 static unsigned njobs; //4
3729 /* current job */
3730 static struct job *curjob; //lots
3731 /* number of presumed living untracked jobs */
3732 static int jobless; //4
3733
3734 #if 0
3735 /* Bash has a feature: it restores termios after a successful wait for
3736  * a foreground job which had at least one stopped or sigkilled member.
3737  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3738  * properly restoring tty state. Should we do this too?
3739  * A reproducer: ^Z an interactive python:
3740  *
3741  * # python
3742  * Python 2.7.12 (...)
3743  * >>> ^Z
3744  *      { python leaves tty in -icanon -echo state. We do survive that... }
3745  *  [1]+  Stopped                    python
3746  *      { ...however, next program (python #2) does not survive it well: }
3747  * # python
3748  * Python 2.7.12 (...)
3749  * >>> Traceback (most recent call last):
3750  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3751  *   File "<stdin>", line 1, in <module>
3752  * NameError: name 'qwerty' is not defined
3753  *
3754  * The implementation below is modeled on bash code and seems to work.
3755  * However, I'm not sure we should do this. For one: what if I'd fg
3756  * the stopped python instead? It'll be confused by "restored" tty state.
3757  */
3758 static struct termios shell_tty_info;
3759 static void
3760 get_tty_state(void)
3761 {
3762         if (rootshell && ttyfd >= 0)
3763                 tcgetattr(ttyfd, &shell_tty_info);
3764 }
3765 static void
3766 set_tty_state(void)
3767 {
3768         /* if (rootshell) - caller ensures this */
3769         if (ttyfd >= 0)
3770                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3771 }
3772 static int
3773 job_signal_status(struct job *jp)
3774 {
3775         int status;
3776         unsigned i;
3777         struct procstat *ps = jp->ps;
3778         for (i = 0; i < jp->nprocs; i++) {
3779                 status = ps[i].ps_status;
3780                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3781                         return status;
3782         }
3783         return 0;
3784 }
3785 static void
3786 restore_tty_if_stopped_or_signaled(struct job *jp)
3787 {
3788 //TODO: check what happens if we come from waitforjob() in expbackq()
3789         if (rootshell) {
3790                 int s = job_signal_status(jp);
3791                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3792                         set_tty_state();
3793         }
3794 }
3795 #else
3796 # define get_tty_state() ((void)0)
3797 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3798 #endif
3799
3800 static void
3801 set_curjob(struct job *jp, unsigned mode)
3802 {
3803         struct job *jp1;
3804         struct job **jpp, **curp;
3805
3806         /* first remove from list */
3807         jpp = curp = &curjob;
3808         while (1) {
3809                 jp1 = *jpp;
3810                 if (jp1 == jp)
3811                         break;
3812                 jpp = &jp1->prev_job;
3813         }
3814         *jpp = jp1->prev_job;
3815
3816         /* Then re-insert in correct position */
3817         jpp = curp;
3818         switch (mode) {
3819         default:
3820 #if DEBUG
3821                 abort();
3822 #endif
3823         case CUR_DELETE:
3824                 /* job being deleted */
3825                 break;
3826         case CUR_RUNNING:
3827                 /* newly created job or backgrounded job,
3828                  * put after all stopped jobs.
3829                  */
3830                 while (1) {
3831                         jp1 = *jpp;
3832 #if JOBS
3833                         if (!jp1 || jp1->state != JOBSTOPPED)
3834 #endif
3835                                 break;
3836                         jpp = &jp1->prev_job;
3837                 }
3838                 /* FALLTHROUGH */
3839 #if JOBS
3840         case CUR_STOPPED:
3841 #endif
3842                 /* newly stopped job - becomes curjob */
3843                 jp->prev_job = *jpp;
3844                 *jpp = jp;
3845                 break;
3846         }
3847 }
3848
3849 #if JOBS || DEBUG
3850 static int
3851 jobno(const struct job *jp)
3852 {
3853         return jp - jobtab + 1;
3854 }
3855 #endif
3856
3857 /*
3858  * Convert a job name to a job structure.
3859  */
3860 #if !JOBS
3861 #define getjob(name, getctl) getjob(name)
3862 #endif
3863 static struct job *
3864 getjob(const char *name, int getctl)
3865 {
3866         struct job *jp;
3867         struct job *found;
3868         const char *err_msg = "%s: no such job";
3869         unsigned num;
3870         int c;
3871         const char *p;
3872         char *(*match)(const char *, const char *);
3873
3874         jp = curjob;
3875         p = name;
3876         if (!p)
3877                 goto currentjob;
3878
3879         if (*p != '%')
3880                 goto err;
3881
3882         c = *++p;
3883         if (!c)
3884                 goto currentjob;
3885
3886         if (!p[1]) {
3887                 if (c == '+' || c == '%') {
3888  currentjob:
3889                         err_msg = "No current job";
3890                         goto check;
3891                 }
3892                 if (c == '-') {
3893                         if (jp)
3894                                 jp = jp->prev_job;
3895                         err_msg = "No previous job";
3896  check:
3897                         if (!jp)
3898                                 goto err;
3899                         goto gotit;
3900                 }
3901         }
3902
3903         if (is_number(p)) {
3904                 num = atoi(p);
3905                 if (num > 0 && num <= njobs) {
3906                         jp = jobtab + num - 1;
3907                         if (jp->used)
3908                                 goto gotit;
3909                         goto err;
3910                 }
3911         }
3912
3913         match = prefix;
3914         if (*p == '?') {
3915                 match = strstr;
3916                 p++;
3917         }
3918
3919         found = NULL;
3920         while (jp) {
3921                 if (match(jp->ps[0].ps_cmd, p)) {
3922                         if (found)
3923                                 goto err;
3924                         found = jp;
3925                         err_msg = "%s: ambiguous";
3926                 }
3927                 jp = jp->prev_job;
3928         }
3929         if (!found)
3930                 goto err;
3931         jp = found;
3932
3933  gotit:
3934 #if JOBS
3935         err_msg = "job %s not created under job control";
3936         if (getctl && jp->jobctl == 0)
3937                 goto err;
3938 #endif
3939         return jp;
3940  err:
3941         ash_msg_and_raise_error(err_msg, name);
3942 }
3943
3944 /*
3945  * Mark a job structure as unused.
3946  */
3947 static void
3948 freejob(struct job *jp)
3949 {
3950         struct procstat *ps;
3951         int i;
3952
3953         INT_OFF;
3954         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3955                 if (ps->ps_cmd != nullstr)
3956                         free(ps->ps_cmd);
3957         }
3958         if (jp->ps != &jp->ps0)
3959                 free(jp->ps);
3960         jp->used = 0;
3961         set_curjob(jp, CUR_DELETE);
3962         INT_ON;
3963 }
3964
3965 #if JOBS
3966 static void
3967 xtcsetpgrp(int fd, pid_t pgrp)
3968 {
3969         if (tcsetpgrp(fd, pgrp))
3970                 ash_msg_and_raise_perror("can't set tty process group");
3971 }
3972
3973 /*
3974  * Turn job control on and off.
3975  *
3976  * Note:  This code assumes that the third arg to ioctl is a character
3977  * pointer, which is true on Berkeley systems but not System V.  Since
3978  * System V doesn't have job control yet, this isn't a problem now.
3979  *
3980  * Called with interrupts off.
3981  */
3982 static void
3983 setjobctl(int on)
3984 {
3985         int fd;
3986         int pgrp;
3987
3988         if (on == doing_jobctl || rootshell == 0)
3989                 return;
3990         if (on) {
3991                 int ofd;
3992                 ofd = fd = open(_PATH_TTY, O_RDWR);
3993                 if (fd < 0) {
3994         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3995          * That sometimes helps to acquire controlling tty.
3996          * Obviously, a workaround for bugs when someone
3997          * failed to provide a controlling tty to bash! :) */
3998                         fd = 2;
3999                         while (!isatty(fd))
4000                                 if (--fd < 0)
4001                                         goto out;
4002                 }
4003                 /* fd is a tty at this point */
4004                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
4005                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
4006                         close(ofd);
4007                 if (fd < 0)
4008                         goto out; /* F_DUPFD failed */
4009                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
4010                         close_on_exec_on(fd);
4011                 while (1) { /* while we are in the background */
4012                         pgrp = tcgetpgrp(fd);
4013                         if (pgrp < 0) {
4014  out:
4015                                 ash_msg("can't access tty; job control turned off");
4016                                 mflag = on = 0;
4017                                 goto close;
4018                         }
4019                         if (pgrp == getpgrp())
4020                                 break;
4021                         killpg(0, SIGTTIN);
4022                 }
4023                 initialpgrp = pgrp;
4024
4025                 setsignal(SIGTSTP);
4026                 setsignal(SIGTTOU);
4027                 setsignal(SIGTTIN);
4028                 pgrp = rootpid;
4029                 setpgid(0, pgrp);
4030                 xtcsetpgrp(fd, pgrp);
4031         } else {
4032                 /* turning job control off */
4033                 fd = ttyfd;
4034                 pgrp = initialpgrp;
4035                 /* was xtcsetpgrp, but this can make exiting ash
4036                  * loop forever if pty is already deleted */
4037                 tcsetpgrp(fd, pgrp);
4038                 setpgid(0, pgrp);
4039                 setsignal(SIGTSTP);
4040                 setsignal(SIGTTOU);
4041                 setsignal(SIGTTIN);
4042  close:
4043                 if (fd >= 0)
4044                         close(fd);
4045                 fd = -1;
4046         }
4047         ttyfd = fd;
4048         doing_jobctl = on;
4049 }
4050
4051 static int FAST_FUNC
4052 killcmd(int argc, char **argv)
4053 {
4054         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4055                 int i = 1;
4056                 do {
4057                         if (argv[i][0] == '%') {
4058                                 /*
4059                                  * "kill %N" - job kill
4060                                  * Converting to pgrp / pid kill
4061                                  */
4062                                 struct job *jp;
4063                                 char *dst;
4064                                 int j, n;
4065
4066                                 jp = getjob(argv[i], 0);
4067                                 /*
4068                                  * In jobs started under job control, we signal
4069                                  * entire process group by kill -PGRP_ID.
4070                                  * This happens, f.e., in interactive shell.
4071                                  *
4072                                  * Otherwise, we signal each child via
4073                                  * kill PID1 PID2 PID3.
4074                                  * Testcases:
4075                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4076                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4077                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4078                                  */
4079                                 n = jp->nprocs; /* can't be 0 (I hope) */
4080                                 if (jp->jobctl)
4081                                         n = 1;
4082                                 dst = alloca(n * sizeof(int)*4);
4083                                 argv[i] = dst;
4084                                 for (j = 0; j < n; j++) {
4085                                         struct procstat *ps = &jp->ps[j];
4086                                         /* Skip non-running and not-stopped members
4087                                          * (i.e. dead members) of the job
4088                                          */
4089                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4090                                                 continue;
4091                                         /*
4092                                          * kill_main has matching code to expect
4093                                          * leading space. Needed to not confuse
4094                                          * negative pids with "kill -SIGNAL_NO" syntax
4095                                          */
4096                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4097                                 }
4098                                 *dst = '\0';
4099                         }
4100                 } while (argv[++i]);
4101         }
4102         return kill_main(argc, argv);
4103 }
4104
4105 static void
4106 showpipe(struct job *jp /*, FILE *out*/)
4107 {
4108         struct procstat *ps;
4109         struct procstat *psend;
4110
4111         psend = jp->ps + jp->nprocs;
4112         for (ps = jp->ps + 1; ps < psend; ps++)
4113                 printf(" | %s", ps->ps_cmd);
4114         newline_and_flush(stdout);
4115         flush_stdout_stderr();
4116 }
4117
4118
4119 static int
4120 restartjob(struct job *jp, int mode)
4121 {
4122         struct procstat *ps;
4123         int i;
4124         int status;
4125         pid_t pgid;
4126
4127         INT_OFF;
4128         if (jp->state == JOBDONE)
4129                 goto out;
4130         jp->state = JOBRUNNING;
4131         pgid = jp->ps[0].ps_pid;
4132         if (mode == FORK_FG) {
4133                 get_tty_state();
4134                 xtcsetpgrp(ttyfd, pgid);
4135         }
4136         killpg(pgid, SIGCONT);
4137         ps = jp->ps;
4138         i = jp->nprocs;
4139         do {
4140                 if (WIFSTOPPED(ps->ps_status)) {
4141                         ps->ps_status = -1;
4142                 }
4143                 ps++;
4144         } while (--i);
4145  out:
4146         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4147         INT_ON;
4148         return status;
4149 }
4150
4151 static int FAST_FUNC
4152 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4153 {
4154         struct job *jp;
4155         int mode;
4156         int retval;
4157
4158         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4159         nextopt(nullstr);
4160         argv = argptr;
4161         do {
4162                 jp = getjob(*argv, 1);
4163                 if (mode == FORK_BG) {
4164                         set_curjob(jp, CUR_RUNNING);
4165                         printf("[%d] ", jobno(jp));
4166                 }
4167                 out1str(jp->ps[0].ps_cmd);
4168                 showpipe(jp /*, stdout*/);
4169                 retval = restartjob(jp, mode);
4170         } while (*argv && *++argv);
4171         return retval;
4172 }
4173 #endif
4174
4175 static int
4176 sprint_status48(char *s, int status, int sigonly)
4177 {
4178         int col;
4179         int st;
4180
4181         col = 0;
4182         if (!WIFEXITED(status)) {
4183 #if JOBS
4184                 if (WIFSTOPPED(status))
4185                         st = WSTOPSIG(status);
4186                 else
4187 #endif
4188                         st = WTERMSIG(status);
4189                 if (sigonly) {
4190                         if (st == SIGINT || st == SIGPIPE)
4191                                 goto out;
4192 #if JOBS
4193                         if (WIFSTOPPED(status))
4194                                 goto out;
4195 #endif
4196                 }
4197                 st &= 0x7f;
4198 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4199                 col = fmtstr(s, 32, strsignal(st));
4200                 if (WCOREDUMP(status)) {
4201                         strcpy(s + col, " (core dumped)");
4202                         col += sizeof(" (core dumped)")-1;
4203                 }
4204         } else if (!sigonly) {
4205                 st = WEXITSTATUS(status);
4206                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4207         }
4208  out:
4209         return col;
4210 }
4211
4212 static int
4213 wait_block_or_sig(int *status)
4214 {
4215         int pid;
4216
4217         do {
4218                 sigset_t mask;
4219
4220                 /* Poll all children for changes in their state */
4221                 got_sigchld = 0;
4222                 /* if job control is active, accept stopped processes too */
4223                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4224                 if (pid != 0)
4225                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4226
4227                 /* Children exist, but none are ready. Sleep until interesting signal */
4228 #if 1
4229                 sigfillset(&mask);
4230                 sigprocmask(SIG_SETMASK, &mask, &mask);
4231                 while (!got_sigchld && !pending_sig)
4232                         sigsuspend(&mask);
4233                 sigprocmask(SIG_SETMASK, &mask, NULL);
4234 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4235                 while (!got_sigchld && !pending_sig)
4236                         pause();
4237 #endif
4238
4239                 /* If it was SIGCHLD, poll children again */
4240         } while (got_sigchld);
4241
4242         return pid;
4243 }
4244
4245 #define DOWAIT_NONBLOCK 0
4246 #define DOWAIT_BLOCK    1
4247 #define DOWAIT_BLOCK_OR_SIG 2
4248
4249 static int
4250 dowait(int block, struct job *job)
4251 {
4252         int pid;
4253         int status;
4254         struct job *jp;
4255         struct job *thisjob = NULL;
4256
4257         TRACE(("dowait(0x%x) called\n", block));
4258
4259         /* It's wrong to call waitpid() outside of INT_OFF region:
4260          * signal can arrive just after syscall return and handler can
4261          * longjmp away, losing stop/exit notification processing.
4262          * Thus, for "jobs" builtin, and for waiting for a fg job,
4263          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4264          *
4265          * However, for "wait" builtin it is wrong to simply call waitpid()
4266          * in INT_OFF region: "wait" needs to wait for any running job
4267          * to change state, but should exit on any trap too.
4268          * In INT_OFF region, a signal just before syscall entry can set
4269          * pending_sig variables, but we can't check them, and we would
4270          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4271          *
4272          * Because of this, we run inside INT_OFF, but use a special routine
4273          * which combines waitpid() and sigsuspend().
4274          * This is the reason why we need to have a handler for SIGCHLD:
4275          * SIG_DFL handler does not wake sigsuspend().
4276          */
4277         INT_OFF;
4278         if (block == DOWAIT_BLOCK_OR_SIG) {
4279                 pid = wait_block_or_sig(&status);
4280         } else {
4281                 int wait_flags = 0;
4282                 if (block == DOWAIT_NONBLOCK)
4283                         wait_flags = WNOHANG;
4284                 /* if job control is active, accept stopped processes too */
4285                 if (doing_jobctl)
4286                         wait_flags |= WUNTRACED;
4287                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4288                 pid = waitpid(-1, &status, wait_flags);
4289         }
4290         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4291                                 pid, status, errno, strerror(errno)));
4292         if (pid <= 0)
4293                 goto out;
4294
4295         thisjob = NULL;
4296         for (jp = curjob; jp; jp = jp->prev_job) {
4297                 int jobstate;
4298                 struct procstat *ps;
4299                 struct procstat *psend;
4300                 if (jp->state == JOBDONE)
4301                         continue;
4302                 jobstate = JOBDONE;
4303                 ps = jp->ps;
4304                 psend = ps + jp->nprocs;
4305                 do {
4306                         if (ps->ps_pid == pid) {
4307                                 TRACE(("Job %d: changing status of proc %d "
4308                                         "from 0x%x to 0x%x\n",
4309                                         jobno(jp), pid, ps->ps_status, status));
4310                                 ps->ps_status = status;
4311                                 thisjob = jp;
4312                         }
4313                         if (ps->ps_status == -1)
4314                                 jobstate = JOBRUNNING;
4315 #if JOBS
4316                         if (jobstate == JOBRUNNING)
4317                                 continue;
4318                         if (WIFSTOPPED(ps->ps_status)) {
4319                                 jp->stopstatus = ps->ps_status;
4320                                 jobstate = JOBSTOPPED;
4321                         }
4322 #endif
4323                 } while (++ps < psend);
4324                 if (!thisjob)
4325                         continue;
4326
4327                 /* Found the job where one of its processes changed its state.
4328                  * Is there at least one live and running process in this job? */
4329                 if (jobstate != JOBRUNNING) {
4330                         /* No. All live processes in the job are stopped
4331                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4332                          */
4333                         thisjob->changed = 1;
4334                         if (thisjob->state != jobstate) {
4335                                 TRACE(("Job %d: changing state from %d to %d\n",
4336                                         jobno(thisjob), thisjob->state, jobstate));
4337                                 thisjob->state = jobstate;
4338 #if JOBS
4339                                 if (jobstate == JOBSTOPPED)
4340                                         set_curjob(thisjob, CUR_STOPPED);
4341 #endif
4342                         }
4343                 }
4344                 goto out;
4345         }
4346         /* The process wasn't found in job list */
4347 #if JOBS
4348         if (!WIFSTOPPED(status))
4349                 jobless--;
4350 #endif
4351  out:
4352         INT_ON;
4353
4354         if (thisjob && thisjob == job) {
4355                 char s[48 + 1];
4356                 int len;
4357
4358                 len = sprint_status48(s, status, 1);
4359                 if (len) {
4360                         s[len] = '\n';
4361                         s[len + 1] = '\0';
4362                         out2str(s);
4363                 }
4364         }
4365         return pid;
4366 }
4367
4368 #if JOBS
4369 static void
4370 showjob(struct job *jp, int mode)
4371 {
4372         struct procstat *ps;
4373         struct procstat *psend;
4374         int col;
4375         int indent_col;
4376         char s[16 + 16 + 48];
4377         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4378
4379         ps = jp->ps;
4380
4381         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4382                 /* just output process (group) id of pipeline */
4383                 fprintf(out, "%d\n", ps->ps_pid);
4384                 return;
4385         }
4386
4387         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4388         indent_col = col;
4389
4390         if (jp == curjob)
4391                 s[col - 3] = '+';
4392         else if (curjob && jp == curjob->prev_job)
4393                 s[col - 3] = '-';
4394
4395         if (mode & SHOW_PIDS)
4396                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4397
4398         psend = ps + jp->nprocs;
4399
4400         if (jp->state == JOBRUNNING) {
4401                 strcpy(s + col, "Running");
4402                 col += sizeof("Running") - 1;
4403         } else {
4404                 int status = psend[-1].ps_status;
4405                 if (jp->state == JOBSTOPPED)
4406                         status = jp->stopstatus;
4407                 col += sprint_status48(s + col, status, 0);
4408         }
4409         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4410
4411         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4412          * or prints several "PID             | <cmdN>" lines,
4413          * depending on SHOW_PIDS bit.
4414          * We do not print status of individual processes
4415          * between PID and <cmdN>. bash does it, but not very well:
4416          * first line shows overall job status, not process status,
4417          * making it impossible to know 1st process status.
4418          */
4419         goto start;
4420         do {
4421                 /* for each process */
4422                 s[0] = '\0';
4423                 col = 33;
4424                 if (mode & SHOW_PIDS)
4425                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4426  start:
4427                 fprintf(out, "%s%*c%s%s",
4428                                 s,
4429                                 33 - col >= 0 ? 33 - col : 0, ' ',
4430                                 ps == jp->ps ? "" : "| ",
4431                                 ps->ps_cmd
4432                 );
4433         } while (++ps != psend);
4434         newline_and_flush(out);
4435
4436         jp->changed = 0;
4437
4438         if (jp->state == JOBDONE) {
4439                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4440                 freejob(jp);
4441         }
4442 }
4443
4444 /*
4445  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4446  * statuses have changed since the last call to showjobs.
4447  */
4448 static void
4449 showjobs(int mode)
4450 {
4451         struct job *jp;
4452
4453         TRACE(("showjobs(0x%x) called\n", mode));
4454
4455         /* Handle all finished jobs */
4456         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4457                 continue;
4458
4459         for (jp = curjob; jp; jp = jp->prev_job) {
4460                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4461                         showjob(jp, mode);
4462                 }
4463         }
4464 }
4465
4466 static int FAST_FUNC
4467 jobscmd(int argc UNUSED_PARAM, char **argv)
4468 {
4469         int mode, m;
4470
4471         mode = 0;
4472         while ((m = nextopt("lp")) != '\0') {
4473                 if (m == 'l')
4474                         mode |= SHOW_PIDS;
4475                 else
4476                         mode |= SHOW_ONLY_PGID;
4477         }
4478
4479         argv = argptr;
4480         if (*argv) {
4481                 do
4482                         showjob(getjob(*argv, 0), mode);
4483                 while (*++argv);
4484         } else {
4485                 showjobs(mode);
4486         }
4487
4488         return 0;
4489 }
4490 #endif /* JOBS */
4491
4492 /* Called only on finished or stopped jobs (no members are running) */
4493 static int
4494 getstatus(struct job *job)
4495 {
4496         int status;
4497         int retval;
4498         struct procstat *ps;
4499
4500         /* Fetch last member's status */
4501         ps = job->ps + job->nprocs - 1;
4502         status = ps->ps_status;
4503         if (pipefail) {
4504                 /* "set -o pipefail" mode: use last _nonzero_ status */
4505                 while (status == 0 && --ps >= job->ps)
4506                         status = ps->ps_status;
4507         }
4508
4509         retval = WEXITSTATUS(status);
4510         if (!WIFEXITED(status)) {
4511 #if JOBS
4512                 retval = WSTOPSIG(status);
4513                 if (!WIFSTOPPED(status))
4514 #endif
4515                 {
4516                         /* XXX: limits number of signals */
4517                         retval = WTERMSIG(status);
4518 #if JOBS
4519                         if (retval == SIGINT)
4520                                 job->sigint = 1;
4521 #endif
4522                 }
4523                 retval += 128;
4524         }
4525         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4526                 jobno(job), job->nprocs, status, retval));
4527         return retval;
4528 }
4529
4530 static int FAST_FUNC
4531 waitcmd(int argc UNUSED_PARAM, char **argv)
4532 {
4533         struct job *job;
4534         int retval;
4535         struct job *jp;
4536
4537         nextopt(nullstr);
4538         retval = 0;
4539
4540         argv = argptr;
4541         if (!*argv) {
4542                 /* wait for all jobs */
4543                 for (;;) {
4544                         jp = curjob;
4545                         while (1) {
4546                                 if (!jp) /* no running procs */
4547                                         goto ret;
4548                                 if (jp->state == JOBRUNNING)
4549                                         break;
4550                                 jp->waited = 1;
4551                                 jp = jp->prev_job;
4552                         }
4553         /* man bash:
4554          * "When bash is waiting for an asynchronous command via
4555          * the wait builtin, the reception of a signal for which a trap
4556          * has been set will cause the wait builtin to return immediately
4557          * with an exit status greater than 128, immediately after which
4558          * the trap is executed."
4559          */
4560                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4561         /* if child sends us a signal *and immediately exits*,
4562          * dowait() returns pid > 0. Check this case,
4563          * not "if (dowait() < 0)"!
4564          */
4565                         if (pending_sig)
4566                                 goto sigout;
4567                 }
4568         }
4569
4570         retval = 127;
4571         do {
4572                 if (**argv != '%') {
4573                         pid_t pid = number(*argv);
4574                         job = curjob;
4575                         while (1) {
4576                                 if (!job)
4577                                         goto repeat;
4578                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4579                                         break;
4580                                 job = job->prev_job;
4581                         }
4582                 } else {
4583                         job = getjob(*argv, 0);
4584                 }
4585                 /* loop until process terminated or stopped */
4586                 while (job->state == JOBRUNNING) {
4587                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4588                         if (pending_sig)
4589                                 goto sigout;
4590                 }
4591                 job->waited = 1;
4592                 retval = getstatus(job);
4593  repeat: ;
4594         } while (*++argv);
4595
4596  ret:
4597         return retval;
4598  sigout:
4599         retval = 128 + pending_sig;
4600         return retval;
4601 }
4602
4603 static struct job *
4604 growjobtab(void)
4605 {
4606         size_t len;
4607         ptrdiff_t offset;
4608         struct job *jp, *jq;
4609
4610         len = njobs * sizeof(*jp);
4611         jq = jobtab;
4612         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4613
4614         offset = (char *)jp - (char *)jq;
4615         if (offset) {
4616                 /* Relocate pointers */
4617                 size_t l = len;
4618
4619                 jq = (struct job *)((char *)jq + l);
4620                 while (l) {
4621                         l -= sizeof(*jp);
4622                         jq--;
4623 #define joff(p) ((struct job *)((char *)(p) + l))
4624 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4625                         if (joff(jp)->ps == &jq->ps0)
4626                                 jmove(joff(jp)->ps);
4627                         if (joff(jp)->prev_job)
4628                                 jmove(joff(jp)->prev_job);
4629                 }
4630                 if (curjob)
4631                         jmove(curjob);
4632 #undef joff
4633 #undef jmove
4634         }
4635
4636         njobs += 4;
4637         jobtab = jp;
4638         jp = (struct job *)((char *)jp + len);
4639         jq = jp + 3;
4640         do {
4641                 jq->used = 0;
4642         } while (--jq >= jp);
4643         return jp;
4644 }
4645
4646 /*
4647  * Return a new job structure.
4648  * Called with interrupts off.
4649  */
4650 static struct job *
4651 makejob(/*union node *node,*/ int nprocs)
4652 {
4653         int i;
4654         struct job *jp;
4655
4656         for (i = njobs, jp = jobtab; ; jp++) {
4657                 if (--i < 0) {
4658                         jp = growjobtab();
4659                         break;
4660                 }
4661                 if (jp->used == 0)
4662                         break;
4663                 if (jp->state != JOBDONE || !jp->waited)
4664                         continue;
4665 #if JOBS
4666                 if (doing_jobctl)
4667                         continue;
4668 #endif
4669                 freejob(jp);
4670                 break;
4671         }
4672         memset(jp, 0, sizeof(*jp));
4673 #if JOBS
4674         /* jp->jobctl is a bitfield.
4675          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4676         if (doing_jobctl)
4677                 jp->jobctl = 1;
4678 #endif
4679         jp->prev_job = curjob;
4680         curjob = jp;
4681         jp->used = 1;
4682         jp->ps = &jp->ps0;
4683         if (nprocs > 1) {
4684                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4685         }
4686         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4687                                 jobno(jp)));
4688         return jp;
4689 }
4690
4691 #if JOBS
4692 /*
4693  * Return a string identifying a command (to be printed by the
4694  * jobs command).
4695  */
4696 static char *cmdnextc;
4697
4698 static void
4699 cmdputs(const char *s)
4700 {
4701         static const char vstype[VSTYPE + 1][3] = {
4702                 "", "}", "-", "+", "?", "=",
4703                 "%", "%%", "#", "##"
4704                 IF_BASH_SUBSTR(, ":")
4705                 IF_BASH_PATTERN_SUBST(, "/", "//")
4706         };
4707
4708         const char *p, *str;
4709         char cc[2];
4710         char *nextc;
4711         unsigned char c;
4712         unsigned char subtype = 0;
4713         int quoted = 0;
4714
4715         cc[1] = '\0';
4716         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4717         p = s;
4718         while ((c = *p++) != '\0') {
4719                 str = NULL;
4720                 switch (c) {
4721                 case CTLESC:
4722                         c = *p++;
4723                         break;
4724                 case CTLVAR:
4725                         subtype = *p++;
4726                         if ((subtype & VSTYPE) == VSLENGTH)
4727                                 str = "${#";
4728                         else
4729                                 str = "${";
4730                         goto dostr;
4731                 case CTLENDVAR:
4732                         str = "\"}" + !(quoted & 1);
4733                         quoted >>= 1;
4734                         subtype = 0;
4735                         goto dostr;
4736                 case CTLBACKQ:
4737                         str = "$(...)";
4738                         goto dostr;
4739 #if ENABLE_FEATURE_SH_MATH
4740                 case CTLARI:
4741                         str = "$((";
4742                         goto dostr;
4743                 case CTLENDARI:
4744                         str = "))";
4745                         goto dostr;
4746 #endif
4747                 case CTLQUOTEMARK:
4748                         quoted ^= 1;
4749                         c = '"';
4750                         break;
4751                 case '=':
4752                         if (subtype == 0)
4753                                 break;
4754                         if ((subtype & VSTYPE) != VSNORMAL)
4755                                 quoted <<= 1;
4756                         str = vstype[subtype & VSTYPE];
4757                         if (subtype & VSNUL)
4758                                 c = ':';
4759                         else
4760                                 goto checkstr;
4761                         break;
4762                 case '\'':
4763                 case '\\':
4764                 case '"':
4765                 case '$':
4766                         /* These can only happen inside quotes */
4767                         cc[0] = c;
4768                         str = cc;
4769 //FIXME:
4770 // $ true $$ &
4771 // $ <cr>
4772 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4773                         c = '\\';
4774                         break;
4775                 default:
4776                         break;
4777                 }
4778                 USTPUTC(c, nextc);
4779  checkstr:
4780                 if (!str)
4781                         continue;
4782  dostr:
4783                 while ((c = *str++) != '\0') {
4784                         USTPUTC(c, nextc);
4785                 }
4786         } /* while *p++ not NUL */
4787
4788         if (quoted & 1) {
4789                 USTPUTC('"', nextc);
4790         }
4791         *nextc = 0;
4792         cmdnextc = nextc;
4793 }
4794
4795 /* cmdtxt() and cmdlist() call each other */
4796 static void cmdtxt(union node *n);
4797
4798 static void
4799 cmdlist(union node *np, int sep)
4800 {
4801         for (; np; np = np->narg.next) {
4802                 if (!sep)
4803                         cmdputs(" ");
4804                 cmdtxt(np);
4805                 if (sep && np->narg.next)
4806                         cmdputs(" ");
4807         }
4808 }
4809
4810 static void
4811 cmdtxt(union node *n)
4812 {
4813         union node *np;
4814         struct nodelist *lp;
4815         const char *p;
4816
4817         if (!n)
4818                 return;
4819         switch (n->type) {
4820         default:
4821 #if DEBUG
4822                 abort();
4823 #endif
4824         case NPIPE:
4825                 lp = n->npipe.cmdlist;
4826                 for (;;) {
4827                         cmdtxt(lp->n);
4828                         lp = lp->next;
4829                         if (!lp)
4830                                 break;
4831                         cmdputs(" | ");
4832                 }
4833                 break;
4834         case NSEMI:
4835                 p = "; ";
4836                 goto binop;
4837         case NAND:
4838                 p = " && ";
4839                 goto binop;
4840         case NOR:
4841                 p = " || ";
4842  binop:
4843                 cmdtxt(n->nbinary.ch1);
4844                 cmdputs(p);
4845                 n = n->nbinary.ch2;
4846                 goto donode;
4847         case NREDIR:
4848         case NBACKGND:
4849                 n = n->nredir.n;
4850                 goto donode;
4851         case NNOT:
4852                 cmdputs("!");
4853                 n = n->nnot.com;
4854  donode:
4855                 cmdtxt(n);
4856                 break;
4857         case NIF:
4858                 cmdputs("if ");
4859                 cmdtxt(n->nif.test);
4860                 cmdputs("; then ");
4861                 if (n->nif.elsepart) {
4862                         cmdtxt(n->nif.ifpart);
4863                         cmdputs("; else ");
4864                         n = n->nif.elsepart;
4865                 } else {
4866                         n = n->nif.ifpart;
4867                 }
4868                 p = "; fi";
4869                 goto dotail;
4870         case NSUBSHELL:
4871                 cmdputs("(");
4872                 n = n->nredir.n;
4873                 p = ")";
4874                 goto dotail;
4875         case NWHILE:
4876                 p = "while ";
4877                 goto until;
4878         case NUNTIL:
4879                 p = "until ";
4880  until:
4881                 cmdputs(p);
4882                 cmdtxt(n->nbinary.ch1);
4883                 n = n->nbinary.ch2;
4884                 p = "; done";
4885  dodo:
4886                 cmdputs("; do ");
4887  dotail:
4888                 cmdtxt(n);
4889                 goto dotail2;
4890         case NFOR:
4891                 cmdputs("for ");
4892                 cmdputs(n->nfor.var);
4893                 cmdputs(" in ");
4894                 cmdlist(n->nfor.args, 1);
4895                 n = n->nfor.body;
4896                 p = "; done";
4897                 goto dodo;
4898         case NDEFUN:
4899                 cmdputs(n->ndefun.text);
4900                 p = "() { ... }";
4901                 goto dotail2;
4902         case NCMD:
4903                 cmdlist(n->ncmd.args, 1);
4904                 cmdlist(n->ncmd.redirect, 0);
4905                 break;
4906         case NARG:
4907                 p = n->narg.text;
4908  dotail2:
4909                 cmdputs(p);
4910                 break;
4911         case NHERE:
4912         case NXHERE:
4913                 p = "<<...";
4914                 goto dotail2;
4915         case NCASE:
4916                 cmdputs("case ");
4917                 cmdputs(n->ncase.expr->narg.text);
4918                 cmdputs(" in ");
4919                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4920                         cmdtxt(np->nclist.pattern);
4921                         cmdputs(") ");
4922                         cmdtxt(np->nclist.body);
4923                         cmdputs(";; ");
4924                 }
4925                 p = "esac";
4926                 goto dotail2;
4927         case NTO:
4928                 p = ">";
4929                 goto redir;
4930         case NCLOBBER:
4931                 p = ">|";
4932                 goto redir;
4933         case NAPPEND:
4934                 p = ">>";
4935                 goto redir;
4936 #if BASH_REDIR_OUTPUT
4937         case NTO2:
4938 #endif
4939         case NTOFD:
4940                 p = ">&";
4941                 goto redir;
4942         case NFROM:
4943                 p = "<";
4944                 goto redir;
4945         case NFROMFD:
4946                 p = "<&";
4947                 goto redir;
4948         case NFROMTO:
4949                 p = "<>";
4950  redir:
4951                 cmdputs(utoa(n->nfile.fd));
4952                 cmdputs(p);
4953                 if (n->type == NTOFD || n->type == NFROMFD) {
4954                         if (n->ndup.dupfd >= 0)
4955                                 cmdputs(utoa(n->ndup.dupfd));
4956                         else
4957                                 cmdputs("-");
4958                         break;
4959                 }
4960                 n = n->nfile.fname;
4961                 goto donode;
4962         }
4963 }
4964
4965 static char *
4966 commandtext(union node *n)
4967 {
4968         char *name;
4969
4970         STARTSTACKSTR(cmdnextc);
4971         cmdtxt(n);
4972         name = stackblock();
4973         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4974         return ckstrdup(name);
4975 }
4976 #endif /* JOBS */
4977
4978 /*
4979  * Fork off a subshell.  If we are doing job control, give the subshell its
4980  * own process group.  Jp is a job structure that the job is to be added to.
4981  * N is the command that will be evaluated by the child.  Both jp and n may
4982  * be NULL.  The mode parameter can be one of the following:
4983  *      FORK_FG - Fork off a foreground process.
4984  *      FORK_BG - Fork off a background process.
4985  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4986  *                   process group even if job control is on.
4987  *
4988  * When job control is turned off, background processes have their standard
4989  * input redirected to /dev/null (except for the second and later processes
4990  * in a pipeline).
4991  *
4992  * Called with interrupts off.
4993  */
4994 /*
4995  * Clear traps on a fork.
4996  */
4997 static void
4998 clear_traps(void)
4999 {
5000         char **tp;
5001
5002         INT_OFF;
5003         for (tp = trap; tp < &trap[NSIG]; tp++) {
5004                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
5005                         if (trap_ptr == trap)
5006                                 free(*tp);
5007                         /* else: it "belongs" to trap_ptr vector, don't free */
5008                         *tp = NULL;
5009                         if ((tp - trap) != 0)
5010                                 setsignal(tp - trap);
5011                 }
5012         }
5013         may_have_traps = 0;
5014         INT_ON;
5015 }
5016
5017 /* Lives far away from here, needed for forkchild */
5018 static void closescript(void);
5019
5020 /* Called after fork(), in child */
5021 /* jp and n are NULL when called by openhere() for heredoc support */
5022 static NOINLINE void
5023 forkchild(struct job *jp, union node *n, int mode)
5024 {
5025         int oldlvl;
5026
5027         TRACE(("Child shell %d\n", getpid()));
5028         oldlvl = shlvl;
5029         shlvl++;
5030
5031         /* man bash: "Non-builtin commands run by bash have signal handlers
5032          * set to the values inherited by the shell from its parent".
5033          * Do we do it correctly? */
5034
5035         closescript();
5036
5037         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5038          && n && n->type == NCMD        /* is it single cmd? */
5039         /* && n->ncmd.args->type == NARG - always true? */
5040          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5041          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5042         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5043         ) {
5044                 TRACE(("Trap hack\n"));
5045                 /* Awful hack for `trap` or $(trap).
5046                  *
5047                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5048                  * contains an example where "trap" is executed in a subshell:
5049                  *
5050                  * save_traps=$(trap)
5051                  * ...
5052                  * eval "$save_traps"
5053                  *
5054                  * Standard does not say that "trap" in subshell shall print
5055                  * parent shell's traps. It only says that its output
5056                  * must have suitable form, but then, in the above example
5057                  * (which is not supposed to be normative), it implies that.
5058                  *
5059                  * bash (and probably other shell) does implement it
5060                  * (traps are reset to defaults, but "trap" still shows them),
5061                  * but as a result, "trap" logic is hopelessly messed up:
5062                  *
5063                  * # trap
5064                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5065                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5066                  * # true | trap   <--- trap is in subshell - no output (ditto)
5067                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5068                  * trap -- 'echo Ho' SIGWINCH
5069                  * # echo `(trap)`         <--- in subshell in subshell - output
5070                  * trap -- 'echo Ho' SIGWINCH
5071                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5072                  * trap -- 'echo Ho' SIGWINCH
5073                  *
5074                  * The rules when to forget and when to not forget traps
5075                  * get really complex and nonsensical.
5076                  *
5077                  * Our solution: ONLY bare $(trap) or `trap` is special.
5078                  */
5079                 /* Save trap handler strings for trap builtin to print */
5080                 trap_ptr = xmemdup(trap, sizeof(trap));
5081                 /* Fall through into clearing traps */
5082         }
5083         clear_traps();
5084 #if JOBS
5085         /* do job control only in root shell */
5086         doing_jobctl = 0;
5087         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5088                 pid_t pgrp;
5089
5090                 if (jp->nprocs == 0)
5091                         pgrp = getpid();
5092                 else
5093                         pgrp = jp->ps[0].ps_pid;
5094                 /* this can fail because we are doing it in the parent also */
5095                 setpgid(0, pgrp);
5096                 if (mode == FORK_FG)
5097                         xtcsetpgrp(ttyfd, pgrp);
5098                 setsignal(SIGTSTP);
5099                 setsignal(SIGTTOU);
5100         } else
5101 #endif
5102         if (mode == FORK_BG) {
5103                 /* man bash: "When job control is not in effect,
5104                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5105                 ignoresig(SIGINT);
5106                 ignoresig(SIGQUIT);
5107                 if (jp->nprocs == 0) {
5108                         close(0);
5109                         if (open(bb_dev_null, O_RDONLY) != 0)
5110                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5111                 }
5112         }
5113         if (oldlvl == 0) {
5114                 if (iflag) { /* why if iflag only? */
5115                         setsignal(SIGINT);
5116                         setsignal(SIGTERM);
5117                 }
5118                 /* man bash:
5119                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5120                  * commands run by bash have signal handlers
5121                  * set to the values inherited by the shell
5122                  * from its parent".
5123                  * Take care of the second rule: */
5124                 setsignal(SIGQUIT);
5125         }
5126 #if JOBS
5127         if (n && n->type == NCMD
5128          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5129         ) {
5130                 TRACE(("Job hack\n"));
5131                 /* "jobs": we do not want to clear job list for it,
5132                  * instead we remove only _its_ own_ job from job list.
5133                  * This makes "jobs .... | cat" more useful.
5134                  */
5135                 freejob(curjob);
5136                 return;
5137         }
5138 #endif
5139         for (jp = curjob; jp; jp = jp->prev_job)
5140                 freejob(jp);
5141         jobless = 0;
5142 }
5143
5144 /* Called after fork(), in parent */
5145 #if !JOBS
5146 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5147 #endif
5148 static void
5149 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5150 {
5151         TRACE(("In parent shell: child = %d\n", pid));
5152         if (!jp) {
5153                 /* jp is NULL when called by openhere() for heredoc support */
5154                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5155                         continue;
5156                 jobless++;
5157                 return;
5158         }
5159 #if JOBS
5160         if (mode != FORK_NOJOB && jp->jobctl) {
5161                 int pgrp;
5162
5163                 if (jp->nprocs == 0)
5164                         pgrp = pid;
5165                 else
5166                         pgrp = jp->ps[0].ps_pid;
5167                 /* This can fail because we are doing it in the child also */
5168                 setpgid(pid, pgrp);
5169         }
5170 #endif
5171         if (mode == FORK_BG) {
5172                 backgndpid = pid;               /* set $! */
5173                 set_curjob(jp, CUR_RUNNING);
5174         }
5175         if (jp) {
5176                 struct procstat *ps = &jp->ps[jp->nprocs++];
5177                 ps->ps_pid = pid;
5178                 ps->ps_status = -1;
5179                 ps->ps_cmd = nullstr;
5180 #if JOBS
5181                 if (doing_jobctl && n)
5182                         ps->ps_cmd = commandtext(n);
5183 #endif
5184         }
5185 }
5186
5187 /* jp and n are NULL when called by openhere() for heredoc support */
5188 static int
5189 forkshell(struct job *jp, union node *n, int mode)
5190 {
5191         int pid;
5192
5193         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5194         pid = fork();
5195         if (pid < 0) {
5196                 TRACE(("Fork failed, errno=%d", errno));
5197                 if (jp)
5198                         freejob(jp);
5199                 ash_msg_and_raise_perror("can't fork");
5200         }
5201         if (pid == 0) {
5202                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5203                 forkchild(jp, n, mode);
5204         } else {
5205                 forkparent(jp, n, mode, pid);
5206         }
5207         return pid;
5208 }
5209
5210 /*
5211  * Wait for job to finish.
5212  *
5213  * Under job control we have the problem that while a child process
5214  * is running interrupts generated by the user are sent to the child
5215  * but not to the shell.  This means that an infinite loop started by
5216  * an interactive user may be hard to kill.  With job control turned off,
5217  * an interactive user may place an interactive program inside a loop.
5218  * If the interactive program catches interrupts, the user doesn't want
5219  * these interrupts to also abort the loop.  The approach we take here
5220  * is to have the shell ignore interrupt signals while waiting for a
5221  * foreground process to terminate, and then send itself an interrupt
5222  * signal if the child process was terminated by an interrupt signal.
5223  * Unfortunately, some programs want to do a bit of cleanup and then
5224  * exit on interrupt; unless these processes terminate themselves by
5225  * sending a signal to themselves (instead of calling exit) they will
5226  * confuse this approach.
5227  *
5228  * Called with interrupts off.
5229  */
5230 static int
5231 waitforjob(struct job *jp)
5232 {
5233         int st;
5234
5235         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5236
5237         INT_OFF;
5238         while (jp->state == JOBRUNNING) {
5239                 /* In non-interactive shells, we _can_ get
5240                  * a keyboard signal here and be EINTRed,
5241                  * but we just loop back, waiting for command to complete.
5242                  *
5243                  * man bash:
5244                  * "If bash is waiting for a command to complete and receives
5245                  * a signal for which a trap has been set, the trap
5246                  * will not be executed until the command completes."
5247                  *
5248                  * Reality is that even if trap is not set, bash
5249                  * will not act on the signal until command completes.
5250                  * Try this. sleep5intoff.c:
5251                  * #include <signal.h>
5252                  * #include <unistd.h>
5253                  * int main() {
5254                  *         sigset_t set;
5255                  *         sigemptyset(&set);
5256                  *         sigaddset(&set, SIGINT);
5257                  *         sigaddset(&set, SIGQUIT);
5258                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5259                  *         sleep(5);
5260                  *         return 0;
5261                  * }
5262                  * $ bash -c './sleep5intoff; echo hi'
5263                  * ^C^C^C^C <--- pressing ^C once a second
5264                  * $ _
5265                  * $ bash -c './sleep5intoff; echo hi'
5266                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5267                  * $ _
5268                  */
5269                 dowait(DOWAIT_BLOCK, jp);
5270         }
5271         INT_ON;
5272
5273         st = getstatus(jp);
5274 #if JOBS
5275         if (jp->jobctl) {
5276                 xtcsetpgrp(ttyfd, rootpid);
5277                 restore_tty_if_stopped_or_signaled(jp);
5278
5279                 /*
5280                  * This is truly gross.
5281                  * If we're doing job control, then we did a TIOCSPGRP which
5282                  * caused us (the shell) to no longer be in the controlling
5283                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5284                  * intuit from the subprocess exit status whether a SIGINT
5285                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5286                  */
5287                 if (jp->sigint) /* TODO: do the same with all signals */
5288                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5289         }
5290         if (jp->state == JOBDONE)
5291 #endif
5292                 freejob(jp);
5293         return st;
5294 }
5295
5296 /*
5297  * return 1 if there are stopped jobs, otherwise 0
5298  */
5299 static int
5300 stoppedjobs(void)
5301 {
5302         struct job *jp;
5303         int retval;
5304
5305         retval = 0;
5306         if (job_warning)
5307                 goto out;
5308         jp = curjob;
5309         if (jp && jp->state == JOBSTOPPED) {
5310                 out2str("You have stopped jobs.\n");
5311                 job_warning = 2;
5312                 retval++;
5313         }
5314  out:
5315         return retval;
5316 }
5317
5318
5319 /*
5320  * Code for dealing with input/output redirection.
5321  */
5322
5323 #undef EMPTY
5324 #undef CLOSED
5325 #define EMPTY -2                /* marks an unused slot in redirtab */
5326 #define CLOSED -1               /* marks a slot of previously-closed fd */
5327
5328 /*
5329  * Handle here documents.  Normally we fork off a process to write the
5330  * data to a pipe.  If the document is short, we can stuff the data in
5331  * the pipe without forking.
5332  */
5333 /* openhere needs this forward reference */
5334 static void expandhere(union node *arg, int fd);
5335 static int
5336 openhere(union node *redir)
5337 {
5338         int pip[2];
5339         size_t len = 0;
5340
5341         if (pipe(pip) < 0)
5342                 ash_msg_and_raise_perror("can't create pipe");
5343         if (redir->type == NHERE) {
5344                 len = strlen(redir->nhere.doc->narg.text);
5345                 if (len <= PIPE_BUF) {
5346                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5347                         goto out;
5348                 }
5349         }
5350         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5351                 /* child */
5352                 close(pip[0]);
5353                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5354                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5355                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5356                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5357                 signal(SIGPIPE, SIG_DFL);
5358                 if (redir->type == NHERE)
5359                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5360                 else /* NXHERE */
5361                         expandhere(redir->nhere.doc, pip[1]);
5362                 _exit(EXIT_SUCCESS);
5363         }
5364  out:
5365         close(pip[1]);
5366         return pip[0];
5367 }
5368
5369 static int
5370 openredirect(union node *redir)
5371 {
5372         struct stat sb;
5373         char *fname;
5374         int f;
5375
5376         switch (redir->nfile.type) {
5377 /* Can't happen, our single caller does this itself */
5378 //      case NTOFD:
5379 //      case NFROMFD:
5380 //              return -1;
5381         case NHERE:
5382         case NXHERE:
5383                 return openhere(redir);
5384         }
5385
5386         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5387          * allocated space. Do it only when we know it is safe.
5388          */
5389         fname = redir->nfile.expfname;
5390
5391         switch (redir->nfile.type) {
5392         default:
5393 #if DEBUG
5394                 abort();
5395 #endif
5396         case NFROM:
5397                 f = open(fname, O_RDONLY);
5398                 if (f < 0)
5399                         goto eopen;
5400                 break;
5401         case NFROMTO:
5402                 f = open(fname, O_RDWR|O_CREAT, 0666);
5403                 if (f < 0)
5404                         goto ecreate;
5405                 break;
5406         case NTO:
5407 #if BASH_REDIR_OUTPUT
5408         case NTO2:
5409 #endif
5410                 /* Take care of noclobber mode. */
5411                 if (Cflag) {
5412                         if (stat(fname, &sb) < 0) {
5413                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5414                                 if (f < 0)
5415                                         goto ecreate;
5416                         } else if (!S_ISREG(sb.st_mode)) {
5417                                 f = open(fname, O_WRONLY, 0666);
5418                                 if (f < 0)
5419                                         goto ecreate;
5420                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5421                                         close(f);
5422                                         errno = EEXIST;
5423                                         goto ecreate;
5424                                 }
5425                         } else {
5426                                 errno = EEXIST;
5427                                 goto ecreate;
5428                         }
5429                         break;
5430                 }
5431                 /* FALLTHROUGH */
5432         case NCLOBBER:
5433                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5434                 if (f < 0)
5435                         goto ecreate;
5436                 break;
5437         case NAPPEND:
5438                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5439                 if (f < 0)
5440                         goto ecreate;
5441                 break;
5442         }
5443
5444         return f;
5445  ecreate:
5446         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5447  eopen:
5448         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5449 }
5450
5451 /*
5452  * Copy a file descriptor to be >= 10. Throws exception on error.
5453  */
5454 static int
5455 savefd(int from)
5456 {
5457         int newfd;
5458         int err;
5459
5460         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5461         err = newfd < 0 ? errno : 0;
5462         if (err != EBADF) {
5463                 if (err)
5464                         ash_msg_and_raise_perror("%d", from);
5465                 close(from);
5466                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5467                         close_on_exec_on(newfd);
5468         }
5469
5470         return newfd;
5471 }
5472 static int
5473 dup2_or_raise(int from, int to)
5474 {
5475         int newfd;
5476
5477         newfd = (from != to) ? dup2(from, to) : to;
5478         if (newfd < 0) {
5479                 /* Happens when source fd is not open: try "echo >&99" */
5480                 ash_msg_and_raise_perror("%d", from);
5481         }
5482         return newfd;
5483 }
5484 static int
5485 dup_CLOEXEC(int fd, int avoid_fd)
5486 {
5487         int newfd;
5488  repeat:
5489         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5490         if (newfd >= 0) {
5491                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5492                         close_on_exec_on(newfd);
5493         } else { /* newfd < 0 */
5494                 if (errno == EBUSY)
5495                         goto repeat;
5496                 if (errno == EINTR)
5497                         goto repeat;
5498         }
5499         return newfd;
5500 }
5501 static int
5502 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5503 {
5504         int newfd;
5505  repeat:
5506         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5507         if (newfd < 0) {
5508                 if (errno == EBUSY)
5509                         goto repeat;
5510                 if (errno == EINTR)
5511                         goto repeat;
5512                 /* fd was not open? */
5513                 if (errno == EBADF)
5514                         return fd;
5515                 ash_msg_and_raise_perror("%d", newfd);
5516         }
5517         if (F_DUPFD_CLOEXEC == F_DUPFD)
5518                 close_on_exec_on(newfd);
5519         close(fd);
5520         return newfd;
5521 }
5522
5523 /* Struct def and variable are moved down to the first usage site */
5524 struct squirrel {
5525         int orig_fd;
5526         int moved_to;
5527 };
5528 struct redirtab {
5529         struct redirtab *next;
5530         int pair_count;
5531         struct squirrel two_fd[];
5532 };
5533 #define redirlist (G_var.redirlist)
5534
5535 static void
5536 add_squirrel_closed(struct redirtab *sq, int fd)
5537 {
5538         int i;
5539
5540         if (!sq)
5541                 return;
5542
5543         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5544                 /* If we collide with an already moved fd... */
5545                 if (fd == sq->two_fd[i].orig_fd) {
5546                         /* Examples:
5547                          * "echo 3>FILE 3>&- 3>FILE"
5548                          * "echo 3>&- 3>FILE"
5549                          * No need for last redirect to insert
5550                          * another "need to close 3" indicator.
5551                          */
5552                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5553                         return;
5554                 }
5555         }
5556         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5557         sq->two_fd[i].orig_fd = fd;
5558         sq->two_fd[i].moved_to = CLOSED;
5559 }
5560
5561 static int
5562 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5563 {
5564         int i, new_fd;
5565
5566         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5567                 avoid_fd = 9;
5568
5569 #if JOBS
5570         if (fd == ttyfd) {
5571                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5572                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5573                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5574                 return 1; /* "we closed fd" */
5575         }
5576 #endif
5577         /* Are we called from redirect(0)? E.g. redirect
5578          * in a forked child. No need to save fds,
5579          * we aren't going to use them anymore, ok to trash.
5580          */
5581         if (!sq)
5582                 return 0;
5583
5584         /* If this one of script's fds? */
5585         if (fd != 0) {
5586                 struct parsefile *pf = g_parsefile;
5587                 while (pf) {
5588                         /* We skip fd == 0 case because of the following:
5589                          * $ ash  # running ash interactively
5590                          * $ . ./script.sh
5591                          * and in script.sh: "exec 9>&0".
5592                          * Even though top-level pf_fd _is_ 0,
5593                          * it's still ok to use it: "read" builtin uses it,
5594                          * why should we cripple "exec" builtin?
5595                          */
5596                         if (fd == pf->pf_fd) {
5597                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5598                                 return 1; /* "we closed fd" */
5599                         }
5600                         pf = pf->prev;
5601                 }
5602         }
5603
5604         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5605
5606         /* First: do we collide with some already moved fds? */
5607         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5608                 /* If we collide with an already moved fd... */
5609                 if (fd == sq->two_fd[i].moved_to) {
5610                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5611                         sq->two_fd[i].moved_to = new_fd;
5612                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5613                         if (new_fd < 0) /* what? */
5614                                 xfunc_die();
5615                         return 0; /* "we did not close fd" */
5616                 }
5617                 if (fd == sq->two_fd[i].orig_fd) {
5618                         /* Example: echo Hello >/dev/null 1>&2 */
5619                         TRACE(("redirect_fd %d: already moved\n", fd));
5620                         return 0; /* "we did not close fd" */
5621                 }
5622         }
5623
5624         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5625         new_fd = dup_CLOEXEC(fd, avoid_fd);
5626         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5627         if (new_fd < 0) {
5628                 if (errno != EBADF)
5629                         xfunc_die();
5630                 /* new_fd = CLOSED; - already is -1 */
5631         }
5632         sq->two_fd[i].moved_to = new_fd;
5633         sq->two_fd[i].orig_fd = fd;
5634
5635         /* if we move stderr, let "set -x" code know */
5636         if (fd == preverrout_fd)
5637                 preverrout_fd = new_fd;
5638
5639         return 0; /* "we did not close fd" */
5640 }
5641
5642 static int
5643 internally_opened_fd(int fd, struct redirtab *sq)
5644 {
5645         int i;
5646 #if JOBS
5647         if (fd == ttyfd)
5648                 return 1;
5649 #endif
5650         /* If this one of script's fds? */
5651         if (fd != 0) {
5652                 struct parsefile *pf = g_parsefile;
5653                 while (pf) {
5654                         if (fd == pf->pf_fd)
5655                                 return 1;
5656                         pf = pf->prev;
5657                 }
5658         }
5659
5660         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5661                 if (fd == sq->two_fd[i].moved_to)
5662                         return 1;
5663         }
5664         return 0;
5665 }
5666
5667 /*
5668  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5669  * old file descriptors are stashed away so that the redirection can be
5670  * undone by calling popredir.
5671  */
5672 /* flags passed to redirect */
5673 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5674 static void
5675 redirect(union node *redir, int flags)
5676 {
5677         struct redirtab *sv;
5678
5679         if (!redir)
5680                 return;
5681
5682         sv = NULL;
5683         INT_OFF;
5684         if (flags & REDIR_PUSH)
5685                 sv = redirlist;
5686         do {
5687                 int fd;
5688                 int newfd;
5689                 int close_fd;
5690                 int closed;
5691
5692                 fd = redir->nfile.fd;
5693                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5694                         //bb_error_msg("doing %d > %d", fd, newfd);
5695                         newfd = redir->ndup.dupfd;
5696                         close_fd = -1;
5697                 } else {
5698                         newfd = openredirect(redir); /* always >= 0 */
5699                         if (fd == newfd) {
5700                                 /* open() gave us precisely the fd we wanted.
5701                                  * This means that this fd was not busy
5702                                  * (not opened to anywhere).
5703                                  * Remember to close it on restore:
5704                                  */
5705                                 add_squirrel_closed(sv, fd);
5706                                 continue;
5707                         }
5708                         close_fd = newfd;
5709                 }
5710
5711                 if (fd == newfd)
5712                         continue;
5713
5714                 /* if "N>FILE": move newfd to fd */
5715                 /* if "N>&M": dup newfd to fd */
5716                 /* if "N>&-": close fd (newfd is -1) */
5717
5718  IF_BASH_REDIR_OUTPUT(redirect_more:)
5719
5720                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5721                 if (newfd == -1) {
5722                         /* "N>&-" means "close me" */
5723                         if (!closed) {
5724                                 /* ^^^ optimization: saving may already
5725                                  * have closed it. If not... */
5726                                 close(fd);
5727                         }
5728                 } else {
5729                         /* if newfd is a script fd or saved fd, simulate EBADF */
5730                         if (internally_opened_fd(newfd, sv)) {
5731                                 errno = EBADF;
5732                                 ash_msg_and_raise_perror("%d", newfd);
5733                         }
5734                         dup2_or_raise(newfd, fd);
5735                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5736                                 close(close_fd);
5737 #if BASH_REDIR_OUTPUT
5738                         if (redir->nfile.type == NTO2 && fd == 1) {
5739                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5740                                 fd = 2;
5741                                 newfd = 1;
5742                                 close_fd = -1;
5743                                 goto redirect_more;
5744                         }
5745 #endif
5746                 }
5747         } while ((redir = redir->nfile.next) != NULL);
5748         INT_ON;
5749
5750 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5751 #define REDIR_SAVEFD2 0
5752         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5753         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5754         // not only for calls with flags containing REDIR_SAVEFD2.
5755         // We do this unconditionally (see save_fd_on_redirect()).
5756         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5757         //      preverrout_fd = copied_fd2;
5758 }
5759
5760 static int
5761 redirectsafe(union node *redir, int flags)
5762 {
5763         int err;
5764         volatile int saveint;
5765         struct jmploc *volatile savehandler = exception_handler;
5766         struct jmploc jmploc;
5767
5768         SAVE_INT(saveint);
5769         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5770         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5771         if (!err) {
5772                 exception_handler = &jmploc;
5773                 redirect(redir, flags);
5774         }
5775         exception_handler = savehandler;
5776         if (err && exception_type != EXERROR)
5777                 longjmp(exception_handler->loc, 1);
5778         RESTORE_INT(saveint);
5779         return err;
5780 }
5781
5782 static struct redirtab*
5783 pushredir(union node *redir)
5784 {
5785         struct redirtab *sv;
5786         int i;
5787
5788         if (!redir)
5789                 return redirlist;
5790
5791         i = 0;
5792         do {
5793                 i++;
5794 #if BASH_REDIR_OUTPUT
5795                 if (redir->nfile.type == NTO2)
5796                         i++;
5797 #endif
5798                 redir = redir->nfile.next;
5799         } while (redir);
5800
5801         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5802         sv->pair_count = i;
5803         while (--i >= 0)
5804                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5805         sv->next = redirlist;
5806         redirlist = sv;
5807         return sv->next;
5808 }
5809
5810 /*
5811  * Undo the effects of the last redirection.
5812  */
5813 static void
5814 popredir(int drop)
5815 {
5816         struct redirtab *rp;
5817         int i;
5818
5819         if (redirlist == NULL)
5820                 return;
5821         INT_OFF;
5822         rp = redirlist;
5823         for (i = 0; i < rp->pair_count; i++) {
5824                 int fd = rp->two_fd[i].orig_fd;
5825                 int copy = rp->two_fd[i].moved_to;
5826                 if (copy == CLOSED) {
5827                         if (!drop)
5828                                 close(fd);
5829                         continue;
5830                 }
5831                 if (copy != EMPTY) {
5832                         if (!drop) {
5833                                 /*close(fd);*/
5834                                 dup2_or_raise(copy, fd);
5835                         }
5836                         close(copy);
5837                 }
5838         }
5839         redirlist = rp->next;
5840         free(rp);
5841         INT_ON;
5842 }
5843
5844 static void
5845 unwindredir(struct redirtab *stop)
5846 {
5847         while (redirlist != stop)
5848                 popredir(/*drop:*/ 0);
5849 }
5850
5851
5852 /* ============ Routines to expand arguments to commands
5853  *
5854  * We have to deal with backquotes, shell variables, and file metacharacters.
5855  */
5856
5857 #if ENABLE_FEATURE_SH_MATH
5858 static arith_t
5859 ash_arith(const char *s)
5860 {
5861         arith_state_t math_state;
5862         arith_t result;
5863
5864         math_state.lookupvar = lookupvar;
5865         math_state.setvar    = setvar0;
5866         //math_state.endofname = endofname;
5867
5868         INT_OFF;
5869         result = arith(&math_state, s);
5870         if (math_state.errmsg)
5871                 ash_msg_and_raise_error(math_state.errmsg);
5872         INT_ON;
5873
5874         return result;
5875 }
5876 #endif
5877 #if BASH_SUBSTR
5878 # if ENABLE_FEATURE_SH_MATH
5879 static int substr_atoi(const char *s)
5880 {
5881         arith_t t = ash_arith(s);
5882         if (sizeof(t) > sizeof(int)) {
5883                 /* clamp very large or very large negative nums for ${v:N:M}:
5884                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5885                  */
5886                 if (t > INT_MAX)
5887                         t = INT_MAX;
5888                 if (t < INT_MIN)
5889                         t = INT_MIN;
5890         }
5891         return t;
5892 }
5893 # else
5894 #  define substr_atoi(s) number(s)
5895 # endif
5896 #endif
5897
5898 /*
5899  * expandarg flags
5900  */
5901 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5902 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5903 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5904 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5905 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5906  * POSIX says for this case:
5907  *  Pathname expansion shall not be performed on the word by a
5908  *  non-interactive shell; an interactive shell may perform it, but shall
5909  *  do so only when the expansion would result in one word.
5910  * Currently, our code complies to the above rule by never globbing
5911  * redirection filenames.
5912  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5913  * (this means that on a typical Linux distro, bash almost always
5914  * performs globbing, and thus diverges from what we do).
5915  */
5916 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5917 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
5918 #define EXP_WORD        0x40    /* expand word in parameter expansion */
5919 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5920 /*
5921  * rmescape() flags
5922  */
5923 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5924 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5925 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5926 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5927
5928 /* Add CTLESC when necessary. */
5929 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
5930 /* Do not skip NUL characters. */
5931 #define QUOTES_KEEPNUL EXP_TILDE
5932
5933 /*
5934  * Structure specifying which parts of the string should be searched
5935  * for IFS characters.
5936  */
5937 struct ifsregion {
5938         struct ifsregion *next; /* next region in list */
5939         int begoff;             /* offset of start of region */
5940         int endoff;             /* offset of end of region */
5941         int nulonly;            /* search for nul bytes only */
5942 };
5943
5944 struct arglist {
5945         struct strlist *list;
5946         struct strlist **lastp;
5947 };
5948
5949 /* output of current string */
5950 static char *expdest;
5951 /* list of back quote expressions */
5952 static struct nodelist *argbackq;
5953 /* first struct in list of ifs regions */
5954 static struct ifsregion ifsfirst;
5955 /* last struct in list */
5956 static struct ifsregion *ifslastp;
5957 /* holds expanded arg list */
5958 static struct arglist exparg;
5959
5960 /*
5961  * Our own itoa().
5962  * cvtnum() is used even if math support is off (to prepare $? values and such).
5963  */
5964 static int
5965 cvtnum(arith_t num)
5966 {
5967         int len;
5968
5969         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5970         len = sizeof(arith_t) * 3;
5971         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5972         if (sizeof(arith_t) < 4) len += 2;
5973
5974         expdest = makestrspace(len, expdest);
5975         len = fmtstr(expdest, len, ARITH_FMT, num);
5976         STADJUST(len, expdest);
5977         return len;
5978 }
5979
5980 /*
5981  * Break the argument string into pieces based upon IFS and add the
5982  * strings to the argument list.  The regions of the string to be
5983  * searched for IFS characters have been stored by recordregion.
5984  */
5985 static void
5986 ifsbreakup(char *string, struct arglist *arglist)
5987 {
5988         struct ifsregion *ifsp;
5989         struct strlist *sp;
5990         char *start;
5991         char *p;
5992         char *q;
5993         const char *ifs, *realifs;
5994         int ifsspc;
5995         int nulonly;
5996
5997         start = string;
5998         if (ifslastp != NULL) {
5999                 ifsspc = 0;
6000                 nulonly = 0;
6001                 realifs = ifsset() ? ifsval() : defifs;
6002                 ifsp = &ifsfirst;
6003                 do {
6004                         int afternul;
6005
6006                         p = string + ifsp->begoff;
6007                         afternul = nulonly;
6008                         nulonly = ifsp->nulonly;
6009                         ifs = nulonly ? nullstr : realifs;
6010                         ifsspc = 0;
6011                         while (p < string + ifsp->endoff) {
6012                                 q = p;
6013                                 if ((unsigned char)*p == CTLESC)
6014                                         p++;
6015                                 if (!strchr(ifs, *p)) {
6016                                         p++;
6017                                         continue;
6018                                 }
6019                                 if (!(afternul || nulonly))
6020                                         ifsspc = (strchr(defifs, *p) != NULL);
6021                                 /* Ignore IFS whitespace at start */
6022                                 if (q == start && ifsspc) {
6023                                         p++;
6024                                         start = p;
6025                                         continue;
6026                                 }
6027                                 *q = '\0';
6028                                 sp = stzalloc(sizeof(*sp));
6029                                 sp->text = start;
6030                                 *arglist->lastp = sp;
6031                                 arglist->lastp = &sp->next;
6032                                 p++;
6033                                 if (!nulonly) {
6034                                         for (;;) {
6035                                                 if (p >= string + ifsp->endoff) {
6036                                                         break;
6037                                                 }
6038                                                 q = p;
6039                                                 if ((unsigned char)*p == CTLESC)
6040                                                         p++;
6041                                                 if (strchr(ifs, *p) == NULL) {
6042                                                         p = q;
6043                                                         break;
6044                                                 }
6045                                                 if (strchr(defifs, *p) == NULL) {
6046                                                         if (ifsspc) {
6047                                                                 p++;
6048                                                                 ifsspc = 0;
6049                                                         } else {
6050                                                                 p = q;
6051                                                                 break;
6052                                                         }
6053                                                 } else
6054                                                         p++;
6055                                         }
6056                                 }
6057                                 start = p;
6058                         } /* while */
6059                         ifsp = ifsp->next;
6060                 } while (ifsp != NULL);
6061                 if (nulonly)
6062                         goto add;
6063         }
6064
6065         if (!*start)
6066                 return;
6067
6068  add:
6069         sp = stzalloc(sizeof(*sp));
6070         sp->text = start;
6071         *arglist->lastp = sp;
6072         arglist->lastp = &sp->next;
6073 }
6074
6075 static void
6076 ifsfree(void)
6077 {
6078         struct ifsregion *p = ifsfirst.next;
6079
6080         if (!p)
6081                 goto out;
6082
6083         INT_OFF;
6084         do {
6085                 struct ifsregion *ifsp;
6086                 ifsp = p->next;
6087                 free(p);
6088                 p = ifsp;
6089         } while (p);
6090         ifsfirst.next = NULL;
6091         INT_ON;
6092  out:
6093         ifslastp = NULL;
6094 }
6095
6096 static size_t
6097 esclen(const char *start, const char *p)
6098 {
6099         size_t esc = 0;
6100
6101         while (p > start && (unsigned char)*--p == CTLESC) {
6102                 esc++;
6103         }
6104         return esc;
6105 }
6106
6107 /*
6108  * Remove any CTLESC characters from a string.
6109  */
6110 #if !BASH_PATTERN_SUBST
6111 #define rmescapes(str, flag, slash_position) \
6112         rmescapes(str, flag)
6113 #endif
6114 static char *
6115 rmescapes(char *str, int flag, int *slash_position)
6116 {
6117         static const char qchars[] ALIGN1 = {
6118                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6119
6120         char *p, *q, *r;
6121         unsigned protect_against_glob;
6122         unsigned globbing;
6123
6124         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6125         if (!p)
6126                 return str;
6127
6128         q = p;
6129         r = str;
6130         if (flag & RMESCAPE_ALLOC) {
6131                 size_t len = p - str;
6132                 size_t fulllen = len + strlen(p) + 1;
6133
6134                 if (flag & RMESCAPE_GROW) {
6135                         int strloc = str - (char *)stackblock();
6136                         r = makestrspace(fulllen, expdest);
6137                         /* p and str may be invalidated by makestrspace */
6138                         str = (char *)stackblock() + strloc;
6139                         p = str + len;
6140                 } else if (flag & RMESCAPE_HEAP) {
6141                         r = ckmalloc(fulllen);
6142                 } else {
6143                         r = stalloc(fulllen);
6144                 }
6145                 q = r;
6146                 if (len > 0) {
6147                         q = (char *)mempcpy(q, str, len);
6148                 }
6149         }
6150
6151         globbing = flag & RMESCAPE_GLOB;
6152         protect_against_glob = globbing;
6153         while (*p) {
6154                 if ((unsigned char)*p == CTLQUOTEMARK) {
6155 // Note: protect_against_glob only affect whether
6156 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6157                         p++;
6158                         protect_against_glob = globbing;
6159                         continue;
6160                 }
6161                 if (*p == '\\') {
6162                         /* naked back slash */
6163                         protect_against_glob = 0;
6164                         goto copy;
6165                 }
6166                 if ((unsigned char)*p == CTLESC) {
6167                         p++;
6168 #if DEBUG
6169                         if (*p == '\0')
6170                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6171 #endif
6172                         if (protect_against_glob) {
6173                                 /*
6174                                  * We used to trust glob() and fnmatch() to eat
6175                                  * superfluous escapes (\z where z has no
6176                                  * special meaning anyway). But this causes
6177                                  * bugs such as string of one greek letter rho
6178                                  * (unicode-encoded as two bytes "cf,81")
6179                                  * getting encoded as "cf,CTLESC,81"
6180                                  * and here, converted to "cf,\,81" -
6181                                  * which does not go well with some flavors
6182                                  * of fnmatch() in unicode locales
6183                                  * (for example, glibc <= 2.22).
6184                                  *
6185                                  * Lets add "\" only on the chars which need it.
6186                                  * Testcases for less obvious chars are shown.
6187                                  */
6188                                 if (*p == '*'
6189                                  || *p == '?'
6190                                  || *p == '['
6191                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6192                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6193                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6194                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6195                                 /* Some libc support [^negate], that's why "^" also needs love */
6196                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6197                                 ) {
6198                                         *q++ = '\\';
6199                                 }
6200                         }
6201                 }
6202 #if BASH_PATTERN_SUBST
6203                 else if (slash_position && p == str + *slash_position) {
6204                         /* stop handling globbing */
6205                         globbing = 0;
6206                         *slash_position = q - r;
6207                         slash_position = NULL;
6208                 }
6209 #endif
6210                 protect_against_glob = globbing;
6211  copy:
6212                 *q++ = *p++;
6213         }
6214         *q = '\0';
6215         if (flag & RMESCAPE_GROW) {
6216                 expdest = r;
6217                 STADJUST(q - r + 1, expdest);
6218         }
6219         return r;
6220 }
6221 #define pmatch(a, b) !fnmatch((a), (b), 0)
6222
6223 /*
6224  * Prepare a pattern for a expmeta (internal glob(3)) call.
6225  *
6226  * Returns an stalloced string.
6227  */
6228 static char *
6229 preglob(const char *pattern, int flag)
6230 {
6231         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6232 }
6233
6234 /*
6235  * Put a string on the stack.
6236  */
6237 static void
6238 memtodest(const char *p, size_t len, int syntax, int quotes)
6239 {
6240         char *q;
6241
6242         if (!len)
6243                 return;
6244
6245         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6246
6247         do {
6248                 unsigned char c = *p++;
6249                 if (c) {
6250                         if (quotes & QUOTES_ESC) {
6251                                 int n = SIT(c, syntax);
6252                                 if (n == CCTL
6253                                  || (syntax != BASESYNTAX && n == CBACK)
6254                                 ) {
6255                                         USTPUTC(CTLESC, q);
6256                                 }
6257                         }
6258                 } else if (!(quotes & QUOTES_KEEPNUL))
6259                         continue;
6260                 USTPUTC(c, q);
6261         } while (--len);
6262
6263         expdest = q;
6264 }
6265
6266 static size_t
6267 strtodest(const char *p, int syntax, int quotes)
6268 {
6269         size_t len = strlen(p);
6270         memtodest(p, len, syntax, quotes);
6271         return len;
6272 }
6273
6274 /*
6275  * Record the fact that we have to scan this region of the
6276  * string for IFS characters.
6277  */
6278 static void
6279 recordregion(int start, int end, int nulonly)
6280 {
6281         struct ifsregion *ifsp;
6282
6283         if (ifslastp == NULL) {
6284                 ifsp = &ifsfirst;
6285         } else {
6286                 INT_OFF;
6287                 ifsp = ckzalloc(sizeof(*ifsp));
6288                 /*ifsp->next = NULL; - ckzalloc did it */
6289                 ifslastp->next = ifsp;
6290                 INT_ON;
6291         }
6292         ifslastp = ifsp;
6293         ifslastp->begoff = start;
6294         ifslastp->endoff = end;
6295         ifslastp->nulonly = nulonly;
6296 }
6297
6298 static void
6299 removerecordregions(int endoff)
6300 {
6301         if (ifslastp == NULL)
6302                 return;
6303
6304         if (ifsfirst.endoff > endoff) {
6305                 while (ifsfirst.next) {
6306                         struct ifsregion *ifsp;
6307                         INT_OFF;
6308                         ifsp = ifsfirst.next->next;
6309                         free(ifsfirst.next);
6310                         ifsfirst.next = ifsp;
6311                         INT_ON;
6312                 }
6313                 if (ifsfirst.begoff > endoff) {
6314                         ifslastp = NULL;
6315                 } else {
6316                         ifslastp = &ifsfirst;
6317                         ifsfirst.endoff = endoff;
6318                 }
6319                 return;
6320         }
6321
6322         ifslastp = &ifsfirst;
6323         while (ifslastp->next && ifslastp->next->begoff < endoff)
6324                 ifslastp = ifslastp->next;
6325         while (ifslastp->next) {
6326                 struct ifsregion *ifsp;
6327                 INT_OFF;
6328                 ifsp = ifslastp->next->next;
6329                 free(ifslastp->next);
6330                 ifslastp->next = ifsp;
6331                 INT_ON;
6332         }
6333         if (ifslastp->endoff > endoff)
6334                 ifslastp->endoff = endoff;
6335 }
6336
6337 static char *
6338 exptilde(char *startp, char *p, int flags)
6339 {
6340         unsigned char c;
6341         char *name;
6342         struct passwd *pw;
6343         const char *home;
6344         int quotes = flags & QUOTES_ESC;
6345
6346         name = p + 1;
6347
6348         while ((c = *++p) != '\0') {
6349                 switch (c) {
6350                 case CTLESC:
6351                         return startp;
6352                 case CTLQUOTEMARK:
6353                         return startp;
6354                 case ':':
6355                         if (flags & EXP_VARTILDE)
6356                                 goto done;
6357                         break;
6358                 case '/':
6359                 case CTLENDVAR:
6360                         goto done;
6361                 }
6362         }
6363  done:
6364         *p = '\0';
6365         if (*name == '\0') {
6366                 home = lookupvar("HOME");
6367         } else {
6368                 pw = getpwnam(name);
6369                 if (pw == NULL)
6370                         goto lose;
6371                 home = pw->pw_dir;
6372         }
6373         if (!home || !*home)
6374                 goto lose;
6375         *p = c;
6376         strtodest(home, SQSYNTAX, quotes);
6377         return p;
6378  lose:
6379         *p = c;
6380         return startp;
6381 }
6382
6383 /*
6384  * Execute a command inside back quotes.  If it's a builtin command, we
6385  * want to save its output in a block obtained from malloc.  Otherwise
6386  * we fork off a subprocess and get the output of the command via a pipe.
6387  * Should be called with interrupts off.
6388  */
6389 struct backcmd {                /* result of evalbackcmd */
6390         int fd;                 /* file descriptor to read from */
6391         int nleft;              /* number of chars in buffer */
6392         char *buf;              /* buffer */
6393         struct job *jp;         /* job structure for command */
6394 };
6395
6396 /* These forward decls are needed to use "eval" code for backticks handling: */
6397 /* flags in argument to evaltree */
6398 #define EV_EXIT    01           /* exit after evaluating tree */
6399 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6400 static int evaltree(union node *, int);
6401
6402 /* An evaltree() which is known to never return.
6403  * Used to use an alias:
6404  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6405  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6406  */
6407 static ALWAYS_INLINE NORETURN void
6408 evaltreenr(union node *n, int flags)
6409 {
6410         evaltree(n, flags);
6411         bb_unreachable(abort());
6412         /* NOTREACHED */
6413 }
6414
6415 static void FAST_FUNC
6416 evalbackcmd(union node *n, struct backcmd *result)
6417 {
6418         int pip[2];
6419         struct job *jp;
6420
6421         result->fd = -1;
6422         result->buf = NULL;
6423         result->nleft = 0;
6424         result->jp = NULL;
6425         if (n == NULL) {
6426                 goto out;
6427         }
6428
6429         if (pipe(pip) < 0)
6430                 ash_msg_and_raise_perror("can't create pipe");
6431         jp = makejob(/*n,*/ 1);
6432         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6433                 /* child */
6434                 FORCE_INT_ON;
6435                 close(pip[0]);
6436                 if (pip[1] != 1) {
6437                         /*close(1);*/
6438                         dup2_or_raise(pip[1], 1);
6439                         close(pip[1]);
6440                 }
6441 /* TODO: eflag clearing makes the following not abort:
6442  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6443  * which is what bash does (unless it is in POSIX mode).
6444  * dash deleted "eflag = 0" line in the commit
6445  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6446  *  [EVAL] Don't clear eflag in evalbackcmd
6447  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6448  */
6449                 eflag = 0;
6450                 ifsfree();
6451                 evaltreenr(n, EV_EXIT);
6452                 /* NOTREACHED */
6453         }
6454         /* parent */
6455         close(pip[1]);
6456         result->fd = pip[0];
6457         result->jp = jp;
6458
6459  out:
6460         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6461                 result->fd, result->buf, result->nleft, result->jp));
6462 }
6463
6464 /*
6465  * Expand stuff in backwards quotes.
6466  */
6467 static void
6468 expbackq(union node *cmd, int flag)
6469 {
6470         struct backcmd in;
6471         int i;
6472         char buf[128];
6473         char *p;
6474         char *dest;
6475         int startloc;
6476         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6477         struct stackmark smark;
6478
6479         INT_OFF;
6480         startloc = expdest - (char *)stackblock();
6481         pushstackmark(&smark, startloc);
6482         evalbackcmd(cmd, &in);
6483         popstackmark(&smark);
6484
6485         p = in.buf;
6486         i = in.nleft;
6487         if (i == 0)
6488                 goto read;
6489         for (;;) {
6490                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6491  read:
6492                 if (in.fd < 0)
6493                         break;
6494                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6495                 TRACE(("expbackq: read returns %d\n", i));
6496                 if (i <= 0)
6497                         break;
6498                 p = buf;
6499         }
6500
6501         free(in.buf);
6502         if (in.fd >= 0) {
6503                 close(in.fd);
6504                 back_exitstatus = waitforjob(in.jp);
6505         }
6506         INT_ON;
6507
6508         /* Eat all trailing newlines */
6509         dest = expdest;
6510         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6511                 STUNPUTC(dest);
6512         expdest = dest;
6513
6514         if (!(flag & EXP_QUOTED))
6515                 recordregion(startloc, dest - (char *)stackblock(), 0);
6516         TRACE(("evalbackq: size:%d:'%.*s'\n",
6517                 (int)((dest - (char *)stackblock()) - startloc),
6518                 (int)((dest - (char *)stackblock()) - startloc),
6519                 stackblock() + startloc));
6520 }
6521
6522 #if ENABLE_FEATURE_SH_MATH
6523 /*
6524  * Expand arithmetic expression.  Backup to start of expression,
6525  * evaluate, place result in (backed up) result, adjust string position.
6526  */
6527 static void
6528 expari(int flag)
6529 {
6530         char *p, *start;
6531         int begoff;
6532         int len;
6533
6534         /* ifsfree(); */
6535
6536         /*
6537          * This routine is slightly over-complicated for
6538          * efficiency.  Next we scan backwards looking for the
6539          * start of arithmetic.
6540          */
6541         start = stackblock();
6542         p = expdest - 1;
6543         *p = '\0';
6544         p--;
6545         while (1) {
6546                 int esc;
6547
6548                 while ((unsigned char)*p != CTLARI) {
6549                         p--;
6550 #if DEBUG
6551                         if (p < start) {
6552                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6553                         }
6554 #endif
6555                 }
6556
6557                 esc = esclen(start, p);
6558                 if (!(esc % 2)) {
6559                         break;
6560                 }
6561
6562                 p -= esc + 1;
6563         }
6564
6565         begoff = p - start;
6566
6567         removerecordregions(begoff);
6568
6569         expdest = p;
6570
6571         if (flag & QUOTES_ESC)
6572                 rmescapes(p + 1, 0, NULL);
6573
6574         len = cvtnum(ash_arith(p + 1));
6575
6576         if (!(flag & EXP_QUOTED))
6577                 recordregion(begoff, begoff + len, 0);
6578 }
6579 #endif
6580
6581 /* argstr needs it */
6582 static char *evalvar(char *p, int flags);
6583
6584 /*
6585  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6586  * characters to allow for further processing.  Otherwise treat
6587  * $@ like $* since no splitting will be performed.
6588  */
6589 static void
6590 argstr(char *p, int flags)
6591 {
6592         static const char spclchars[] ALIGN1 = {
6593                 '=',
6594                 ':',
6595                 CTLQUOTEMARK,
6596                 CTLENDVAR,
6597                 CTLESC,
6598                 CTLVAR,
6599                 CTLBACKQ,
6600 #if ENABLE_FEATURE_SH_MATH
6601                 CTLENDARI,
6602 #endif
6603                 '\0'
6604         };
6605         const char *reject = spclchars;
6606         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6607         int inquotes;
6608         size_t length;
6609         int startloc;
6610
6611         if (!(flags & EXP_VARTILDE)) {
6612                 reject += 2;
6613         } else if (flags & EXP_VARTILDE2) {
6614                 reject++;
6615         }
6616         inquotes = 0;
6617         length = 0;
6618         if (flags & EXP_TILDE) {
6619                 char *q;
6620
6621                 flags &= ~EXP_TILDE;
6622  tilde:
6623                 q = p;
6624                 if (*q == '~')
6625                         p = exptilde(p, q, flags);
6626         }
6627  start:
6628         startloc = expdest - (char *)stackblock();
6629         for (;;) {
6630                 unsigned char c;
6631
6632                 length += strcspn(p + length, reject);
6633                 c = p[length];
6634                 if (c) {
6635                         if (!(c & 0x80)
6636                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6637                         ) {
6638                                 /* c == '=' || c == ':' || c == CTLENDARI */
6639                                 length++;
6640                         }
6641                 }
6642                 if (length > 0) {
6643                         int newloc;
6644                         expdest = stack_nputstr(p, length, expdest);
6645                         newloc = expdest - (char *)stackblock();
6646                         if (breakall && !inquotes && newloc > startloc) {
6647                                 recordregion(startloc, newloc, 0);
6648                         }
6649                         startloc = newloc;
6650                 }
6651                 p += length + 1;
6652                 length = 0;
6653
6654                 switch (c) {
6655                 case '\0':
6656                         goto breakloop;
6657                 case '=':
6658                         if (flags & EXP_VARTILDE2) {
6659                                 p--;
6660                                 continue;
6661                         }
6662                         flags |= EXP_VARTILDE2;
6663                         reject++;
6664                         /* fall through */
6665                 case ':':
6666                         /*
6667                          * sort of a hack - expand tildes in variable
6668                          * assignments (after the first '=' and after ':'s).
6669                          */
6670                         if (*--p == '~') {
6671                                 goto tilde;
6672                         }
6673                         continue;
6674                 }
6675
6676                 switch (c) {
6677                 case CTLENDVAR: /* ??? */
6678                         goto breakloop;
6679                 case CTLQUOTEMARK:
6680                         /* "$@" syntax adherence hack */
6681                         if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6682                                 p = evalvar(p + 1, flags | EXP_QUOTED) + 1;
6683                                 goto start;
6684                         }
6685                         inquotes ^= EXP_QUOTED;
6686  addquote:
6687                         if (flags & QUOTES_ESC) {
6688                                 p--;
6689                                 length++;
6690                                 startloc++;
6691                         }
6692                         break;
6693                 case CTLESC:
6694                         startloc++;
6695                         length++;
6696                         goto addquote;
6697                 case CTLVAR:
6698                         TRACE(("argstr: evalvar('%s')\n", p));
6699                         p = evalvar(p, flags | inquotes);
6700                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6701                         goto start;
6702                 case CTLBACKQ:
6703                         expbackq(argbackq->n, flags | inquotes);
6704                         argbackq = argbackq->next;
6705                         goto start;
6706 #if ENABLE_FEATURE_SH_MATH
6707                 case CTLENDARI:
6708                         p--;
6709                         expari(flags | inquotes);
6710                         goto start;
6711 #endif
6712                 }
6713         }
6714  breakloop: ;
6715 }
6716
6717 static char *
6718 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6719                 char *pattern, int quotes, int zero)
6720 {
6721         char *loc, *loc2;
6722         char c;
6723
6724         loc = startp;
6725         loc2 = rmesc;
6726         do {
6727                 int match;
6728                 const char *s = loc2;
6729
6730                 c = *loc2;
6731                 if (zero) {
6732                         *loc2 = '\0';
6733                         s = rmesc;
6734                 }
6735                 match = pmatch(pattern, s);
6736
6737                 *loc2 = c;
6738                 if (match)
6739                         return loc;
6740                 if (quotes && (unsigned char)*loc == CTLESC)
6741                         loc++;
6742                 loc++;
6743                 loc2++;
6744         } while (c);
6745         return NULL;
6746 }
6747
6748 static char *
6749 scanright(char *startp, char *rmesc, char *rmescend,
6750                 char *pattern, int quotes, int match_at_start)
6751 {
6752 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6753         int try2optimize = match_at_start;
6754 #endif
6755         int esc = 0;
6756         char *loc;
6757         char *loc2;
6758
6759         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6760          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6761          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6762          * Logic:
6763          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6764          * and on each iteration they go back two/one char until they reach the beginning.
6765          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6766          */
6767         /* TODO: document in what other circumstances we are called. */
6768
6769         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6770                 int match;
6771                 char c = *loc2;
6772                 const char *s = loc2;
6773                 if (match_at_start) {
6774                         *loc2 = '\0';
6775                         s = rmesc;
6776                 }
6777                 match = pmatch(pattern, s);
6778                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6779                 *loc2 = c;
6780                 if (match)
6781                         return loc;
6782 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6783                 if (try2optimize) {
6784                         /* Maybe we can optimize this:
6785                          * if pattern ends with unescaped *, we can avoid checking
6786                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6787                          * it won't match truncated "raw_value_of_" strings too.
6788                          */
6789                         unsigned plen = strlen(pattern);
6790                         /* Does it end with "*"? */
6791                         if (plen != 0 && pattern[--plen] == '*') {
6792                                 /* "xxxx*" is not escaped */
6793                                 /* "xxx\*" is escaped */
6794                                 /* "xx\\*" is not escaped */
6795                                 /* "x\\\*" is escaped */
6796                                 int slashes = 0;
6797                                 while (plen != 0 && pattern[--plen] == '\\')
6798                                         slashes++;
6799                                 if (!(slashes & 1))
6800                                         break; /* ends with unescaped "*" */
6801                         }
6802                         try2optimize = 0;
6803                 }
6804 #endif
6805                 loc--;
6806                 if (quotes) {
6807                         if (--esc < 0) {
6808                                 esc = esclen(startp, loc);
6809                         }
6810                         if (esc % 2) {
6811                                 esc--;
6812                                 loc--;
6813                         }
6814                 }
6815         }
6816         return NULL;
6817 }
6818
6819 static void varunset(const char *, const char *, const char *, int) NORETURN;
6820 static void
6821 varunset(const char *end, const char *var, const char *umsg, int varflags)
6822 {
6823         const char *msg;
6824         const char *tail;
6825
6826         tail = nullstr;
6827         msg = "parameter not set";
6828         if (umsg) {
6829                 if ((unsigned char)*end == CTLENDVAR) {
6830                         if (varflags & VSNUL)
6831                                 tail = " or null";
6832                 } else {
6833                         msg = umsg;
6834                 }
6835         }
6836         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6837 }
6838
6839 static const char *
6840 subevalvar(char *p, char *varname, int strloc, int subtype,
6841                 int startloc, int varflags, int flag)
6842 {
6843         struct nodelist *saveargbackq = argbackq;
6844         int quotes = flag & QUOTES_ESC;
6845         char *startp;
6846         char *loc;
6847         char *rmesc, *rmescend;
6848         char *str;
6849         int amount, resetloc;
6850         int argstr_flags;
6851         IF_BASH_PATTERN_SUBST(int workloc;)
6852         IF_BASH_PATTERN_SUBST(int slash_pos;)
6853         IF_BASH_PATTERN_SUBST(char *repl;)
6854         int zero;
6855         char *(*scan)(char*, char*, char*, char*, int, int);
6856
6857         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6858         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6859
6860 #if BASH_PATTERN_SUBST
6861         /* For "${v/pattern/repl}", we must find the delimiter _before_
6862          * argstr() call expands possible variable references in pattern:
6863          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6864          */
6865         repl = NULL;
6866         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6867                 /* Find '/' and replace with NUL */
6868                 repl = p;
6869                 /* The pattern can't be empty.
6870                  * IOW: if the first char after "${v//" is a slash,
6871                  * it does not terminate the pattern - it's the first char of the pattern:
6872                  *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
6873                  *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
6874                  */
6875                 if (*repl == '/')
6876                         repl++;
6877                 for (;;) {
6878                         if (*repl == '\0') {
6879                                 repl = NULL;
6880                                 break;
6881                         }
6882                         if (*repl == '/') {
6883                                 *repl = '\0';
6884                                 break;
6885                         }
6886                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6887                         if ((unsigned char)*repl == CTLESC && repl[1])
6888                                 repl++;
6889                         repl++;
6890                 }
6891         }
6892 #endif
6893         argstr_flags = EXP_TILDE;
6894         if (subtype != VSASSIGN
6895          && subtype != VSQUESTION
6896 #if BASH_SUBSTR
6897          && subtype != VSSUBSTR
6898 #endif
6899         ) {
6900                 /* EXP_CASE keeps CTLESC's */
6901                 argstr_flags = EXP_TILDE | EXP_CASE;
6902         }
6903         argstr(p, argstr_flags);
6904         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
6905 #if BASH_PATTERN_SUBST
6906         slash_pos = -1;
6907         if (repl) {
6908                 slash_pos = expdest - ((char *)stackblock() + strloc);
6909                 STPUTC('/', expdest);
6910                 //bb_error_msg("repl+1:'%s'", repl + 1);
6911                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
6912                 *repl = '/';
6913         }
6914 #endif
6915         STPUTC('\0', expdest);
6916         argbackq = saveargbackq;
6917         startp = (char *)stackblock() + startloc;
6918         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6919
6920         switch (subtype) {
6921         case VSASSIGN:
6922                 setvar0(varname, startp);
6923                 amount = startp - expdest;
6924                 STADJUST(amount, expdest);
6925                 return startp;
6926
6927         case VSQUESTION:
6928                 varunset(p, varname, startp, varflags);
6929                 /* NOTREACHED */
6930
6931 #if BASH_SUBSTR
6932         case VSSUBSTR: {
6933                 int pos, len, orig_len;
6934                 char *colon;
6935
6936                 loc = str = stackblock() + strloc;
6937
6938                 /* Read POS in ${var:POS:LEN} */
6939                 colon = strchr(loc, ':');
6940                 if (colon) *colon = '\0';
6941                 pos = substr_atoi(loc);
6942                 if (colon) *colon = ':';
6943
6944                 /* Read LEN in ${var:POS:LEN} */
6945                 len = str - startp - 1;
6946                 /* *loc != '\0', guaranteed by parser */
6947                 if (quotes) {
6948                         char *ptr;
6949                         /* Adjust the length by the number of escapes */
6950                         for (ptr = startp; ptr < (str - 1); ptr++) {
6951                                 if ((unsigned char)*ptr == CTLESC) {
6952                                         len--;
6953                                         ptr++;
6954                                 }
6955                         }
6956                 }
6957                 orig_len = len;
6958                 if (*loc++ == ':') {
6959                         /* ${var::LEN} */
6960                         len = substr_atoi(loc);
6961                 } else {
6962                         /* Skip POS in ${var:POS:LEN} */
6963                         len = orig_len;
6964                         while (*loc && *loc != ':')
6965                                 loc++;
6966                         if (*loc++ == ':')
6967                                 len = substr_atoi(loc);
6968                 }
6969                 if (pos < 0) {
6970                         /* ${VAR:$((-n)):l} starts n chars from the end */
6971                         pos = orig_len + pos;
6972                 }
6973                 if ((unsigned)pos >= orig_len) {
6974                         /* apart from obvious ${VAR:999999:l},
6975                          * covers ${VAR:$((-9999999)):l} - result is ""
6976                          * (bash compat)
6977                          */
6978                         pos = 0;
6979                         len = 0;
6980                 }
6981                 if (len < 0) {
6982                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6983                         len = (orig_len - pos) + len;
6984                 }
6985                 if ((unsigned)len > (orig_len - pos))
6986                         len = orig_len - pos;
6987
6988                 for (str = startp; pos; str++, pos--) {
6989                         if (quotes && (unsigned char)*str == CTLESC)
6990                                 str++;
6991                 }
6992                 for (loc = startp; len; len--) {
6993                         if (quotes && (unsigned char)*str == CTLESC)
6994                                 *loc++ = *str++;
6995                         *loc++ = *str++;
6996                 }
6997                 *loc = '\0';
6998                 amount = loc - expdest;
6999                 STADJUST(amount, expdest);
7000                 return loc;
7001         }
7002 #endif /* BASH_SUBSTR */
7003         }
7004
7005         resetloc = expdest - (char *)stackblock();
7006
7007 #if BASH_PATTERN_SUBST
7008         repl = NULL;
7009
7010         /* We'll comeback here if we grow the stack while handling
7011          * a VSREPLACE or VSREPLACEALL, since our pointers into the
7012          * stack will need rebasing, and we'll need to remove our work
7013          * areas each time
7014          */
7015  restart:
7016 #endif
7017
7018         amount = expdest - ((char *)stackblock() + resetloc);
7019         STADJUST(-amount, expdest);
7020         startp = (char *)stackblock() + startloc;
7021
7022         rmesc = startp;
7023         rmescend = (char *)stackblock() + strloc;
7024         //bb_error_msg("str7:'%s'", rmescend);
7025         if (quotes) {
7026 //TODO: how to handle slash_pos here if string changes (shortens?)
7027                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
7028                 if (rmesc != startp) {
7029                         rmescend = expdest;
7030                         startp = (char *)stackblock() + startloc;
7031                 }
7032         }
7033         rmescend--;
7034         str = (char *)stackblock() + strloc;
7035         /*
7036          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7037          * The result is a_\_z_c (not a\_\_z_c)!
7038          *
7039          * The search pattern and replace string treat backslashes differently!
7040          * "&slash_pos" causes rmescapes() to work differently on the pattern
7041          * and string.  It's only used on the first call.
7042          */
7043         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7044         rmescapes(str, RMESCAPE_GLOB,
7045                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7046         );
7047
7048 #if BASH_PATTERN_SUBST
7049         workloc = expdest - (char *)stackblock();
7050         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7051                 int len;
7052                 char *idx, *end;
7053
7054                 if (!repl) {
7055                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7056                         repl = nullstr;
7057                         if (slash_pos >= 0) {
7058                                 repl = str + slash_pos;
7059                                 *repl++ = '\0';
7060                         }
7061                 }
7062                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7063
7064                 /* If there's no pattern to match, return the expansion unmolested */
7065                 if (str[0] == '\0')
7066                         return NULL;
7067
7068                 len = 0;
7069                 idx = startp;
7070                 end = str - 1;
7071                 while (idx < end) {
7072  try_to_match:
7073                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7074                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7075                         if (!loc) {
7076                                 /* No match, advance */
7077                                 char *restart_detect = stackblock();
7078  skip_matching:
7079                                 STPUTC(*idx, expdest);
7080                                 if (quotes && (unsigned char)*idx == CTLESC) {
7081                                         idx++;
7082                                         len++;
7083                                         STPUTC(*idx, expdest);
7084                                 }
7085                                 if (stackblock() != restart_detect)
7086                                         goto restart;
7087                                 idx++;
7088                                 len++;
7089                                 rmesc++;
7090                                 /* continue; - prone to quadratic behavior, smarter code: */
7091                                 if (idx >= end)
7092                                         break;
7093                                 if (str[0] == '*') {
7094                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7095                                          * it would never match "ong_string" etc, no point in trying.
7096                                          */
7097                                         goto skip_matching;
7098                                 }
7099                                 goto try_to_match;
7100                         }
7101
7102                         if (subtype == VSREPLACEALL) {
7103                                 while (idx < loc) {
7104                                         if (quotes && (unsigned char)*idx == CTLESC)
7105                                                 idx++;
7106                                         idx++;
7107                                         rmesc++;
7108                                 }
7109                         } else {
7110                                 idx = loc;
7111                         }
7112
7113                         //bb_error_msg("repl:'%s'", repl);
7114                         for (loc = (char*)repl; *loc; loc++) {
7115                                 char *restart_detect = stackblock();
7116                                 if (quotes && *loc == '\\') {
7117                                         STPUTC(CTLESC, expdest);
7118                                         len++;
7119                                 }
7120                                 STPUTC(*loc, expdest);
7121                                 if (stackblock() != restart_detect)
7122                                         goto restart;
7123                                 len++;
7124                         }
7125
7126                         if (subtype == VSREPLACE) {
7127                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7128                                 while (*idx) {
7129                                         char *restart_detect = stackblock();
7130                                         STPUTC(*idx, expdest);
7131                                         if (stackblock() != restart_detect)
7132                                                 goto restart;
7133                                         len++;
7134                                         idx++;
7135                                 }
7136                                 break;
7137                         }
7138                 }
7139
7140                 /* We've put the replaced text into a buffer at workloc, now
7141                  * move it to the right place and adjust the stack.
7142                  */
7143                 STPUTC('\0', expdest);
7144                 startp = (char *)stackblock() + startloc;
7145                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7146                 //bb_error_msg("startp:'%s'", startp);
7147                 amount = expdest - (startp + len);
7148                 STADJUST(-amount, expdest);
7149                 return startp;
7150         }
7151 #endif /* BASH_PATTERN_SUBST */
7152
7153         subtype -= VSTRIMRIGHT;
7154 #if DEBUG
7155         if (subtype < 0 || subtype > 7)
7156                 abort();
7157 #endif
7158         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7159         zero = subtype >> 1;
7160         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7161         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7162
7163         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7164         if (loc) {
7165                 if (zero) {
7166                         memmove(startp, loc, str - loc);
7167                         loc = startp + (str - loc) - 1;
7168                 }
7169                 *loc = '\0';
7170                 amount = loc - expdest;
7171                 STADJUST(amount, expdest);
7172         }
7173         return loc;
7174 }
7175
7176 /*
7177  * Add the value of a specialized variable to the stack string.
7178  * name parameter (examples):
7179  * ash -c 'echo $1'      name:'1='
7180  * ash -c 'echo $qwe'    name:'qwe='
7181  * ash -c 'echo $$'      name:'$='
7182  * ash -c 'echo ${$}'    name:'$='
7183  * ash -c 'echo ${$##q}' name:'$=q'
7184  * ash -c 'echo ${#$}'   name:'$='
7185  * note: examples with bad shell syntax:
7186  * ash -c 'echo ${#$1}'  name:'$=1'
7187  * ash -c 'echo ${#1#}'  name:'1=#'
7188  */
7189 static NOINLINE ssize_t
7190 varvalue(char *name, int varflags, int flags, int quoted)
7191 {
7192         const char *p;
7193         int num;
7194         int i;
7195         ssize_t len = 0;
7196         int sep;
7197         int subtype = varflags & VSTYPE;
7198         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7199         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7200         int syntax;
7201
7202         sep = (flags & EXP_FULL) << CHAR_BIT;
7203         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7204
7205         switch (*name) {
7206         case '$':
7207                 num = rootpid;
7208                 goto numvar;
7209         case '?':
7210                 num = exitstatus;
7211                 goto numvar;
7212         case '#':
7213                 num = shellparam.nparam;
7214                 goto numvar;
7215         case '!':
7216                 num = backgndpid;
7217                 if (num == 0)
7218                         return -1;
7219  numvar:
7220                 len = cvtnum(num);
7221                 goto check_1char_name;
7222         case '-':
7223                 expdest = makestrspace(NOPTS, expdest);
7224                 for (i = NOPTS - 1; i >= 0; i--) {
7225                         if (optlist[i] && optletters(i)) {
7226                                 USTPUTC(optletters(i), expdest);
7227                                 len++;
7228                         }
7229                 }
7230  check_1char_name:
7231 #if 0
7232                 /* handles cases similar to ${#$1} */
7233                 if (name[2] != '\0')
7234                         raise_error_syntax("bad substitution");
7235 #endif
7236                 break;
7237         case '@':
7238                 if (quoted && sep)
7239                         goto param;
7240                 /* fall through */
7241         case '*': {
7242                 char **ap;
7243                 char sepc;
7244                 char c;
7245
7246                 /* We will set c to 0 or ~0 depending on whether
7247                  * we're doing field splitting.  We won't do field
7248                  * splitting if either we're quoted or sep is zero.
7249                  *
7250                  * Instead of testing (quoted || !sep) the following
7251                  * trick optimises away any branches by using the
7252                  * fact that EXP_QUOTED (which is the only bit that
7253                  * can be set in quoted) is the same as EXP_FULL <<
7254                  * CHAR_BIT (which is the only bit that can be set
7255                  * in sep).
7256                  */
7257 #if EXP_QUOTED >> CHAR_BIT != EXP_FULL
7258 #error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
7259 #endif
7260                 c = !((quoted | ~sep) & EXP_QUOTED) - 1;
7261                 sep &= ~quoted;
7262                 sep |= ifsset() ? (unsigned char)(c & ifsval()[0]) : ' ';
7263  param:
7264                 sepc = sep;
7265                 ap = shellparam.p;
7266                 if (!ap)
7267                         return -1;
7268                 while ((p = *ap++) != NULL) {
7269                         len += strtodest(p, syntax, quotes);
7270
7271                         if (*ap && sep) {
7272                                 len++;
7273                                 memtodest(&sepc, 1, syntax, quotes);
7274                         }
7275                 }
7276                 break;
7277         } /* case '*' */
7278         case '0':
7279         case '1':
7280         case '2':
7281         case '3':
7282         case '4':
7283         case '5':
7284         case '6':
7285         case '7':
7286         case '8':
7287         case '9':
7288                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7289                 if (num < 0 || num > shellparam.nparam)
7290                         return -1;
7291                 p = num ? shellparam.p[num - 1] : arg0;
7292                 goto value;
7293         default:
7294                 /* NB: name has form "VAR=..." */
7295                 p = lookupvar(name);
7296  value:
7297                 if (!p)
7298                         return -1;
7299
7300                 len = strtodest(p, syntax, quotes);
7301 #if ENABLE_UNICODE_SUPPORT
7302                 if (subtype == VSLENGTH && len > 0) {
7303                         reinit_unicode_for_ash();
7304                         if (unicode_status == UNICODE_ON) {
7305                                 STADJUST(-len, expdest);
7306                                 discard = 0;
7307                                 len = unicode_strlen(p);
7308                         }
7309                 }
7310 #endif
7311                 break;
7312         }
7313
7314         if (discard)
7315                 STADJUST(-len, expdest);
7316         return len;
7317 }
7318
7319 /*
7320  * Expand a variable, and return a pointer to the next character in the
7321  * input string.
7322  */
7323 static char *
7324 evalvar(char *p, int flag)
7325 {
7326         char varflags;
7327         char subtype;
7328         int quoted;
7329         char *var;
7330         int patloc;
7331         int startloc;
7332         ssize_t varlen;
7333
7334         varflags = (unsigned char) *p++;
7335         subtype = varflags & VSTYPE;
7336
7337         if (!subtype)
7338                 raise_error_syntax("bad substitution");
7339
7340         quoted = flag & EXP_QUOTED;
7341         var = p;
7342         startloc = expdest - (char *)stackblock();
7343         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7344
7345  again:
7346         varlen = varvalue(var, varflags, flag, quoted);
7347         if (varflags & VSNUL)
7348                 varlen--;
7349
7350         if (subtype == VSPLUS) {
7351                 varlen = -1 - varlen;
7352                 goto vsplus;
7353         }
7354
7355         if (subtype == VSMINUS) {
7356  vsplus:
7357                 if (varlen < 0) {
7358                         argstr(
7359                                 p,
7360                                 flag | EXP_TILDE | EXP_WORD
7361                         );
7362                         goto end;
7363                 }
7364                 goto record;
7365         }
7366
7367         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7368                 if (varlen >= 0)
7369                         goto record;
7370
7371                 subevalvar(p, var, 0, subtype, startloc, varflags,
7372                            flag & ~QUOTES_ESC);
7373                 varflags &= ~VSNUL;
7374                 /*
7375                  * Remove any recorded regions beyond
7376                  * start of variable
7377                  */
7378                 removerecordregions(startloc);
7379                 goto again;
7380         }
7381
7382         if (varlen < 0 && uflag)
7383                 varunset(p, var, 0, 0);
7384
7385         if (subtype == VSLENGTH) {
7386                 cvtnum(varlen > 0 ? varlen : 0);
7387                 goto record;
7388         }
7389
7390         if (subtype == VSNORMAL) {
7391  record:
7392                 if (quoted) {
7393                         quoted = *var == '@' && shellparam.nparam;
7394                         if (!quoted)
7395                                 goto end;
7396                 }
7397                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7398                 goto end;
7399         }
7400
7401 #if DEBUG
7402         switch (subtype) {
7403         case VSTRIMLEFT:
7404         case VSTRIMLEFTMAX:
7405         case VSTRIMRIGHT:
7406         case VSTRIMRIGHTMAX:
7407 #if BASH_SUBSTR
7408         case VSSUBSTR:
7409 #endif
7410 #if BASH_PATTERN_SUBST
7411         case VSREPLACE:
7412         case VSREPLACEALL:
7413 #endif
7414                 break;
7415         default:
7416                 abort();
7417         }
7418 #endif
7419
7420         if (varlen >= 0) {
7421                 /*
7422                  * Terminate the string and start recording the pattern
7423                  * right after it
7424                  */
7425                 STPUTC('\0', expdest);
7426                 patloc = expdest - (char *)stackblock();
7427                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7428                                 startloc, varflags, flag)) {
7429                         int amount = expdest - (
7430                                 (char *)stackblock() + patloc - 1
7431                         );
7432                         STADJUST(-amount, expdest);
7433                 }
7434                 /* Remove any recorded regions beyond start of variable */
7435                 removerecordregions(startloc);
7436                 goto record;
7437         }
7438
7439  end:
7440         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7441                 int nesting = 1;
7442                 for (;;) {
7443                         unsigned char c = *p++;
7444                         if (c == CTLESC)
7445                                 p++;
7446                         else if (c == CTLBACKQ) {
7447                                 if (varlen >= 0)
7448                                         argbackq = argbackq->next;
7449                         } else if (c == CTLVAR) {
7450                                 if ((*p++ & VSTYPE) != VSNORMAL)
7451                                         nesting++;
7452                         } else if (c == CTLENDVAR) {
7453                                 if (--nesting == 0)
7454                                         break;
7455                         }
7456                 }
7457         }
7458         return p;
7459 }
7460
7461 /*
7462  * Add a file name to the list.
7463  */
7464 static void
7465 addfname(const char *name)
7466 {
7467         struct strlist *sp;
7468
7469         sp = stzalloc(sizeof(*sp));
7470         sp->text = sstrdup(name);
7471         *exparg.lastp = sp;
7472         exparg.lastp = &sp->next;
7473 }
7474
7475 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7476 static int
7477 hasmeta(const char *p)
7478 {
7479         static const char chars[] ALIGN1 = {
7480                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7481         };
7482
7483         for (;;) {
7484                 p = strpbrk(p, chars);
7485                 if (!p)
7486                         break;
7487                 switch ((unsigned char)*p) {
7488                 case CTLQUOTEMARK:
7489                         for (;;) {
7490                                 p++;
7491                                 if ((unsigned char)*p == CTLQUOTEMARK)
7492                                         break;
7493                                 if ((unsigned char)*p == CTLESC)
7494                                         p++;
7495                                 if (*p == '\0') /* huh? */
7496                                         return 0;
7497                         }
7498                         break;
7499                 case '\\':
7500                 case CTLESC:
7501                         p++;
7502                         if (*p == '\0')
7503                                 return 0;
7504                         break;
7505                 case '[':
7506                         if (!strchr(p + 1, ']')) {
7507                                 /* It's not a properly closed [] pattern,
7508                                  * but other metas may follow. Continue checking.
7509                                  * my[file* _is_ globbed by bash
7510                                  * and matches filenames like "my[file1".
7511                                  */
7512                                 break;
7513                         }
7514                         /* fallthrough */
7515                 default:
7516                 /* case '*': */
7517                 /* case '?': */
7518                         return 1;
7519                 }
7520                 p++;
7521         }
7522
7523         return 0;
7524 }
7525
7526 /* If we want to use glob() from libc... */
7527 #if !ENABLE_ASH_INTERNAL_GLOB
7528
7529 /* Add the result of glob() to the list */
7530 static void
7531 addglob(const glob_t *pglob)
7532 {
7533         char **p = pglob->gl_pathv;
7534
7535         do {
7536                 addfname(*p);
7537         } while (*++p);
7538 }
7539 static void
7540 expandmeta(struct strlist *str /*, int flag*/)
7541 {
7542         /* TODO - EXP_REDIR */
7543
7544         while (str) {
7545                 char *p;
7546                 glob_t pglob;
7547                 int i;
7548
7549                 if (fflag)
7550                         goto nometa;
7551
7552                 if (!hasmeta(str->text))
7553                         goto nometa;
7554
7555                 INT_OFF;
7556                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7557 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7558 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7559 //
7560 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7561 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7562 // Which means you need to unescape the string, right? Not so fast:
7563 // if there _is_ a file named "file\?" (with backslash), it is returned
7564 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7565 // You DON'T KNOW by looking at the result whether you need to unescape it.
7566 //
7567 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7568 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7569 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7570 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7571 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7572 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7573                 i = glob(p, 0, NULL, &pglob);
7574                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7575                 if (p != str->text)
7576                         free(p);
7577                 switch (i) {
7578                 case 0:
7579 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7580                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7581                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7582                                 goto nometa2;
7583 #endif
7584                         addglob(&pglob);
7585                         globfree(&pglob);
7586                         INT_ON;
7587                         break;
7588                 case GLOB_NOMATCH:
7589  //nometa2:
7590                         globfree(&pglob);
7591                         INT_ON;
7592  nometa:
7593                         *exparg.lastp = str;
7594                         rmescapes(str->text, 0, NULL);
7595                         exparg.lastp = &str->next;
7596                         break;
7597                 default:        /* GLOB_NOSPACE */
7598                         globfree(&pglob);
7599                         INT_ON;
7600                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7601                 }
7602                 str = str->next;
7603         }
7604 }
7605
7606 #else
7607 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7608
7609 /*
7610  * Do metacharacter (i.e. *, ?, [...]) expansion.
7611  */
7612 typedef struct exp_t {
7613         char *dir;
7614         unsigned dir_max;
7615 } exp_t;
7616 static void
7617 expmeta(exp_t *exp, char *name, unsigned name_len, unsigned expdir_len)
7618 {
7619 #define expdir exp->dir
7620 #define expdir_max exp->dir_max
7621         char *enddir = expdir + expdir_len;
7622         char *p;
7623         const char *cp;
7624         char *start;
7625         char *endname;
7626         int metaflag;
7627         struct stat statb;
7628         DIR *dirp;
7629         struct dirent *dp;
7630         int atend;
7631         int matchdot;
7632         int esc;
7633
7634         metaflag = 0;
7635         start = name;
7636         for (p = name; esc = 0, *p; p += esc + 1) {
7637                 if (*p == '*' || *p == '?')
7638                         metaflag = 1;
7639                 else if (*p == '[') {
7640                         char *q = p + 1;
7641                         if (*q == '!')
7642                                 q++;
7643                         for (;;) {
7644                                 if (*q == '\\')
7645                                         q++;
7646                                 if (*q == '/' || *q == '\0')
7647                                         break;
7648                                 if (*++q == ']') {
7649                                         metaflag = 1;
7650                                         break;
7651                                 }
7652                         }
7653                 } else {
7654                         if (*p == '\\' && p[1])
7655                                 esc++;
7656                         if (p[esc] == '/') {
7657                                 if (metaflag)
7658                                         break;
7659                                 start = p + esc + 1;
7660                         }
7661                 }
7662         }
7663         if (metaflag == 0) {    /* we've reached the end of the file name */
7664                 if (!expdir_len)
7665                         return;
7666                 p = name;
7667                 do {
7668                         if (*p == '\\' && p[1])
7669                                 p++;
7670                         *enddir++ = *p;
7671                 } while (*p++);
7672                 if (lstat(expdir, &statb) == 0)
7673                         addfname(expdir);
7674                 return;
7675         }
7676         endname = p;
7677         if (name < start) {
7678                 p = name;
7679                 do {
7680                         if (*p == '\\' && p[1])
7681                                 p++;
7682                         *enddir++ = *p++;
7683                 } while (p < start);
7684         }
7685         *enddir = '\0';
7686         cp = expdir;
7687         expdir_len = enddir - cp;
7688         if (!expdir_len)
7689                 cp = ".";
7690         dirp = opendir(cp);
7691         if (dirp == NULL)
7692                 return;
7693         if (*endname == 0) {
7694                 atend = 1;
7695         } else {
7696                 atend = 0;
7697                 *endname = '\0';
7698                 endname += esc + 1;
7699         }
7700         name_len -= endname - name;
7701         matchdot = 0;
7702         p = start;
7703         if (*p == '\\')
7704                 p++;
7705         if (*p == '.')
7706                 matchdot++;
7707         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7708                 if (dp->d_name[0] == '.' && !matchdot)
7709                         continue;
7710                 if (pmatch(start, dp->d_name)) {
7711                         if (atend) {
7712                                 strcpy(enddir, dp->d_name);
7713                                 addfname(expdir);
7714                         } else {
7715                                 unsigned offset;
7716                                 unsigned len;
7717
7718                                 p = stpcpy(enddir, dp->d_name);
7719                                 *p = '/';
7720
7721                                 offset = p - expdir + 1;
7722                                 len = offset + name_len + NAME_MAX;
7723                                 if (len > expdir_max) {
7724                                         len += PATH_MAX;
7725                                         expdir = ckrealloc(expdir, len);
7726                                         expdir_max = len;
7727                                 }
7728
7729                                 expmeta(exp, endname, name_len, offset);
7730                                 enddir = expdir + expdir_len;
7731                         }
7732                 }
7733         }
7734         closedir(dirp);
7735         if (!atend)
7736                 endname[-esc - 1] = esc ? '\\' : '/';
7737 #undef expdir
7738 #undef expdir_max
7739 }
7740
7741 static struct strlist *
7742 msort(struct strlist *list, int len)
7743 {
7744         struct strlist *p, *q = NULL;
7745         struct strlist **lpp;
7746         int half;
7747         int n;
7748
7749         if (len <= 1)
7750                 return list;
7751         half = len >> 1;
7752         p = list;
7753         for (n = half; --n >= 0;) {
7754                 q = p;
7755                 p = p->next;
7756         }
7757         q->next = NULL;                 /* terminate first half of list */
7758         q = msort(list, half);          /* sort first half of list */
7759         p = msort(p, len - half);               /* sort second half */
7760         lpp = &list;
7761         for (;;) {
7762 #if ENABLE_LOCALE_SUPPORT
7763                 if (strcoll(p->text, q->text) < 0)
7764 #else
7765                 if (strcmp(p->text, q->text) < 0)
7766 #endif
7767                                                 {
7768                         *lpp = p;
7769                         lpp = &p->next;
7770                         p = *lpp;
7771                         if (p == NULL) {
7772                                 *lpp = q;
7773                                 break;
7774                         }
7775                 } else {
7776                         *lpp = q;
7777                         lpp = &q->next;
7778                         q = *lpp;
7779                         if (q == NULL) {
7780                                 *lpp = p;
7781                                 break;
7782                         }
7783                 }
7784         }
7785         return list;
7786 }
7787
7788 /*
7789  * Sort the results of file name expansion.  It calculates the number of
7790  * strings to sort and then calls msort (short for merge sort) to do the
7791  * work.
7792  */
7793 static struct strlist *
7794 expsort(struct strlist *str)
7795 {
7796         int len;
7797         struct strlist *sp;
7798
7799         len = 0;
7800         for (sp = str; sp; sp = sp->next)
7801                 len++;
7802         return msort(str, len);
7803 }
7804
7805 static void
7806 expandmeta(struct strlist *str /*, int flag*/)
7807 {
7808         /* TODO - EXP_REDIR */
7809
7810         while (str) {
7811                 exp_t exp;
7812                 struct strlist **savelastp;
7813                 struct strlist *sp;
7814                 char *p;
7815                 unsigned len;
7816
7817                 if (fflag)
7818                         goto nometa;
7819                 if (!hasmeta(str->text))
7820                         goto nometa;
7821                 savelastp = exparg.lastp;
7822
7823                 INT_OFF;
7824                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7825                 len = strlen(p);
7826                 exp.dir_max = len + PATH_MAX;
7827                 exp.dir = ckmalloc(exp.dir_max);
7828
7829                 expmeta(&exp, p, len, 0);
7830                 free(exp.dir);
7831                 if (p != str->text)
7832                         free(p);
7833                 INT_ON;
7834                 if (exparg.lastp == savelastp) {
7835                         /*
7836                          * no matches
7837                          */
7838  nometa:
7839                         *exparg.lastp = str;
7840                         rmescapes(str->text, 0, NULL);
7841                         exparg.lastp = &str->next;
7842                 } else {
7843                         *exparg.lastp = NULL;
7844                         *savelastp = sp = expsort(*savelastp);
7845                         while (sp->next != NULL)
7846                                 sp = sp->next;
7847                         exparg.lastp = &sp->next;
7848                 }
7849                 str = str->next;
7850         }
7851 }
7852 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7853
7854 /*
7855  * Perform variable substitution and command substitution on an argument,
7856  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7857  * perform splitting and file name expansion.  When arglist is NULL, perform
7858  * here document expansion.
7859  */
7860 static void
7861 expandarg(union node *arg, struct arglist *arglist, int flag)
7862 {
7863         struct strlist *sp;
7864         char *p;
7865
7866         argbackq = arg->narg.backquote;
7867         STARTSTACKSTR(expdest);
7868         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7869         argstr(arg->narg.text, flag);
7870         p = _STPUTC('\0', expdest);
7871         expdest = p - 1;
7872         if (arglist == NULL) {
7873                 /* here document expanded */
7874                 goto out;
7875         }
7876         p = grabstackstr(p);
7877         TRACE(("expandarg: p:'%s'\n", p));
7878         exparg.lastp = &exparg.list;
7879         /*
7880          * TODO - EXP_REDIR
7881          */
7882         if (flag & EXP_FULL) {
7883                 ifsbreakup(p, &exparg);
7884                 *exparg.lastp = NULL;
7885                 exparg.lastp = &exparg.list;
7886                 expandmeta(exparg.list /*, flag*/);
7887         } else {
7888                 sp = stzalloc(sizeof(*sp));
7889                 sp->text = p;
7890                 *exparg.lastp = sp;
7891                 exparg.lastp = &sp->next;
7892         }
7893         *exparg.lastp = NULL;
7894         if (exparg.list) {
7895                 *arglist->lastp = exparg.list;
7896                 arglist->lastp = exparg.lastp;
7897         }
7898
7899  out:
7900         ifsfree();
7901 }
7902
7903 /*
7904  * Expand shell variables and backquotes inside a here document.
7905  */
7906 static void
7907 expandhere(union node *arg, int fd)
7908 {
7909         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7910         full_write(fd, stackblock(), expdest - (char *)stackblock());
7911 }
7912
7913 /*
7914  * Returns true if the pattern matches the string.
7915  */
7916 static int
7917 patmatch(char *pattern, const char *string)
7918 {
7919         char *p = preglob(pattern, 0);
7920         int r = pmatch(p, string);
7921         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7922         return r;
7923 }
7924
7925 /*
7926  * See if a pattern matches in a case statement.
7927  */
7928 static int
7929 casematch(union node *pattern, char *val)
7930 {
7931         struct stackmark smark;
7932         int result;
7933
7934         setstackmark(&smark);
7935         argbackq = pattern->narg.backquote;
7936         STARTSTACKSTR(expdest);
7937         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7938         STACKSTRNUL(expdest);
7939         ifsfree();
7940         result = patmatch(stackblock(), val);
7941         popstackmark(&smark);
7942         return result;
7943 }
7944
7945
7946 /* ============ find_command */
7947
7948 struct builtincmd {
7949         const char *name;
7950         int (*builtin)(int, char **) FAST_FUNC;
7951         /* unsigned flags; */
7952 };
7953 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7954 /* "regular" builtins always take precedence over commands,
7955  * regardless of PATH=....%builtin... position */
7956 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7957 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7958
7959 struct cmdentry {
7960         smallint cmdtype;       /* CMDxxx */
7961         union param {
7962                 int index;
7963                 /* index >= 0 for commands without path (slashes) */
7964                 /* (TODO: what exactly does the value mean? PATH position?) */
7965                 /* index == -1 for commands with slashes */
7966                 /* index == (-2 - applet_no) for NOFORK applets */
7967                 const struct builtincmd *cmd;
7968                 struct funcnode *func;
7969         } u;
7970 };
7971 /* values of cmdtype */
7972 #define CMDUNKNOWN      -1      /* no entry in table for command */
7973 #define CMDNORMAL       0       /* command is an executable program */
7974 #define CMDFUNCTION     1       /* command is a shell function */
7975 #define CMDBUILTIN      2       /* command is a shell builtin */
7976
7977 /* action to find_command() */
7978 #define DO_ERR          0x01    /* prints errors */
7979 #define DO_ABS          0x02    /* checks absolute paths */
7980 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7981 #define DO_ALTPATH      0x08    /* using alternate path */
7982 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7983
7984 static void find_command(char *, struct cmdentry *, int, const char *);
7985
7986
7987 /* ============ Hashing commands */
7988
7989 /*
7990  * When commands are first encountered, they are entered in a hash table.
7991  * This ensures that a full path search will not have to be done for them
7992  * on each invocation.
7993  *
7994  * We should investigate converting to a linear search, even though that
7995  * would make the command name "hash" a misnomer.
7996  */
7997
7998 struct tblentry {
7999         struct tblentry *next;  /* next entry in hash chain */
8000         union param param;      /* definition of builtin function */
8001         smallint cmdtype;       /* CMDxxx */
8002         char rehash;            /* if set, cd done since entry created */
8003         char cmdname[1];        /* name of command */
8004 };
8005
8006 static struct tblentry **cmdtable;
8007 #define INIT_G_cmdtable() do { \
8008         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
8009 } while (0)
8010
8011 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
8012
8013
8014 static void
8015 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
8016 {
8017 #if ENABLE_FEATURE_SH_STANDALONE
8018         if (applet_no >= 0) {
8019 # if NUM_SCRIPTS > 0
8020                 if (applet_no < NUM_APPLETS)
8021 # endif
8022                 if (APPLET_IS_NOEXEC(applet_no)) {
8023                         clearenv();
8024                         while (*envp)
8025                                 putenv(*envp++);
8026                         popredir(/*drop:*/ 1);
8027                         run_noexec_applet_and_exit(applet_no, cmd, argv);
8028                 }
8029                 /* re-exec ourselves with the new arguments */
8030                 execve(bb_busybox_exec_path, argv, envp);
8031                 /* If they called chroot or otherwise made the binary no longer
8032                  * executable, fall through */
8033         }
8034 #endif
8035
8036  repeat:
8037 #ifdef SYSV
8038         do {
8039                 execve(cmd, argv, envp);
8040         } while (errno == EINTR);
8041 #else
8042         execve(cmd, argv, envp);
8043 #endif
8044
8045         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8046                 /* Run "cmd" as a shell script:
8047                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8048                  * "If the execve() function fails with ENOEXEC, the shell
8049                  * shall execute a command equivalent to having a shell invoked
8050                  * with the command name as its first operand,
8051                  * with any remaining arguments passed to the new shell"
8052                  *
8053                  * That is, do not use $SHELL, user's shell, or /bin/sh;
8054                  * just call ourselves.
8055                  *
8056                  * Note that bash reads ~80 chars of the file, and if it sees
8057                  * a zero byte before it sees newline, it doesn't try to
8058                  * interpret it, but fails with "cannot execute binary file"
8059                  * message and exit code 126. For one, this prevents attempts
8060                  * to interpret foreign ELF binaries as shell scripts.
8061                  */
8062                 argv[0] = (char*) cmd;
8063                 cmd = bb_busybox_exec_path;
8064                 /* NB: this is only possible because all callers of shellexec()
8065                  * ensure that the argv[-1] slot exists!
8066                  */
8067                 argv--;
8068                 argv[0] = (char*) "ash";
8069                 goto repeat;
8070         }
8071 }
8072
8073 /*
8074  * Exec a program.  Never returns.  If you change this routine, you may
8075  * have to change the find_command routine as well.
8076  * argv[-1] must exist and be writable! See tryexec() for why.
8077  */
8078 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8079 static void shellexec(char *prog, char **argv, const char *path, int idx)
8080 {
8081         char *cmdname;
8082         int e;
8083         char **envp;
8084         int exerrno;
8085         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8086
8087         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8088         if (strchr(prog, '/') != NULL
8089 #if ENABLE_FEATURE_SH_STANDALONE
8090          || (applet_no = find_applet_by_name(prog)) >= 0
8091 # if NUM_SCRIPTS > 0
8092          || (applet_no = NUM_APPLETS + find_script_by_name(prog)) >= 0
8093 # endif
8094 #endif
8095         ) {
8096                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8097                 if (applet_no >= 0) {
8098                         /* We tried execing ourself, but it didn't work.
8099                          * Maybe /proc/self/exe doesn't exist?
8100                          * Try $PATH search.
8101                          */
8102                         goto try_PATH;
8103                 }
8104                 e = errno;
8105         } else {
8106  try_PATH:
8107                 e = ENOENT;
8108                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8109                         if (--idx < 0 && pathopt == NULL) {
8110                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8111                                 if (errno != ENOENT && errno != ENOTDIR)
8112                                         e = errno;
8113                         }
8114                         stunalloc(cmdname);
8115                 }
8116         }
8117
8118         /* Map to POSIX errors */
8119         switch (e) {
8120         default:
8121                 exerrno = 126;
8122                 break;
8123         case ELOOP:
8124         case ENAMETOOLONG:
8125         case ENOENT:
8126         case ENOTDIR:
8127                 exerrno = 127;
8128                 break;
8129         }
8130         exitstatus = exerrno;
8131         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8132                 prog, e, suppress_int));
8133         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8134         /* NOTREACHED */
8135 }
8136
8137 static void
8138 printentry(struct tblentry *cmdp)
8139 {
8140         int idx;
8141         const char *path;
8142         char *name;
8143
8144         idx = cmdp->param.index;
8145         path = pathval();
8146         do {
8147                 name = path_advance(&path, cmdp->cmdname);
8148                 stunalloc(name);
8149         } while (--idx >= 0);
8150         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8151 }
8152
8153 /*
8154  * Clear out command entries.  The argument specifies the first entry in
8155  * PATH which has changed.
8156  */
8157 static void
8158 clearcmdentry(int firstchange)
8159 {
8160         struct tblentry **tblp;
8161         struct tblentry **pp;
8162         struct tblentry *cmdp;
8163
8164         INT_OFF;
8165         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8166                 pp = tblp;
8167                 while ((cmdp = *pp) != NULL) {
8168                         if ((cmdp->cmdtype == CMDNORMAL &&
8169                              cmdp->param.index >= firstchange)
8170                          || (cmdp->cmdtype == CMDBUILTIN &&
8171                              builtinloc >= firstchange)
8172                         ) {
8173                                 *pp = cmdp->next;
8174                                 free(cmdp);
8175                         } else {
8176                                 pp = &cmdp->next;
8177                         }
8178                 }
8179         }
8180         INT_ON;
8181 }
8182
8183 /*
8184  * Locate a command in the command hash table.  If "add" is nonzero,
8185  * add the command to the table if it is not already present.  The
8186  * variable "lastcmdentry" is set to point to the address of the link
8187  * pointing to the entry, so that delete_cmd_entry can delete the
8188  * entry.
8189  *
8190  * Interrupts must be off if called with add != 0.
8191  */
8192 static struct tblentry **lastcmdentry;
8193
8194 static struct tblentry *
8195 cmdlookup(const char *name, int add)
8196 {
8197         unsigned int hashval;
8198         const char *p;
8199         struct tblentry *cmdp;
8200         struct tblentry **pp;
8201
8202         p = name;
8203         hashval = (unsigned char)*p << 4;
8204         while (*p)
8205                 hashval += (unsigned char)*p++;
8206         hashval &= 0x7FFF;
8207         pp = &cmdtable[hashval % CMDTABLESIZE];
8208         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8209                 if (strcmp(cmdp->cmdname, name) == 0)
8210                         break;
8211                 pp = &cmdp->next;
8212         }
8213         if (add && cmdp == NULL) {
8214                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8215                                 + strlen(name)
8216                                 /* + 1 - already done because
8217                                  * tblentry::cmdname is char[1] */);
8218                 /*cmdp->next = NULL; - ckzalloc did it */
8219                 cmdp->cmdtype = CMDUNKNOWN;
8220                 strcpy(cmdp->cmdname, name);
8221         }
8222         lastcmdentry = pp;
8223         return cmdp;
8224 }
8225
8226 /*
8227  * Delete the command entry returned on the last lookup.
8228  */
8229 static void
8230 delete_cmd_entry(void)
8231 {
8232         struct tblentry *cmdp;
8233
8234         INT_OFF;
8235         cmdp = *lastcmdentry;
8236         *lastcmdentry = cmdp->next;
8237         if (cmdp->cmdtype == CMDFUNCTION)
8238                 freefunc(cmdp->param.func);
8239         free(cmdp);
8240         INT_ON;
8241 }
8242
8243 /*
8244  * Add a new command entry, replacing any existing command entry for
8245  * the same name - except special builtins.
8246  */
8247 static void
8248 addcmdentry(char *name, struct cmdentry *entry)
8249 {
8250         struct tblentry *cmdp;
8251
8252         cmdp = cmdlookup(name, 1);
8253         if (cmdp->cmdtype == CMDFUNCTION) {
8254                 freefunc(cmdp->param.func);
8255         }
8256         cmdp->cmdtype = entry->cmdtype;
8257         cmdp->param = entry->u;
8258         cmdp->rehash = 0;
8259 }
8260
8261 static int FAST_FUNC
8262 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8263 {
8264         struct tblentry **pp;
8265         struct tblentry *cmdp;
8266         int c;
8267         struct cmdentry entry;
8268         char *name;
8269
8270         if (nextopt("r") != '\0') {
8271                 clearcmdentry(0);
8272                 return 0;
8273         }
8274
8275         if (*argptr == NULL) {
8276                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8277                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8278                                 if (cmdp->cmdtype == CMDNORMAL)
8279                                         printentry(cmdp);
8280                         }
8281                 }
8282                 return 0;
8283         }
8284
8285         c = 0;
8286         while ((name = *argptr) != NULL) {
8287                 cmdp = cmdlookup(name, 0);
8288                 if (cmdp != NULL
8289                  && (cmdp->cmdtype == CMDNORMAL
8290                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8291                 ) {
8292                         delete_cmd_entry();
8293                 }
8294                 find_command(name, &entry, DO_ERR, pathval());
8295                 if (entry.cmdtype == CMDUNKNOWN)
8296                         c = 1;
8297                 argptr++;
8298         }
8299         return c;
8300 }
8301
8302 /*
8303  * Called when a cd is done.  Marks all commands so the next time they
8304  * are executed they will be rehashed.
8305  */
8306 static void
8307 hashcd(void)
8308 {
8309         struct tblentry **pp;
8310         struct tblentry *cmdp;
8311
8312         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8313                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8314                         if (cmdp->cmdtype == CMDNORMAL
8315                          || (cmdp->cmdtype == CMDBUILTIN
8316                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8317                              && builtinloc > 0)
8318                         ) {
8319                                 cmdp->rehash = 1;
8320                         }
8321                 }
8322         }
8323 }
8324
8325 /*
8326  * Fix command hash table when PATH changed.
8327  * Called before PATH is changed.  The argument is the new value of PATH;
8328  * pathval() still returns the old value at this point.
8329  * Called with interrupts off.
8330  */
8331 static void FAST_FUNC
8332 changepath(const char *new)
8333 {
8334         const char *old;
8335         int firstchange;
8336         int idx;
8337         int idx_bltin;
8338
8339         old = pathval();
8340         firstchange = 9999;     /* assume no change */
8341         idx = 0;
8342         idx_bltin = -1;
8343         for (;;) {
8344                 if (*old != *new) {
8345                         firstchange = idx;
8346                         if ((*old == '\0' && *new == ':')
8347                          || (*old == ':' && *new == '\0')
8348                         ) {
8349                                 firstchange++;
8350                         }
8351                         old = new;      /* ignore subsequent differences */
8352                 }
8353                 if (*new == '\0')
8354                         break;
8355                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8356                         idx_bltin = idx;
8357                 if (*new == ':')
8358                         idx++;
8359                 new++;
8360                 old++;
8361         }
8362         if (builtinloc < 0 && idx_bltin >= 0)
8363                 builtinloc = idx_bltin;             /* zap builtins */
8364         if (builtinloc >= 0 && idx_bltin < 0)
8365                 firstchange = 0;
8366         clearcmdentry(firstchange);
8367         builtinloc = idx_bltin;
8368 }
8369 enum {
8370         TEOF,
8371         TNL,
8372         TREDIR,
8373         TWORD,
8374         TSEMI,
8375         TBACKGND,
8376         TAND,
8377         TOR,
8378         TPIPE,
8379         TLP,
8380         TRP,
8381         TENDCASE,
8382         TENDBQUOTE,
8383         TNOT,
8384         TCASE,
8385         TDO,
8386         TDONE,
8387         TELIF,
8388         TELSE,
8389         TESAC,
8390         TFI,
8391         TFOR,
8392 #if BASH_FUNCTION
8393         TFUNCTION,
8394 #endif
8395         TIF,
8396         TIN,
8397         TTHEN,
8398         TUNTIL,
8399         TWHILE,
8400         TBEGIN,
8401         TEND
8402 };
8403 typedef smallint token_id_t;
8404
8405 /* Nth bit indicates if token marks the end of a list */
8406 enum {
8407         tokendlist = 0
8408         /*  0 */ | (1u << TEOF)
8409         /*  1 */ | (0u << TNL)
8410         /*  2 */ | (0u << TREDIR)
8411         /*  3 */ | (0u << TWORD)
8412         /*  4 */ | (0u << TSEMI)
8413         /*  5 */ | (0u << TBACKGND)
8414         /*  6 */ | (0u << TAND)
8415         /*  7 */ | (0u << TOR)
8416         /*  8 */ | (0u << TPIPE)
8417         /*  9 */ | (0u << TLP)
8418         /* 10 */ | (1u << TRP)
8419         /* 11 */ | (1u << TENDCASE)
8420         /* 12 */ | (1u << TENDBQUOTE)
8421         /* 13 */ | (0u << TNOT)
8422         /* 14 */ | (0u << TCASE)
8423         /* 15 */ | (1u << TDO)
8424         /* 16 */ | (1u << TDONE)
8425         /* 17 */ | (1u << TELIF)
8426         /* 18 */ | (1u << TELSE)
8427         /* 19 */ | (1u << TESAC)
8428         /* 20 */ | (1u << TFI)
8429         /* 21 */ | (0u << TFOR)
8430 #if BASH_FUNCTION
8431         /* 22 */ | (0u << TFUNCTION)
8432 #endif
8433         /* 23 */ | (0u << TIF)
8434         /* 24 */ | (0u << TIN)
8435         /* 25 */ | (1u << TTHEN)
8436         /* 26 */ | (0u << TUNTIL)
8437         /* 27 */ | (0u << TWHILE)
8438         /* 28 */ | (0u << TBEGIN)
8439         /* 29 */ | (1u << TEND)
8440         , /* thus far 29 bits used */
8441 };
8442
8443 static const char *const tokname_array[] = {
8444         "end of file",
8445         "newline",
8446         "redirection",
8447         "word",
8448         ";",
8449         "&",
8450         "&&",
8451         "||",
8452         "|",
8453         "(",
8454         ")",
8455         ";;",
8456         "`",
8457 #define KWDOFFSET 13
8458         /* the following are keywords */
8459         "!",
8460         "case",
8461         "do",
8462         "done",
8463         "elif",
8464         "else",
8465         "esac",
8466         "fi",
8467         "for",
8468 #if BASH_FUNCTION
8469         "function",
8470 #endif
8471         "if",
8472         "in",
8473         "then",
8474         "until",
8475         "while",
8476         "{",
8477         "}",
8478 };
8479
8480 /* Wrapper around strcmp for qsort/bsearch/... */
8481 static int
8482 pstrcmp(const void *a, const void *b)
8483 {
8484         return strcmp((char*)a, *(char**)b);
8485 }
8486
8487 static const char *const *
8488 findkwd(const char *s)
8489 {
8490         return bsearch(s, tokname_array + KWDOFFSET,
8491                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8492                         sizeof(tokname_array[0]), pstrcmp);
8493 }
8494
8495 /*
8496  * Locate and print what a word is...
8497  */
8498 static int
8499 describe_command(char *command, const char *path, int describe_command_verbose)
8500 {
8501         struct cmdentry entry;
8502 #if ENABLE_ASH_ALIAS
8503         const struct alias *ap;
8504 #endif
8505
8506         path = path ? path : pathval();
8507
8508         if (describe_command_verbose) {
8509                 out1str(command);
8510         }
8511
8512         /* First look at the keywords */
8513         if (findkwd(command)) {
8514                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8515                 goto out;
8516         }
8517
8518 #if ENABLE_ASH_ALIAS
8519         /* Then look at the aliases */
8520         ap = lookupalias(command, 0);
8521         if (ap != NULL) {
8522                 if (!describe_command_verbose) {
8523                         out1str("alias ");
8524                         printalias(ap);
8525                         return 0;
8526                 }
8527                 out1fmt(" is an alias for %s", ap->val);
8528                 goto out;
8529         }
8530 #endif
8531         /* Brute force */
8532         find_command(command, &entry, DO_ABS, path);
8533
8534         switch (entry.cmdtype) {
8535         case CMDNORMAL: {
8536                 int j = entry.u.index;
8537                 char *p;
8538                 if (j < 0) {
8539                         p = command;
8540                 } else {
8541                         do {
8542                                 p = path_advance(&path, command);
8543                                 stunalloc(p);
8544                         } while (--j >= 0);
8545                 }
8546                 if (describe_command_verbose) {
8547                         out1fmt(" is %s", p);
8548                 } else {
8549                         out1str(p);
8550                 }
8551                 break;
8552         }
8553
8554         case CMDFUNCTION:
8555                 if (describe_command_verbose) {
8556                         /*out1str(" is a shell function");*/
8557                         out1str(" is a function"); /* bash says this */
8558                 } else {
8559                         out1str(command);
8560                 }
8561                 break;
8562
8563         case CMDBUILTIN:
8564                 if (describe_command_verbose) {
8565                         out1fmt(" is a %sshell builtin",
8566                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8567                                         "special " : nullstr
8568                         );
8569                 } else {
8570                         out1str(command);
8571                 }
8572                 break;
8573
8574         default:
8575                 if (describe_command_verbose) {
8576                         out1str(": not found\n");
8577                 }
8578                 return 127;
8579         }
8580  out:
8581         out1str("\n");
8582         return 0;
8583 }
8584
8585 static int FAST_FUNC
8586 typecmd(int argc UNUSED_PARAM, char **argv)
8587 {
8588         int i = 1;
8589         int err = 0;
8590         int verbose = 1;
8591
8592         /* type -p ... ? (we don't bother checking for 'p') */
8593         if (argv[1] && argv[1][0] == '-') {
8594                 i++;
8595                 verbose = 0;
8596         }
8597         while (argv[i]) {
8598                 err |= describe_command(argv[i++], NULL, verbose);
8599         }
8600         return err;
8601 }
8602
8603 #if ENABLE_ASH_CMDCMD
8604 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8605 static char **
8606 parse_command_args(char **argv, const char **path)
8607 {
8608         char *cp, c;
8609
8610         for (;;) {
8611                 cp = *++argv;
8612                 if (!cp)
8613                         return NULL;
8614                 if (*cp++ != '-')
8615                         break;
8616                 c = *cp++;
8617                 if (!c)
8618                         break;
8619                 if (c == '-' && !*cp) {
8620                         if (!*++argv)
8621                                 return NULL;
8622                         break;
8623                 }
8624                 do {
8625                         switch (c) {
8626                         case 'p':
8627                                 *path = bb_default_path;
8628                                 break;
8629                         default:
8630                                 /* run 'typecmd' for other options */
8631                                 return NULL;
8632                         }
8633                         c = *cp++;
8634                 } while (c);
8635         }
8636         return argv;
8637 }
8638
8639 static int FAST_FUNC
8640 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8641 {
8642         char *cmd;
8643         int c;
8644         enum {
8645                 VERIFY_BRIEF = 1,
8646                 VERIFY_VERBOSE = 2,
8647         } verify = 0;
8648         const char *path = NULL;
8649
8650         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8651          * never reaches this function.
8652          */
8653
8654         while ((c = nextopt("pvV")) != '\0')
8655                 if (c == 'V')
8656                         verify |= VERIFY_VERBOSE;
8657                 else if (c == 'v')
8658                         /*verify |= VERIFY_BRIEF*/;
8659 #if DEBUG
8660                 else if (c != 'p')
8661                         abort();
8662 #endif
8663                 else
8664                         path = bb_default_path;
8665
8666         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8667         cmd = *argptr;
8668         if (/*verify && */ cmd)
8669                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8670
8671         return 0;
8672 }
8673 #endif
8674
8675
8676 /*static int funcblocksize;     // size of structures in function */
8677 /*static int funcstringsize;    // size of strings in node */
8678 static void *funcblock;         /* block to allocate function from */
8679 static char *funcstring_end;    /* end of block to allocate strings from */
8680
8681 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8682         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8683         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8684         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8685         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8686         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8687         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8688         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8689         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8690         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8691         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8692         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8693         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8694         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8695         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8696         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8697         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8698         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8699 #if BASH_REDIR_OUTPUT
8700         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8701 #endif
8702         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8703         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8704         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8705         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8706         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8707         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8708         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8709         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8710         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8711 };
8712
8713 static int calcsize(int funcblocksize, union node *n);
8714
8715 static int
8716 sizenodelist(int funcblocksize, struct nodelist *lp)
8717 {
8718         while (lp) {
8719                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8720                 funcblocksize = calcsize(funcblocksize, lp->n);
8721                 lp = lp->next;
8722         }
8723         return funcblocksize;
8724 }
8725
8726 static int
8727 calcsize(int funcblocksize, union node *n)
8728 {
8729         if (n == NULL)
8730                 return funcblocksize;
8731         funcblocksize += nodesize[n->type];
8732         switch (n->type) {
8733         case NCMD:
8734                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8735                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8736                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8737                 break;
8738         case NPIPE:
8739                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8740                 break;
8741         case NREDIR:
8742         case NBACKGND:
8743         case NSUBSHELL:
8744                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8745                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8746                 break;
8747         case NAND:
8748         case NOR:
8749         case NSEMI:
8750         case NWHILE:
8751         case NUNTIL:
8752                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8753                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8754                 break;
8755         case NIF:
8756                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8757                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8758                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8759                 break;
8760         case NFOR:
8761                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8762                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8763                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8764                 break;
8765         case NCASE:
8766                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8767                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8768                 break;
8769         case NCLIST:
8770                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8771                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8772                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8773                 break;
8774         case NDEFUN:
8775                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8776                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8777                 break;
8778         case NARG:
8779                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8780                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8781                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8782                 break;
8783         case NTO:
8784 #if BASH_REDIR_OUTPUT
8785         case NTO2:
8786 #endif
8787         case NCLOBBER:
8788         case NFROM:
8789         case NFROMTO:
8790         case NAPPEND:
8791                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8792                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8793                 break;
8794         case NTOFD:
8795         case NFROMFD:
8796                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8797                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8798         break;
8799         case NHERE:
8800         case NXHERE:
8801                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8802                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8803                 break;
8804         case NNOT:
8805                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8806                 break;
8807         };
8808         return funcblocksize;
8809 }
8810
8811 static char *
8812 nodeckstrdup(char *s)
8813 {
8814         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8815         return strcpy(funcstring_end, s);
8816 }
8817
8818 static union node *copynode(union node *);
8819
8820 static struct nodelist *
8821 copynodelist(struct nodelist *lp)
8822 {
8823         struct nodelist *start;
8824         struct nodelist **lpp;
8825
8826         lpp = &start;
8827         while (lp) {
8828                 *lpp = funcblock;
8829                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8830                 (*lpp)->n = copynode(lp->n);
8831                 lp = lp->next;
8832                 lpp = &(*lpp)->next;
8833         }
8834         *lpp = NULL;
8835         return start;
8836 }
8837
8838 static union node *
8839 copynode(union node *n)
8840 {
8841         union node *new;
8842
8843         if (n == NULL)
8844                 return NULL;
8845         new = funcblock;
8846         funcblock = (char *) funcblock + nodesize[n->type];
8847
8848         switch (n->type) {
8849         case NCMD:
8850                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8851                 new->ncmd.args = copynode(n->ncmd.args);
8852                 new->ncmd.assign = copynode(n->ncmd.assign);
8853                 new->ncmd.linno = n->ncmd.linno;
8854                 break;
8855         case NPIPE:
8856                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8857                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8858                 break;
8859         case NREDIR:
8860         case NBACKGND:
8861         case NSUBSHELL:
8862                 new->nredir.redirect = copynode(n->nredir.redirect);
8863                 new->nredir.n = copynode(n->nredir.n);
8864                 new->nredir.linno = n->nredir.linno;
8865                 break;
8866         case NAND:
8867         case NOR:
8868         case NSEMI:
8869         case NWHILE:
8870         case NUNTIL:
8871                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8872                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8873                 break;
8874         case NIF:
8875                 new->nif.elsepart = copynode(n->nif.elsepart);
8876                 new->nif.ifpart = copynode(n->nif.ifpart);
8877                 new->nif.test = copynode(n->nif.test);
8878                 break;
8879         case NFOR:
8880                 new->nfor.var = nodeckstrdup(n->nfor.var);
8881                 new->nfor.body = copynode(n->nfor.body);
8882                 new->nfor.args = copynode(n->nfor.args);
8883                 new->nfor.linno = n->nfor.linno;
8884                 break;
8885         case NCASE:
8886                 new->ncase.cases = copynode(n->ncase.cases);
8887                 new->ncase.expr = copynode(n->ncase.expr);
8888                 new->ncase.linno = n->ncase.linno;
8889                 break;
8890         case NCLIST:
8891                 new->nclist.body = copynode(n->nclist.body);
8892                 new->nclist.pattern = copynode(n->nclist.pattern);
8893                 new->nclist.next = copynode(n->nclist.next);
8894                 break;
8895         case NDEFUN:
8896                 new->ndefun.body = copynode(n->ndefun.body);
8897                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8898                 new->ndefun.linno = n->ndefun.linno;
8899                 break;
8900         case NARG:
8901                 new->narg.backquote = copynodelist(n->narg.backquote);
8902                 new->narg.text = nodeckstrdup(n->narg.text);
8903                 new->narg.next = copynode(n->narg.next);
8904                 break;
8905         case NTO:
8906 #if BASH_REDIR_OUTPUT
8907         case NTO2:
8908 #endif
8909         case NCLOBBER:
8910         case NFROM:
8911         case NFROMTO:
8912         case NAPPEND:
8913                 new->nfile.fname = copynode(n->nfile.fname);
8914                 new->nfile.fd = n->nfile.fd;
8915                 new->nfile.next = copynode(n->nfile.next);
8916                 break;
8917         case NTOFD:
8918         case NFROMFD:
8919                 new->ndup.vname = copynode(n->ndup.vname);
8920                 new->ndup.dupfd = n->ndup.dupfd;
8921                 new->ndup.fd = n->ndup.fd;
8922                 new->ndup.next = copynode(n->ndup.next);
8923                 break;
8924         case NHERE:
8925         case NXHERE:
8926                 new->nhere.doc = copynode(n->nhere.doc);
8927                 new->nhere.fd = n->nhere.fd;
8928                 new->nhere.next = copynode(n->nhere.next);
8929                 break;
8930         case NNOT:
8931                 new->nnot.com = copynode(n->nnot.com);
8932                 break;
8933         };
8934         new->type = n->type;
8935         return new;
8936 }
8937
8938 /*
8939  * Make a copy of a parse tree.
8940  */
8941 static struct funcnode *
8942 copyfunc(union node *n)
8943 {
8944         struct funcnode *f;
8945         size_t blocksize;
8946
8947         /*funcstringsize = 0;*/
8948         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8949         f = ckzalloc(blocksize /* + funcstringsize */);
8950         funcblock = (char *) f + offsetof(struct funcnode, n);
8951         funcstring_end = (char *) f + blocksize;
8952         copynode(n);
8953         /* f->count = 0; - ckzalloc did it */
8954         return f;
8955 }
8956
8957 /*
8958  * Define a shell function.
8959  */
8960 static void
8961 defun(union node *func)
8962 {
8963         struct cmdentry entry;
8964
8965         INT_OFF;
8966         entry.cmdtype = CMDFUNCTION;
8967         entry.u.func = copyfunc(func);
8968         addcmdentry(func->ndefun.text, &entry);
8969         INT_ON;
8970 }
8971
8972 /* Reasons for skipping commands (see comment on breakcmd routine) */
8973 #define SKIPBREAK      (1 << 0)
8974 #define SKIPCONT       (1 << 1)
8975 #define SKIPFUNC       (1 << 2)
8976 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8977 static int skipcount;           /* number of levels to skip */
8978 static int loopnest;            /* current loop nesting level */
8979 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8980
8981 /* Forward decl way out to parsing code - dotrap needs it */
8982 static int evalstring(char *s, int flags);
8983
8984 /* Called to execute a trap.
8985  * Single callsite - at the end of evaltree().
8986  * If we return non-zero, evaltree raises EXEXIT exception.
8987  *
8988  * Perhaps we should avoid entering new trap handlers
8989  * while we are executing a trap handler. [is it a TODO?]
8990  */
8991 static void
8992 dotrap(void)
8993 {
8994         uint8_t *g;
8995         int sig;
8996         uint8_t last_status;
8997
8998         if (!pending_sig)
8999                 return;
9000
9001         last_status = exitstatus;
9002         pending_sig = 0;
9003         barrier();
9004
9005         TRACE(("dotrap entered\n"));
9006         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
9007                 char *p;
9008
9009                 if (!*g)
9010                         continue;
9011
9012                 if (evalskip) {
9013                         pending_sig = sig;
9014                         break;
9015                 }
9016
9017                 p = trap[sig];
9018                 /* non-trapped SIGINT is handled separately by raise_interrupt,
9019                  * don't upset it by resetting gotsig[SIGINT-1] */
9020                 if (sig == SIGINT && !p)
9021                         continue;
9022
9023                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
9024                 *g = 0;
9025                 if (!p)
9026                         continue;
9027                 evalstring(p, 0);
9028         }
9029         exitstatus = last_status;
9030         TRACE(("dotrap returns\n"));
9031 }
9032
9033 /* forward declarations - evaluation is fairly recursive business... */
9034 static int evalloop(union node *, int);
9035 static int evalfor(union node *, int);
9036 static int evalcase(union node *, int);
9037 static int evalsubshell(union node *, int);
9038 static void expredir(union node *);
9039 static int evalpipe(union node *, int);
9040 static int evalcommand(union node *, int);
9041 static int evalbltin(const struct builtincmd *, int, char **, int);
9042 static void prehash(union node *);
9043
9044 /*
9045  * Evaluate a parse tree.  The value is left in the global variable
9046  * exitstatus.
9047  */
9048 static int
9049 evaltree(union node *n, int flags)
9050 {
9051         int checkexit = 0;
9052         int (*evalfn)(union node *, int);
9053         int status = 0;
9054
9055         if (n == NULL) {
9056                 TRACE(("evaltree(NULL) called\n"));
9057                 goto out;
9058         }
9059         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
9060
9061         dotrap();
9062
9063         switch (n->type) {
9064         default:
9065 #if DEBUG
9066                 out1fmt("Node type = %d\n", n->type);
9067                 fflush_all();
9068                 break;
9069 #endif
9070         case NNOT:
9071                 status = !evaltree(n->nnot.com, EV_TESTED);
9072                 goto setstatus;
9073         case NREDIR:
9074                 errlinno = lineno = n->nredir.linno;
9075                 if (funcline)
9076                         lineno -= funcline - 1;
9077                 expredir(n->nredir.redirect);
9078                 pushredir(n->nredir.redirect);
9079                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9080                 if (!status) {
9081                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9082                 }
9083                 if (n->nredir.redirect)
9084                         popredir(/*drop:*/ 0);
9085                 goto setstatus;
9086         case NCMD:
9087                 evalfn = evalcommand;
9088  checkexit:
9089                 if (eflag && !(flags & EV_TESTED))
9090                         checkexit = ~0;
9091                 goto calleval;
9092         case NFOR:
9093                 evalfn = evalfor;
9094                 goto calleval;
9095         case NWHILE:
9096         case NUNTIL:
9097                 evalfn = evalloop;
9098                 goto calleval;
9099         case NSUBSHELL:
9100         case NBACKGND:
9101                 evalfn = evalsubshell;
9102                 goto checkexit;
9103         case NPIPE:
9104                 evalfn = evalpipe;
9105                 goto checkexit;
9106         case NCASE:
9107                 evalfn = evalcase;
9108                 goto calleval;
9109         case NAND:
9110         case NOR:
9111         case NSEMI: {
9112
9113 #if NAND + 1 != NOR
9114 #error NAND + 1 != NOR
9115 #endif
9116 #if NOR + 1 != NSEMI
9117 #error NOR + 1 != NSEMI
9118 #endif
9119                 unsigned is_or = n->type - NAND;
9120                 status = evaltree(
9121                         n->nbinary.ch1,
9122                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9123                 );
9124                 if ((!status) == is_or || evalskip)
9125                         break;
9126                 n = n->nbinary.ch2;
9127  evaln:
9128                 evalfn = evaltree;
9129  calleval:
9130                 status = evalfn(n, flags);
9131                 goto setstatus;
9132         }
9133         case NIF:
9134                 status = evaltree(n->nif.test, EV_TESTED);
9135                 if (evalskip)
9136                         break;
9137                 if (!status) {
9138                         n = n->nif.ifpart;
9139                         goto evaln;
9140                 }
9141                 if (n->nif.elsepart) {
9142                         n = n->nif.elsepart;
9143                         goto evaln;
9144                 }
9145                 status = 0;
9146                 goto setstatus;
9147         case NDEFUN:
9148                 defun(n);
9149                 /* Not necessary. To test it:
9150                  * "false; f() { qwerty; }; echo $?" should print 0.
9151                  */
9152                 /* status = 0; */
9153  setstatus:
9154                 exitstatus = status;
9155                 break;
9156         }
9157  out:
9158         /* Order of checks below is important:
9159          * signal handlers trigger before exit caused by "set -e".
9160          */
9161         dotrap();
9162
9163         if (checkexit & status)
9164                 raise_exception(EXEXIT);
9165         if (flags & EV_EXIT)
9166                 raise_exception(EXEXIT);
9167
9168         TRACE(("leaving evaltree (no interrupts)\n"));
9169         return exitstatus;
9170 }
9171
9172 static int
9173 skiploop(void)
9174 {
9175         int skip = evalskip;
9176
9177         switch (skip) {
9178         case 0:
9179                 break;
9180         case SKIPBREAK:
9181         case SKIPCONT:
9182                 if (--skipcount <= 0) {
9183                         evalskip = 0;
9184                         break;
9185                 }
9186                 skip = SKIPBREAK;
9187                 break;
9188         }
9189         return skip;
9190 }
9191
9192 static int
9193 evalloop(union node *n, int flags)
9194 {
9195         int skip;
9196         int status;
9197
9198         loopnest++;
9199         status = 0;
9200         flags &= EV_TESTED;
9201         do {
9202                 int i;
9203
9204                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9205                 skip = skiploop();
9206                 if (skip == SKIPFUNC)
9207                         status = i;
9208                 if (skip)
9209                         continue;
9210                 if (n->type != NWHILE)
9211                         i = !i;
9212                 if (i != 0)
9213                         break;
9214                 status = evaltree(n->nbinary.ch2, flags);
9215                 skip = skiploop();
9216         } while (!(skip & ~SKIPCONT));
9217         loopnest--;
9218
9219         return status;
9220 }
9221
9222 static int
9223 evalfor(union node *n, int flags)
9224 {
9225         struct arglist arglist;
9226         union node *argp;
9227         struct strlist *sp;
9228         struct stackmark smark;
9229         int status = 0;
9230
9231         errlinno = lineno = n->ncase.linno;
9232         if (funcline)
9233                 lineno -= funcline - 1;
9234
9235         setstackmark(&smark);
9236         arglist.list = NULL;
9237         arglist.lastp = &arglist.list;
9238         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9239                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9240         }
9241         *arglist.lastp = NULL;
9242
9243         loopnest++;
9244         flags &= EV_TESTED;
9245         for (sp = arglist.list; sp; sp = sp->next) {
9246                 setvar0(n->nfor.var, sp->text);
9247                 status = evaltree(n->nfor.body, flags);
9248                 if (skiploop() & ~SKIPCONT)
9249                         break;
9250         }
9251         loopnest--;
9252         popstackmark(&smark);
9253
9254         return status;
9255 }
9256
9257 static int
9258 evalcase(union node *n, int flags)
9259 {
9260         union node *cp;
9261         union node *patp;
9262         struct arglist arglist;
9263         struct stackmark smark;
9264         int status = 0;
9265
9266         errlinno = lineno = n->ncase.linno;
9267         if (funcline)
9268                 lineno -= funcline - 1;
9269
9270         setstackmark(&smark);
9271         arglist.list = NULL;
9272         arglist.lastp = &arglist.list;
9273         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9274         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9275                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9276                         if (casematch(patp, arglist.list->text)) {
9277                                 /* Ensure body is non-empty as otherwise
9278                                  * EV_EXIT may prevent us from setting the
9279                                  * exit status.
9280                                  */
9281                                 if (evalskip == 0 && cp->nclist.body) {
9282                                         status = evaltree(cp->nclist.body, flags);
9283                                 }
9284                                 goto out;
9285                         }
9286                 }
9287         }
9288  out:
9289         popstackmark(&smark);
9290
9291         return status;
9292 }
9293
9294 /*
9295  * Kick off a subshell to evaluate a tree.
9296  */
9297 static int
9298 evalsubshell(union node *n, int flags)
9299 {
9300         struct job *jp;
9301         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9302         int status;
9303
9304         errlinno = lineno = n->nredir.linno;
9305         if (funcline)
9306                 lineno -= funcline - 1;
9307
9308         expredir(n->nredir.redirect);
9309         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9310                 goto nofork;
9311         INT_OFF;
9312         if (backgnd == FORK_FG)
9313                 get_tty_state();
9314         jp = makejob(/*n,*/ 1);
9315         if (forkshell(jp, n, backgnd) == 0) {
9316                 /* child */
9317                 INT_ON;
9318                 flags |= EV_EXIT;
9319                 if (backgnd)
9320                         flags &= ~EV_TESTED;
9321  nofork:
9322                 redirect(n->nredir.redirect, 0);
9323                 evaltreenr(n->nredir.n, flags);
9324                 /* never returns */
9325         }
9326         /* parent */
9327         status = 0;
9328         if (backgnd == FORK_FG)
9329                 status = waitforjob(jp);
9330         INT_ON;
9331         return status;
9332 }
9333
9334 /*
9335  * Compute the names of the files in a redirection list.
9336  */
9337 static void fixredir(union node *, const char *, int);
9338 static void
9339 expredir(union node *n)
9340 {
9341         union node *redir;
9342
9343         for (redir = n; redir; redir = redir->nfile.next) {
9344                 struct arglist fn;
9345
9346                 fn.list = NULL;
9347                 fn.lastp = &fn.list;
9348                 switch (redir->type) {
9349                 case NFROMTO:
9350                 case NFROM:
9351                 case NTO:
9352 #if BASH_REDIR_OUTPUT
9353                 case NTO2:
9354 #endif
9355                 case NCLOBBER:
9356                 case NAPPEND:
9357                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9358                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9359 #if BASH_REDIR_OUTPUT
9360  store_expfname:
9361 #endif
9362 #if 0
9363 // By the design of stack allocator, the loop of this kind:
9364 //      while true; do while true; do break; done </dev/null; done
9365 // will look like a memory leak: ash plans to free expfname's
9366 // of "/dev/null" as soon as it finishes running the loop
9367 // (in this case, never).
9368 // This "fix" is wrong:
9369                         if (redir->nfile.expfname)
9370                                 stunalloc(redir->nfile.expfname);
9371 // It results in corrupted state of stacked allocations.
9372 #endif
9373                         redir->nfile.expfname = fn.list->text;
9374                         break;
9375                 case NFROMFD:
9376                 case NTOFD: /* >& */
9377                         if (redir->ndup.vname) {
9378                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9379                                 if (fn.list == NULL)
9380                                         ash_msg_and_raise_error("redir error");
9381 #if BASH_REDIR_OUTPUT
9382 //FIXME: we used expandarg with different args!
9383                                 if (!isdigit_str9(fn.list->text)) {
9384                                         /* >&file, not >&fd */
9385                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9386                                                 ash_msg_and_raise_error("redir error");
9387                                         redir->type = NTO2;
9388                                         goto store_expfname;
9389                                 }
9390 #endif
9391                                 fixredir(redir, fn.list->text, 1);
9392                         }
9393                         break;
9394                 }
9395         }
9396 }
9397
9398 /*
9399  * Evaluate a pipeline.  All the processes in the pipeline are children
9400  * of the process creating the pipeline.  (This differs from some versions
9401  * of the shell, which make the last process in a pipeline the parent
9402  * of all the rest.)
9403  */
9404 static int
9405 evalpipe(union node *n, int flags)
9406 {
9407         struct job *jp;
9408         struct nodelist *lp;
9409         int pipelen;
9410         int prevfd;
9411         int pip[2];
9412         int status = 0;
9413
9414         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9415         pipelen = 0;
9416         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9417                 pipelen++;
9418         flags |= EV_EXIT;
9419         INT_OFF;
9420         if (n->npipe.pipe_backgnd == 0)
9421                 get_tty_state();
9422         jp = makejob(/*n,*/ pipelen);
9423         prevfd = -1;
9424         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9425                 prehash(lp->n);
9426                 pip[1] = -1;
9427                 if (lp->next) {
9428                         if (pipe(pip) < 0) {
9429                                 close(prevfd);
9430                                 ash_msg_and_raise_perror("can't create pipe");
9431                         }
9432                 }
9433                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9434                         /* child */
9435                         INT_ON;
9436                         if (pip[1] >= 0) {
9437                                 close(pip[0]);
9438                         }
9439                         if (prevfd > 0) {
9440                                 dup2(prevfd, 0);
9441                                 close(prevfd);
9442                         }
9443                         if (pip[1] > 1) {
9444                                 dup2(pip[1], 1);
9445                                 close(pip[1]);
9446                         }
9447                         evaltreenr(lp->n, flags);
9448                         /* never returns */
9449                 }
9450                 /* parent */
9451                 if (prevfd >= 0)
9452                         close(prevfd);
9453                 prevfd = pip[0];
9454                 /* Don't want to trigger debugging */
9455                 if (pip[1] != -1)
9456                         close(pip[1]);
9457         }
9458         if (n->npipe.pipe_backgnd == 0) {
9459                 status = waitforjob(jp);
9460                 TRACE(("evalpipe:  job done exit status %d\n", status));
9461         }
9462         INT_ON;
9463
9464         return status;
9465 }
9466
9467 /*
9468  * Controls whether the shell is interactive or not.
9469  */
9470 static void
9471 setinteractive(int on)
9472 {
9473         static smallint is_interactive;
9474
9475         if (++on == is_interactive)
9476                 return;
9477         is_interactive = on;
9478         setsignal(SIGINT);
9479         setsignal(SIGQUIT);
9480         setsignal(SIGTERM);
9481 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9482         if (is_interactive > 1) {
9483                 /* Looks like they want an interactive shell */
9484                 static smallint did_banner;
9485
9486                 if (!did_banner) {
9487                         /* note: ash and hush share this string */
9488                         out1fmt("\n\n%s %s\n"
9489                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9490                                 "\n",
9491                                 bb_banner,
9492                                 "built-in shell (ash)"
9493                         );
9494                         did_banner = 1;
9495                 }
9496         }
9497 #endif
9498 }
9499
9500 static void
9501 optschanged(void)
9502 {
9503 #if DEBUG
9504         opentrace();
9505 #endif
9506         setinteractive(iflag);
9507         setjobctl(mflag);
9508 #if ENABLE_FEATURE_EDITING_VI
9509         if (viflag)
9510                 line_input_state->flags |= VI_MODE;
9511         else
9512                 line_input_state->flags &= ~VI_MODE;
9513 #else
9514         viflag = 0; /* forcibly keep the option off */
9515 #endif
9516 }
9517
9518 struct localvar_list {
9519         struct localvar_list *next;
9520         struct localvar *lv;
9521 };
9522
9523 static struct localvar_list *localvar_stack;
9524
9525 /*
9526  * Called after a function returns.
9527  * Interrupts must be off.
9528  */
9529 static void
9530 poplocalvars(int keep)
9531 {
9532         struct localvar_list *ll;
9533         struct localvar *lvp, *next;
9534         struct var *vp;
9535
9536         INT_OFF;
9537         ll = localvar_stack;
9538         localvar_stack = ll->next;
9539
9540         next = ll->lv;
9541         free(ll);
9542
9543         while ((lvp = next) != NULL) {
9544                 next = lvp->next;
9545                 vp = lvp->vp;
9546                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9547                 if (keep) {
9548                         int bits = VSTRFIXED;
9549
9550                         if (lvp->flags != VUNSET) {
9551                                 if (vp->var_text == lvp->text)
9552                                         bits |= VTEXTFIXED;
9553                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9554                                         free((char*)lvp->text);
9555                         }
9556
9557                         vp->flags &= ~bits;
9558                         vp->flags |= (lvp->flags & bits);
9559
9560                         if ((vp->flags &
9561                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9562                                 unsetvar(vp->var_text);
9563                 } else if (vp == NULL) {        /* $- saved */
9564                         memcpy(optlist, lvp->text, sizeof(optlist));
9565                         free((char*)lvp->text);
9566                         optschanged();
9567                 } else if (lvp->flags == VUNSET) {
9568                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9569                         unsetvar(vp->var_text);
9570                 } else {
9571                         if (vp->var_func)
9572                                 vp->var_func(var_end(lvp->text));
9573                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9574                                 free((char*)vp->var_text);
9575                         vp->flags = lvp->flags;
9576                         vp->var_text = lvp->text;
9577                 }
9578                 free(lvp);
9579         }
9580         INT_ON;
9581 }
9582
9583 /*
9584  * Create a new localvar environment.
9585  */
9586 static struct localvar_list *
9587 pushlocalvars(void)
9588 {
9589         struct localvar_list *ll;
9590
9591         INT_OFF;
9592         ll = ckzalloc(sizeof(*ll));
9593         /*ll->lv = NULL; - zalloc did it */
9594         ll->next = localvar_stack;
9595         localvar_stack = ll;
9596         INT_ON;
9597
9598         return ll->next;
9599 }
9600
9601 static void
9602 unwindlocalvars(struct localvar_list *stop)
9603 {
9604         while (localvar_stack != stop)
9605                 poplocalvars(0);
9606 }
9607
9608 static int
9609 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9610 {
9611         volatile struct shparam saveparam;
9612         struct jmploc *volatile savehandler;
9613         struct jmploc jmploc;
9614         int e;
9615         int savefuncline;
9616
9617         saveparam = shellparam;
9618         savefuncline = funcline;
9619         savehandler = exception_handler;
9620         e = setjmp(jmploc.loc);
9621         if (e) {
9622                 goto funcdone;
9623         }
9624         INT_OFF;
9625         exception_handler = &jmploc;
9626         shellparam.malloced = 0;
9627         func->count++;
9628         funcline = func->n.ndefun.linno;
9629         INT_ON;
9630         shellparam.nparam = argc - 1;
9631         shellparam.p = argv + 1;
9632 #if ENABLE_ASH_GETOPTS
9633         shellparam.optind = 1;
9634         shellparam.optoff = -1;
9635 #endif
9636         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9637  funcdone:
9638         INT_OFF;
9639         funcline = savefuncline;
9640         freefunc(func);
9641         freeparam(&shellparam);
9642         shellparam = saveparam;
9643         exception_handler = savehandler;
9644         INT_ON;
9645         evalskip &= ~SKIPFUNC;
9646         return e;
9647 }
9648
9649 /*
9650  * Make a variable a local variable.  When a variable is made local, it's
9651  * value and flags are saved in a localvar structure.  The saved values
9652  * will be restored when the shell function returns.  We handle the name
9653  * "-" as a special case: it makes changes to "set +-options" local
9654  * (options will be restored on return from the function).
9655  */
9656 static void
9657 mklocal(char *name)
9658 {
9659         struct localvar *lvp;
9660         struct var **vpp;
9661         struct var *vp;
9662         char *eq = strchr(name, '=');
9663
9664         INT_OFF;
9665         /* Cater for duplicate "local". Examples:
9666          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9667          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9668          */
9669         lvp = localvar_stack->lv;
9670         while (lvp) {
9671                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9672                         if (eq)
9673                                 setvareq(name, 0);
9674                         /* else:
9675                          * it's a duplicate "local VAR" declaration, do nothing
9676                          */
9677                         goto ret;
9678                 }
9679                 lvp = lvp->next;
9680         }
9681
9682         lvp = ckzalloc(sizeof(*lvp));
9683         if (LONE_DASH(name)) {
9684                 char *p;
9685                 p = ckmalloc(sizeof(optlist));
9686                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9687                 vp = NULL;
9688         } else {
9689                 vpp = hashvar(name);
9690                 vp = *findvar(vpp, name);
9691                 if (vp == NULL) {
9692                         /* variable did not exist yet */
9693                         if (eq)
9694                                 vp = setvareq(name, VSTRFIXED);
9695                         else
9696                                 vp = setvar(name, NULL, VSTRFIXED);
9697                         lvp->flags = VUNSET;
9698                 } else {
9699                         lvp->text = vp->var_text;
9700                         lvp->flags = vp->flags;
9701                         /* make sure neither "struct var" nor string gets freed
9702                          * during (un)setting:
9703                          */
9704                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9705                         if (eq)
9706                                 setvareq(name, 0);
9707                         else
9708                                 /* "local VAR" unsets VAR: */
9709                                 setvar0(name, NULL);
9710                 }
9711         }
9712         lvp->vp = vp;
9713         lvp->next = localvar_stack->lv;
9714         localvar_stack->lv = lvp;
9715  ret:
9716         INT_ON;
9717 }
9718
9719 /*
9720  * The "local" command.
9721  */
9722 static int FAST_FUNC
9723 localcmd(int argc UNUSED_PARAM, char **argv)
9724 {
9725         char *name;
9726
9727         if (!localvar_stack)
9728                 ash_msg_and_raise_error("not in a function");
9729
9730         argv = argptr;
9731         while ((name = *argv++) != NULL) {
9732                 mklocal(name);
9733         }
9734         return 0;
9735 }
9736
9737 static int FAST_FUNC
9738 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9739 {
9740         return 1;
9741 }
9742
9743 static int FAST_FUNC
9744 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9745 {
9746         return 0;
9747 }
9748
9749 static int FAST_FUNC
9750 execcmd(int argc UNUSED_PARAM, char **argv)
9751 {
9752         optionarg = NULL;
9753         while (nextopt("a:") != '\0')
9754                 /* nextopt() sets optionarg to "-a ARGV0" */;
9755
9756         argv = argptr;
9757         if (argv[0]) {
9758                 char *prog;
9759
9760                 iflag = 0;              /* exit on error */
9761                 mflag = 0;
9762                 optschanged();
9763                 /* We should set up signals for "exec CMD"
9764                  * the same way as for "CMD" without "exec".
9765                  * But optschanged->setinteractive->setsignal
9766                  * still thought we are a root shell. Therefore, for example,
9767                  * SIGQUIT is still set to IGN. Fix it:
9768                  */
9769                 shlvl++;
9770                 setsignal(SIGQUIT);
9771                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9772                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9773                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9774
9775                 prog = argv[0];
9776                 if (optionarg)
9777                         argv[0] = optionarg;
9778                 shellexec(prog, argv, pathval(), 0);
9779                 /* NOTREACHED */
9780         }
9781         return 0;
9782 }
9783
9784 /*
9785  * The return command.
9786  */
9787 static int FAST_FUNC
9788 returncmd(int argc UNUSED_PARAM, char **argv)
9789 {
9790         /*
9791          * If called outside a function, do what ksh does;
9792          * skip the rest of the file.
9793          */
9794         evalskip = SKIPFUNC;
9795         return argv[1] ? number(argv[1]) : exitstatus;
9796 }
9797
9798 /* Forward declarations for builtintab[] */
9799 static int breakcmd(int, char **) FAST_FUNC;
9800 static int dotcmd(int, char **) FAST_FUNC;
9801 static int evalcmd(int, char **, int) FAST_FUNC;
9802 static int exitcmd(int, char **) FAST_FUNC;
9803 static int exportcmd(int, char **) FAST_FUNC;
9804 #if ENABLE_ASH_GETOPTS
9805 static int getoptscmd(int, char **) FAST_FUNC;
9806 #endif
9807 #if ENABLE_ASH_HELP
9808 static int helpcmd(int, char **) FAST_FUNC;
9809 #endif
9810 #if MAX_HISTORY
9811 static int historycmd(int, char **) FAST_FUNC;
9812 #endif
9813 #if ENABLE_FEATURE_SH_MATH
9814 static int letcmd(int, char **) FAST_FUNC;
9815 #endif
9816 static int readcmd(int, char **) FAST_FUNC;
9817 static int setcmd(int, char **) FAST_FUNC;
9818 static int shiftcmd(int, char **) FAST_FUNC;
9819 static int timescmd(int, char **) FAST_FUNC;
9820 static int trapcmd(int, char **) FAST_FUNC;
9821 static int umaskcmd(int, char **) FAST_FUNC;
9822 static int unsetcmd(int, char **) FAST_FUNC;
9823 static int ulimitcmd(int, char **) FAST_FUNC;
9824
9825 #define BUILTIN_NOSPEC          "0"
9826 #define BUILTIN_SPECIAL         "1"
9827 #define BUILTIN_REGULAR         "2"
9828 #define BUILTIN_SPEC_REG        "3"
9829 #define BUILTIN_ASSIGN          "4"
9830 #define BUILTIN_SPEC_ASSG       "5"
9831 #define BUILTIN_REG_ASSG        "6"
9832 #define BUILTIN_SPEC_REG_ASSG   "7"
9833
9834 /* Stubs for calling non-FAST_FUNC's */
9835 #if ENABLE_ASH_ECHO
9836 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9837 #endif
9838 #if ENABLE_ASH_PRINTF
9839 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9840 #endif
9841 #if ENABLE_ASH_TEST || BASH_TEST2
9842 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9843 #endif
9844
9845 /* Keep these in proper order since it is searched via bsearch() */
9846 static const struct builtincmd builtintab[] = {
9847         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9848         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9849 #if ENABLE_ASH_TEST
9850         { BUILTIN_REGULAR       "["       , testcmd    },
9851 #endif
9852 #if BASH_TEST2
9853         { BUILTIN_REGULAR       "[["      , testcmd    },
9854 #endif
9855 #if ENABLE_ASH_ALIAS
9856         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9857 #endif
9858 #if JOBS
9859         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9860 #endif
9861         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9862         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9863         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9864 #if ENABLE_ASH_CMDCMD
9865         { BUILTIN_REGULAR       "command" , commandcmd },
9866 #endif
9867         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9868 #if ENABLE_ASH_ECHO
9869         { BUILTIN_REGULAR       "echo"    , echocmd    },
9870 #endif
9871         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9872         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9873         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9874         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9875         { BUILTIN_REGULAR       "false"   , falsecmd   },
9876 #if JOBS
9877         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9878 #endif
9879 #if ENABLE_ASH_GETOPTS
9880         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9881 #endif
9882         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9883 #if ENABLE_ASH_HELP
9884         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9885 #endif
9886 #if MAX_HISTORY
9887         { BUILTIN_NOSPEC        "history" , historycmd },
9888 #endif
9889 #if JOBS
9890         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9891         { BUILTIN_REGULAR       "kill"    , killcmd    },
9892 #endif
9893 #if ENABLE_FEATURE_SH_MATH
9894         { BUILTIN_NOSPEC        "let"     , letcmd     },
9895 #endif
9896         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9897 #if ENABLE_ASH_PRINTF
9898         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9899 #endif
9900         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9901         { BUILTIN_REGULAR       "read"    , readcmd    },
9902         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9903         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9904         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9905         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9906 #if BASH_SOURCE
9907         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9908 #endif
9909 #if ENABLE_ASH_TEST
9910         { BUILTIN_REGULAR       "test"    , testcmd    },
9911 #endif
9912         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9913         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9914         { BUILTIN_REGULAR       "true"    , truecmd    },
9915         { BUILTIN_NOSPEC        "type"    , typecmd    },
9916         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9917         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9918 #if ENABLE_ASH_ALIAS
9919         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9920 #endif
9921         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9922         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9923 };
9924
9925 /* Should match the above table! */
9926 #define COMMANDCMD (builtintab + \
9927         /* . : */       2 + \
9928         /* [ */         1 * ENABLE_ASH_TEST + \
9929         /* [[ */        1 * BASH_TEST2 + \
9930         /* alias */     1 * ENABLE_ASH_ALIAS + \
9931         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9932         /* break cd cddir  */   3)
9933 #define EVALCMD (COMMANDCMD + \
9934         /* command */   1 * ENABLE_ASH_CMDCMD + \
9935         /* continue */  1 + \
9936         /* echo */      1 * ENABLE_ASH_ECHO + \
9937         0)
9938 #define EXECCMD (EVALCMD + \
9939         /* eval */      1)
9940
9941 /*
9942  * Search the table of builtin commands.
9943  */
9944 static int
9945 pstrcmp1(const void *a, const void *b)
9946 {
9947         return strcmp((char*)a, *(char**)b + 1);
9948 }
9949 static struct builtincmd *
9950 find_builtin(const char *name)
9951 {
9952         struct builtincmd *bp;
9953
9954         bp = bsearch(
9955                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9956                 pstrcmp1
9957         );
9958         return bp;
9959 }
9960
9961 /*
9962  * Execute a simple command.
9963  */
9964 static void unwindfiles(struct parsefile *stop);
9965 static int
9966 isassignment(const char *p)
9967 {
9968         const char *q = endofname(p);
9969         if (p == q)
9970                 return 0;
9971         return *q == '=';
9972 }
9973 static int FAST_FUNC
9974 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9975 {
9976         /* Preserve exitstatus of a previous possible redirection
9977          * as POSIX mandates */
9978         return back_exitstatus;
9979 }
9980 static int
9981 evalcommand(union node *cmd, int flags)
9982 {
9983         static const struct builtincmd null_bltin = {
9984                 "\0\0", bltincmd /* why three NULs? */
9985         };
9986         struct localvar_list *localvar_stop;
9987         struct parsefile *file_stop;
9988         struct redirtab *redir_stop;
9989         struct stackmark smark;
9990         union node *argp;
9991         struct arglist arglist;
9992         struct arglist varlist;
9993         char **argv;
9994         int argc;
9995         const struct strlist *sp;
9996         struct cmdentry cmdentry;
9997         struct job *jp;
9998         char *lastarg;
9999         const char *path;
10000         int spclbltin;
10001         int status;
10002         char **nargv;
10003         smallint cmd_is_exec;
10004
10005         errlinno = lineno = cmd->ncmd.linno;
10006         if (funcline)
10007                 lineno -= funcline - 1;
10008
10009         /* First expand the arguments. */
10010         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
10011         setstackmark(&smark);
10012         localvar_stop = pushlocalvars();
10013         file_stop = g_parsefile;
10014         back_exitstatus = 0;
10015
10016         cmdentry.cmdtype = CMDBUILTIN;
10017         cmdentry.u.cmd = &null_bltin;
10018         varlist.lastp = &varlist.list;
10019         *varlist.lastp = NULL;
10020         arglist.lastp = &arglist.list;
10021         *arglist.lastp = NULL;
10022
10023         argc = 0;
10024         if (cmd->ncmd.args) {
10025                 struct builtincmd *bcmd;
10026                 smallint pseudovarflag;
10027
10028                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
10029                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
10030
10031                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
10032                         struct strlist **spp;
10033
10034                         spp = arglist.lastp;
10035                         if (pseudovarflag && isassignment(argp->narg.text))
10036                                 expandarg(argp, &arglist, EXP_VARTILDE);
10037                         else
10038                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
10039
10040                         for (sp = *spp; sp; sp = sp->next)
10041                                 argc++;
10042                 }
10043         }
10044
10045         /* Reserve one extra spot at the front for shellexec. */
10046         nargv = stalloc(sizeof(char *) * (argc + 2));
10047         argv = ++nargv;
10048         for (sp = arglist.list; sp; sp = sp->next) {
10049                 TRACE(("evalcommand arg: %s\n", sp->text));
10050                 *nargv++ = sp->text;
10051         }
10052         *nargv = NULL;
10053
10054         lastarg = NULL;
10055         if (iflag && funcline == 0 && argc > 0)
10056                 lastarg = nargv[-1];
10057
10058         expredir(cmd->ncmd.redirect);
10059         redir_stop = pushredir(cmd->ncmd.redirect);
10060         preverrout_fd = 2;
10061         if (BASH_XTRACEFD && xflag) {
10062                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10063                  * we do not emulate this. We only use its value.
10064                  */
10065                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
10066                 if (xtracefd && is_number(xtracefd))
10067                         preverrout_fd = atoi(xtracefd);
10068
10069         }
10070         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10071
10072         path = vpath.var_text;
10073         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10074                 struct strlist **spp;
10075                 char *p;
10076
10077                 spp = varlist.lastp;
10078                 expandarg(argp, &varlist, EXP_VARTILDE);
10079
10080                 mklocal((*spp)->text);
10081
10082                 /*
10083                  * Modify the command lookup path, if a PATH= assignment
10084                  * is present
10085                  */
10086                 p = (*spp)->text;
10087                 if (varcmp(p, path) == 0)
10088                         path = p;
10089         }
10090
10091         /* Print the command if xflag is set. */
10092         if (xflag) {
10093                 const char *pfx = "";
10094
10095                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10096
10097                 sp = varlist.list;
10098                 while (sp) {
10099                         char *varval = sp->text;
10100                         char *eq = strchrnul(varval, '=');
10101                         if (*eq)
10102                                 eq++;
10103                         fdprintf(preverrout_fd, "%s%.*s%s",
10104                                 pfx,
10105                                 (int)(eq - varval), varval,
10106                                 maybe_single_quote(eq)
10107                         );
10108                         sp = sp->next;
10109                         pfx = " ";
10110                 }
10111
10112                 sp = arglist.list;
10113                 while (sp) {
10114                         fdprintf(preverrout_fd, "%s%s",
10115                                 pfx,
10116                                 /* always quote if matches reserved word: */
10117                                 findkwd(sp->text)
10118                                 ? single_quote(sp->text)
10119                                 : maybe_single_quote(sp->text)
10120                         );
10121                         sp = sp->next;
10122                         pfx = " ";
10123                 }
10124                 safe_write(preverrout_fd, "\n", 1);
10125         }
10126
10127         cmd_is_exec = 0;
10128         spclbltin = -1;
10129
10130         /* Now locate the command. */
10131         if (argc) {
10132                 int cmd_flag = DO_ERR;
10133 #if ENABLE_ASH_CMDCMD
10134                 const char *oldpath = path + 5;
10135 #endif
10136                 path += 5;
10137                 for (;;) {
10138                         find_command(argv[0], &cmdentry, cmd_flag, path);
10139                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10140                                 flush_stdout_stderr();
10141                                 status = 127;
10142                                 goto bail;
10143                         }
10144
10145                         /* implement bltin and command here */
10146                         if (cmdentry.cmdtype != CMDBUILTIN)
10147                                 break;
10148                         if (spclbltin < 0)
10149                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10150                         if (cmdentry.u.cmd == EXECCMD)
10151                                 cmd_is_exec = 1;
10152 #if ENABLE_ASH_CMDCMD
10153                         if (cmdentry.u.cmd == COMMANDCMD) {
10154                                 path = oldpath;
10155                                 nargv = parse_command_args(argv, &path);
10156                                 if (!nargv)
10157                                         break;
10158                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10159                                  * nargv => "PROG". path is updated if -p.
10160                                  */
10161                                 argc -= nargv - argv;
10162                                 argv = nargv;
10163                                 cmd_flag |= DO_NOFUNC;
10164                         } else
10165 #endif
10166                                 break;
10167                 }
10168         }
10169
10170         if (status) {
10171  bail:
10172                 exitstatus = status;
10173
10174                 /* We have a redirection error. */
10175                 if (spclbltin > 0)
10176                         raise_exception(EXERROR);
10177
10178                 goto out;
10179         }
10180
10181         /* Execute the command. */
10182         switch (cmdentry.cmdtype) {
10183         default: {
10184
10185 #if ENABLE_FEATURE_SH_STANDALONE \
10186  && ENABLE_FEATURE_SH_NOFORK \
10187  && NUM_APPLETS > 1
10188 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10189  *     around run_nofork_applet() call.
10190  * (2) Should this check also be done in forkshell()?
10191  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10192  */
10193                 /* find_command() encodes applet_no as (-2 - applet_no) */
10194                 int applet_no = (- cmdentry.u.index - 2);
10195 # if NUM_SCRIPTS > 0
10196                 /* Applets are ok, but not embedded scripts */
10197                 if (applet_no < NUM_APPLETS)
10198 # endif
10199                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10200                         char **sv_environ;
10201
10202                         INT_OFF;
10203                         sv_environ = environ;
10204                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10205                         /*
10206                          * Run <applet>_main().
10207                          * Signals (^C) can't interrupt here.
10208                          * Otherwise we can mangle stdio or malloc internal state.
10209                          * This makes applets which can run for a long time
10210                          * and/or wait for user input ineligible for NOFORK:
10211                          * for example, "yes" or "rm" (rm -i waits for input).
10212                          */
10213                         status = run_nofork_applet(applet_no, argv);
10214                         environ = sv_environ;
10215                         /*
10216                          * Try enabling NOFORK for "yes" applet.
10217                          * ^C _will_ stop it (write returns EINTR),
10218                          * but this causes stdout FILE to be stuck
10219                          * and needing clearerr(). What if other applets
10220                          * also can get EINTRs? Do we need to switch
10221                          * our signals to SA_RESTART?
10222                          */
10223                         /*clearerr(stdout);*/
10224                         INT_ON;
10225                         break;
10226                 }
10227 #endif
10228                 /* Can we avoid forking? For example, very last command
10229                  * in a script or a subshell does not need forking,
10230                  * we can just exec it.
10231                  */
10232                 if (!(flags & EV_EXIT) || may_have_traps) {
10233                         /* No, forking off a child is necessary */
10234                         INT_OFF;
10235                         get_tty_state();
10236                         jp = makejob(/*cmd,*/ 1);
10237                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10238                                 /* parent */
10239                                 status = waitforjob(jp);
10240                                 INT_ON;
10241                                 TRACE(("forked child exited with %d\n", status));
10242                                 break;
10243                         }
10244                         /* child */
10245                         FORCE_INT_ON;
10246                         /* fall through to exec'ing external program */
10247                 }
10248                 listsetvar(varlist.list, VEXPORT|VSTACK);
10249                 shellexec(argv[0], argv, path, cmdentry.u.index);
10250                 /* NOTREACHED */
10251         } /* default */
10252         case CMDBUILTIN:
10253                 if (spclbltin > 0 || argc == 0) {
10254                         poplocalvars(1);
10255                         if (cmd_is_exec && argc > 1)
10256                                 listsetvar(varlist.list, VEXPORT);
10257                 }
10258
10259                 /* Tight loop with builtins only:
10260                  * "while kill -0 $child; do true; done"
10261                  * will never exit even if $child died, unless we do this
10262                  * to reap the zombie and make kill detect that it's gone: */
10263                 dowait(DOWAIT_NONBLOCK, NULL);
10264
10265                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10266                         if (exception_type == EXERROR && spclbltin <= 0) {
10267                                 FORCE_INT_ON;
10268                                 goto readstatus;
10269                         }
10270  raise:
10271                         longjmp(exception_handler->loc, 1);
10272                 }
10273                 goto readstatus;
10274
10275         case CMDFUNCTION:
10276                 /* See above for the rationale */
10277                 dowait(DOWAIT_NONBLOCK, NULL);
10278                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10279                         goto raise;
10280  readstatus:
10281                 status = exitstatus;
10282                 break;
10283         } /* switch */
10284
10285  out:
10286         if (cmd->ncmd.redirect)
10287                 popredir(/*drop:*/ cmd_is_exec);
10288         unwindredir(redir_stop);
10289         unwindfiles(file_stop);
10290         unwindlocalvars(localvar_stop);
10291         if (lastarg) {
10292                 /* dsl: I think this is intended to be used to support
10293                  * '_' in 'vi' command mode during line editing...
10294                  * However I implemented that within libedit itself.
10295                  */
10296                 setvar0("_", lastarg);
10297         }
10298         popstackmark(&smark);
10299
10300         return status;
10301 }
10302
10303 static int
10304 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10305 {
10306         char *volatile savecmdname;
10307         struct jmploc *volatile savehandler;
10308         struct jmploc jmploc;
10309         int status;
10310         int i;
10311
10312         savecmdname = commandname;
10313         savehandler = exception_handler;
10314         i = setjmp(jmploc.loc);
10315         if (i)
10316                 goto cmddone;
10317         exception_handler = &jmploc;
10318         commandname = argv[0];
10319         argptr = argv + 1;
10320         optptr = NULL;                  /* initialize nextopt */
10321         if (cmd == EVALCMD)
10322                 status = evalcmd(argc, argv, flags);
10323         else
10324                 status = (*cmd->builtin)(argc, argv);
10325         flush_stdout_stderr();
10326         status |= ferror(stdout);
10327         exitstatus = status;
10328  cmddone:
10329         clearerr(stdout);
10330         commandname = savecmdname;
10331         exception_handler = savehandler;
10332
10333         return i;
10334 }
10335
10336 static int
10337 goodname(const char *p)
10338 {
10339         return endofname(p)[0] == '\0';
10340 }
10341
10342
10343 /*
10344  * Search for a command.  This is called before we fork so that the
10345  * location of the command will be available in the parent as well as
10346  * the child.  The check for "goodname" is an overly conservative
10347  * check that the name will not be subject to expansion.
10348  */
10349 static void
10350 prehash(union node *n)
10351 {
10352         struct cmdentry entry;
10353
10354         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10355                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10356 }
10357
10358
10359 /* ============ Builtin commands
10360  *
10361  * Builtin commands whose functions are closely tied to evaluation
10362  * are implemented here.
10363  */
10364
10365 /*
10366  * Handle break and continue commands.  Break, continue, and return are
10367  * all handled by setting the evalskip flag.  The evaluation routines
10368  * above all check this flag, and if it is set they start skipping
10369  * commands rather than executing them.  The variable skipcount is
10370  * the number of loops to break/continue, or the number of function
10371  * levels to return.  (The latter is always 1.)  It should probably
10372  * be an error to break out of more loops than exist, but it isn't
10373  * in the standard shell so we don't make it one here.
10374  */
10375 static int FAST_FUNC
10376 breakcmd(int argc UNUSED_PARAM, char **argv)
10377 {
10378         int n = argv[1] ? number(argv[1]) : 1;
10379
10380         if (n <= 0)
10381                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10382         if (n > loopnest)
10383                 n = loopnest;
10384         if (n > 0) {
10385                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10386                 skipcount = n;
10387         }
10388         return 0;
10389 }
10390
10391
10392 /*
10393  * This implements the input routines used by the parser.
10394  */
10395
10396 enum {
10397         INPUT_PUSH_FILE = 1,
10398         INPUT_NOFILE_OK = 2,
10399 };
10400
10401 static smallint checkkwd;
10402 /* values of checkkwd variable */
10403 #define CHKALIAS        0x1
10404 #define CHKKWD          0x2
10405 #define CHKNL           0x4
10406 #define CHKEOFMARK      0x8
10407
10408 /*
10409  * Push a string back onto the input at this current parsefile level.
10410  * We handle aliases this way.
10411  */
10412 #if !ENABLE_ASH_ALIAS
10413 #define pushstring(s, ap) pushstring(s)
10414 #endif
10415 static void
10416 pushstring(char *s, struct alias *ap)
10417 {
10418         struct strpush *sp;
10419         int len;
10420
10421         len = strlen(s);
10422         INT_OFF;
10423         if (g_parsefile->strpush) {
10424                 sp = ckzalloc(sizeof(*sp));
10425                 sp->prev = g_parsefile->strpush;
10426         } else {
10427                 sp = &(g_parsefile->basestrpush);
10428         }
10429         g_parsefile->strpush = sp;
10430         sp->prev_string = g_parsefile->next_to_pgetc;
10431         sp->prev_left_in_line = g_parsefile->left_in_line;
10432         sp->unget = g_parsefile->unget;
10433         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10434 #if ENABLE_ASH_ALIAS
10435         sp->ap = ap;
10436         if (ap) {
10437                 ap->flag |= ALIASINUSE;
10438                 sp->string = s;
10439         }
10440 #endif
10441         g_parsefile->next_to_pgetc = s;
10442         g_parsefile->left_in_line = len;
10443         g_parsefile->unget = 0;
10444         INT_ON;
10445 }
10446
10447 static void
10448 popstring(void)
10449 {
10450         struct strpush *sp = g_parsefile->strpush;
10451
10452         INT_OFF;
10453 #if ENABLE_ASH_ALIAS
10454         if (sp->ap) {
10455                 if (g_parsefile->next_to_pgetc[-1] == ' '
10456                  || g_parsefile->next_to_pgetc[-1] == '\t'
10457                 ) {
10458                         checkkwd |= CHKALIAS;
10459                 }
10460                 if (sp->string != sp->ap->val) {
10461                         free(sp->string);
10462                 }
10463                 sp->ap->flag &= ~ALIASINUSE;
10464                 if (sp->ap->flag & ALIASDEAD) {
10465                         unalias(sp->ap->name);
10466                 }
10467         }
10468 #endif
10469         g_parsefile->next_to_pgetc = sp->prev_string;
10470         g_parsefile->left_in_line = sp->prev_left_in_line;
10471         g_parsefile->unget = sp->unget;
10472         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10473         g_parsefile->strpush = sp->prev;
10474         if (sp != &(g_parsefile->basestrpush))
10475                 free(sp);
10476         INT_ON;
10477 }
10478
10479 static int
10480 preadfd(void)
10481 {
10482         int nr;
10483         char *buf = g_parsefile->buf;
10484
10485         g_parsefile->next_to_pgetc = buf;
10486 #if ENABLE_FEATURE_EDITING
10487  retry:
10488         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10489                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10490         else {
10491 # if ENABLE_ASH_IDLE_TIMEOUT
10492                 int timeout = -1;
10493                 if (iflag) {
10494                         const char *tmout_var = lookupvar("TMOUT");
10495                         if (tmout_var) {
10496                                 timeout = atoi(tmout_var) * 1000;
10497                                 if (timeout <= 0)
10498                                         timeout = -1;
10499                         }
10500                 }
10501                 line_input_state->timeout = timeout;
10502 # endif
10503 # if ENABLE_FEATURE_TAB_COMPLETION
10504                 line_input_state->path_lookup = pathval();
10505 # endif
10506                 reinit_unicode_for_ash();
10507                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10508                 if (nr == 0) {
10509                         /* ^C pressed, "convert" to SIGINT */
10510                         write(STDOUT_FILENO, "^C", 2);
10511                         if (trap[SIGINT]) {
10512                                 buf[0] = '\n';
10513                                 buf[1] = '\0';
10514                                 raise(SIGINT);
10515                                 return 1;
10516                         }
10517                         exitstatus = 128 + SIGINT;
10518                         bb_putchar('\n');
10519                         goto retry;
10520                 }
10521                 if (nr < 0) {
10522                         if (errno == 0) {
10523                                 /* Ctrl+D pressed */
10524                                 nr = 0;
10525                         }
10526 # if ENABLE_ASH_IDLE_TIMEOUT
10527                         else if (errno == EAGAIN && timeout > 0) {
10528                                 puts("\007timed out waiting for input: auto-logout");
10529                                 exitshell();
10530                         }
10531 # endif
10532                 }
10533         }
10534 #else
10535         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10536 #endif
10537
10538 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10539         if (nr < 0) {
10540                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10541                         int flags = fcntl(0, F_GETFL);
10542                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10543                                 flags &= ~O_NONBLOCK;
10544                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10545                                         out2str("sh: turning off NDELAY mode\n");
10546                                         goto retry;
10547                                 }
10548                         }
10549                 }
10550         }
10551 #endif
10552         return nr;
10553 }
10554
10555 /*
10556  * Refill the input buffer and return the next input character:
10557  *
10558  * 1) If a string was pushed back on the input, pop it;
10559  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10560  *    or we are reading from a string so we can't refill the buffer,
10561  *    return EOF.
10562  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10563  * 4) Process input up to the next newline, deleting nul characters.
10564  */
10565 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10566 #define pgetc_debug(...) ((void)0)
10567 static int pgetc(void);
10568 static int
10569 preadbuffer(void)
10570 {
10571         char *q;
10572         int more;
10573
10574         if (g_parsefile->strpush) {
10575 #if ENABLE_ASH_ALIAS
10576                 if (g_parsefile->left_in_line == -1
10577                  && g_parsefile->strpush->ap
10578                  && g_parsefile->next_to_pgetc[-1] != ' '
10579                  && g_parsefile->next_to_pgetc[-1] != '\t'
10580                 ) {
10581                         pgetc_debug("preadbuffer PEOA");
10582                         return PEOA;
10583                 }
10584 #endif
10585                 popstring();
10586                 return pgetc();
10587         }
10588         /* on both branches above g_parsefile->left_in_line < 0.
10589          * "pgetc" needs refilling.
10590          */
10591
10592         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10593          * pungetc() may increment it a few times.
10594          * Assuming it won't increment it to less than -90.
10595          */
10596         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10597                 pgetc_debug("preadbuffer PEOF1");
10598                 /* even in failure keep left_in_line and next_to_pgetc
10599                  * in lock step, for correct multi-layer pungetc.
10600                  * left_in_line was decremented before preadbuffer(),
10601                  * must inc next_to_pgetc: */
10602                 g_parsefile->next_to_pgetc++;
10603                 return PEOF;
10604         }
10605
10606         more = g_parsefile->left_in_buffer;
10607         if (more <= 0) {
10608                 flush_stdout_stderr();
10609  again:
10610                 more = preadfd();
10611                 if (more <= 0) {
10612                         /* don't try reading again */
10613                         g_parsefile->left_in_line = -99;
10614                         pgetc_debug("preadbuffer PEOF2");
10615                         g_parsefile->next_to_pgetc++;
10616                         return PEOF;
10617                 }
10618         }
10619
10620         /* Find out where's the end of line.
10621          * Set g_parsefile->left_in_line
10622          * and g_parsefile->left_in_buffer acordingly.
10623          * NUL chars are deleted.
10624          */
10625         q = g_parsefile->next_to_pgetc;
10626         for (;;) {
10627                 char c;
10628
10629                 more--;
10630
10631                 c = *q;
10632                 if (c == '\0') {
10633                         memmove(q, q + 1, more);
10634                 } else {
10635                         q++;
10636                         if (c == '\n') {
10637                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10638                                 break;
10639                         }
10640                 }
10641
10642                 if (more <= 0) {
10643                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10644                         if (g_parsefile->left_in_line < 0)
10645                                 goto again;
10646                         break;
10647                 }
10648         }
10649         g_parsefile->left_in_buffer = more;
10650
10651         if (vflag) {
10652                 char save = *q;
10653                 *q = '\0';
10654                 out2str(g_parsefile->next_to_pgetc);
10655                 *q = save;
10656         }
10657
10658         pgetc_debug("preadbuffer at %d:%p'%s'",
10659                         g_parsefile->left_in_line,
10660                         g_parsefile->next_to_pgetc,
10661                         g_parsefile->next_to_pgetc);
10662         return (unsigned char)*g_parsefile->next_to_pgetc++;
10663 }
10664
10665 static void
10666 nlprompt(void)
10667 {
10668         g_parsefile->linno++;
10669         setprompt_if(doprompt, 2);
10670 }
10671 static void
10672 nlnoprompt(void)
10673 {
10674         g_parsefile->linno++;
10675         needprompt = doprompt;
10676 }
10677
10678 static int
10679 pgetc(void)
10680 {
10681         int c;
10682
10683         pgetc_debug("pgetc at %d:%p'%s'",
10684                         g_parsefile->left_in_line,
10685                         g_parsefile->next_to_pgetc,
10686                         g_parsefile->next_to_pgetc);
10687         if (g_parsefile->unget)
10688                 return g_parsefile->lastc[--g_parsefile->unget];
10689
10690         if (--g_parsefile->left_in_line >= 0)
10691                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10692         else
10693                 c = preadbuffer();
10694
10695         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10696         g_parsefile->lastc[0] = c;
10697
10698         return c;
10699 }
10700
10701 #if ENABLE_ASH_ALIAS
10702 static int
10703 pgetc_without_PEOA(void)
10704 {
10705         int c;
10706         do {
10707                 pgetc_debug("pgetc at %d:%p'%s'",
10708                                 g_parsefile->left_in_line,
10709                                 g_parsefile->next_to_pgetc,
10710                                 g_parsefile->next_to_pgetc);
10711                 c = pgetc();
10712         } while (c == PEOA);
10713         return c;
10714 }
10715 #else
10716 # define pgetc_without_PEOA() pgetc()
10717 #endif
10718
10719 /*
10720  * Undo a call to pgetc.  Only two characters may be pushed back.
10721  * PEOF may be pushed back.
10722  */
10723 static void
10724 pungetc(void)
10725 {
10726         g_parsefile->unget++;
10727 }
10728
10729 /* This one eats backslash+newline */
10730 static int
10731 pgetc_eatbnl(void)
10732 {
10733         int c;
10734
10735         while ((c = pgetc()) == '\\') {
10736                 if (pgetc() != '\n') {
10737                         pungetc();
10738                         break;
10739                 }
10740
10741                 nlprompt();
10742         }
10743
10744         return c;
10745 }
10746
10747 struct synstack {
10748         smalluint syntax;
10749         uint8_t innerdq   :1;
10750         uint8_t varpushed :1;
10751         uint8_t dblquote  :1;
10752         int varnest;            /* levels of variables expansion */
10753         int dqvarnest;          /* levels of variables expansion within double quotes */
10754         int parenlevel;         /* levels of parens in arithmetic */
10755         struct synstack *prev;
10756         struct synstack *next;
10757 };
10758
10759 static void
10760 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10761 {
10762         memset(next, 0, sizeof(*next));
10763         next->syntax = syntax;
10764         next->next = *stack;
10765         (*stack)->prev = next;
10766         *stack = next;
10767 }
10768
10769 static ALWAYS_INLINE void
10770 synstack_pop(struct synstack **stack)
10771 {
10772         *stack = (*stack)->next;
10773 }
10774
10775 /*
10776  * To handle the "." command, a stack of input files is used.  Pushfile
10777  * adds a new entry to the stack and popfile restores the previous level.
10778  */
10779 static void
10780 pushfile(void)
10781 {
10782         struct parsefile *pf;
10783
10784         pf = ckzalloc(sizeof(*pf));
10785         pf->prev = g_parsefile;
10786         pf->pf_fd = -1;
10787         /*pf->strpush = NULL; - ckzalloc did it */
10788         /*pf->basestrpush.prev = NULL;*/
10789         /*pf->unget = 0;*/
10790         g_parsefile = pf;
10791 }
10792
10793 static void
10794 popfile(void)
10795 {
10796         struct parsefile *pf = g_parsefile;
10797
10798         if (pf == &basepf)
10799                 return;
10800
10801         INT_OFF;
10802         if (pf->pf_fd >= 0)
10803                 close(pf->pf_fd);
10804         free(pf->buf);
10805         while (pf->strpush)
10806                 popstring();
10807         g_parsefile = pf->prev;
10808         free(pf);
10809         INT_ON;
10810 }
10811
10812 static void
10813 unwindfiles(struct parsefile *stop)
10814 {
10815         while (g_parsefile != stop)
10816                 popfile();
10817 }
10818
10819 /*
10820  * Return to top level.
10821  */
10822 static void
10823 popallfiles(void)
10824 {
10825         unwindfiles(&basepf);
10826 }
10827
10828 /*
10829  * Close the file(s) that the shell is reading commands from.  Called
10830  * after a fork is done.
10831  */
10832 static void
10833 closescript(void)
10834 {
10835         popallfiles();
10836         if (g_parsefile->pf_fd > 0) {
10837                 close(g_parsefile->pf_fd);
10838                 g_parsefile->pf_fd = 0;
10839         }
10840 }
10841
10842 /*
10843  * Like setinputfile, but takes an open file descriptor.  Call this with
10844  * interrupts off.
10845  */
10846 static void
10847 setinputfd(int fd, int push)
10848 {
10849         if (push) {
10850                 pushfile();
10851                 g_parsefile->buf = NULL;
10852         }
10853         g_parsefile->pf_fd = fd;
10854         if (g_parsefile->buf == NULL)
10855                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10856         g_parsefile->left_in_buffer = 0;
10857         g_parsefile->left_in_line = 0;
10858         g_parsefile->linno = 1;
10859 }
10860
10861 /*
10862  * Set the input to take input from a file.  If push is set, push the
10863  * old input onto the stack first.
10864  */
10865 static int
10866 setinputfile(const char *fname, int flags)
10867 {
10868         int fd;
10869
10870         INT_OFF;
10871         fd = open(fname, O_RDONLY | O_CLOEXEC);
10872         if (fd < 0) {
10873                 if (flags & INPUT_NOFILE_OK)
10874                         goto out;
10875                 exitstatus = 127;
10876                 ash_msg_and_raise_perror("can't open '%s'", fname);
10877         }
10878         if (fd < 10)
10879                 fd = savefd(fd);
10880         else if (O_CLOEXEC == 0) /* old libc */
10881                 close_on_exec_on(fd);
10882
10883         setinputfd(fd, flags & INPUT_PUSH_FILE);
10884  out:
10885         INT_ON;
10886         return fd;
10887 }
10888
10889 /*
10890  * Like setinputfile, but takes input from a string.
10891  */
10892 static void
10893 setinputstring(char *string)
10894 {
10895         INT_OFF;
10896         pushfile();
10897         g_parsefile->next_to_pgetc = string;
10898         g_parsefile->left_in_line = strlen(string);
10899         g_parsefile->buf = NULL;
10900         g_parsefile->linno = 1;
10901         INT_ON;
10902 }
10903
10904
10905 /*
10906  * Routines to check for mail.
10907  */
10908
10909 #if ENABLE_ASH_MAIL
10910
10911 /* Hash of mtimes of mailboxes */
10912 static unsigned mailtime_hash;
10913 /* Set if MAIL or MAILPATH is changed. */
10914 static smallint mail_var_path_changed;
10915
10916 /*
10917  * Print appropriate message(s) if mail has arrived.
10918  * If mail_var_path_changed is set,
10919  * then the value of MAIL has mail_var_path_changed,
10920  * so we just update the values.
10921  */
10922 static void
10923 chkmail(void)
10924 {
10925         const char *mpath;
10926         char *p;
10927         char *q;
10928         unsigned new_hash;
10929         struct stackmark smark;
10930         struct stat statb;
10931
10932         setstackmark(&smark);
10933         mpath = mpathset() ? mpathval() : mailval();
10934         new_hash = 0;
10935         for (;;) {
10936                 p = path_advance(&mpath, nullstr);
10937                 if (p == NULL)
10938                         break;
10939                 if (*p == '\0')
10940                         continue;
10941                 for (q = p; *q; q++)
10942                         continue;
10943 #if DEBUG
10944                 if (q[-1] != '/')
10945                         abort();
10946 #endif
10947                 q[-1] = '\0';                   /* delete trailing '/' */
10948                 if (stat(p, &statb) < 0) {
10949                         continue;
10950                 }
10951                 /* Very simplistic "hash": just a sum of all mtimes */
10952                 new_hash += (unsigned)statb.st_mtime;
10953         }
10954         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10955                 if (mailtime_hash != 0)
10956                         out2str("you have mail\n");
10957                 mailtime_hash = new_hash;
10958         }
10959         mail_var_path_changed = 0;
10960         popstackmark(&smark);
10961 }
10962
10963 static void FAST_FUNC
10964 changemail(const char *val UNUSED_PARAM)
10965 {
10966         mail_var_path_changed = 1;
10967 }
10968
10969 #endif /* ASH_MAIL */
10970
10971
10972 /* ============ ??? */
10973
10974 /*
10975  * Set the shell parameters.
10976  */
10977 static void
10978 setparam(char **argv)
10979 {
10980         char **newparam;
10981         char **ap;
10982         int nparam;
10983
10984         for (nparam = 0; argv[nparam]; nparam++)
10985                 continue;
10986         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10987         while (*argv) {
10988                 *ap++ = ckstrdup(*argv++);
10989         }
10990         *ap = NULL;
10991         freeparam(&shellparam);
10992         shellparam.malloced = 1;
10993         shellparam.nparam = nparam;
10994         shellparam.p = newparam;
10995 #if ENABLE_ASH_GETOPTS
10996         shellparam.optind = 1;
10997         shellparam.optoff = -1;
10998 #endif
10999 }
11000
11001 /*
11002  * Process shell options.  The global variable argptr contains a pointer
11003  * to the argument list; we advance it past the options.
11004  *
11005  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
11006  * For a non-interactive shell, an error condition encountered
11007  * by a special built-in ... shall cause the shell to write a diagnostic message
11008  * to standard error and exit as shown in the following table:
11009  * Error                                           Special Built-In
11010  * ...
11011  * Utility syntax error (option or operand error)  Shall exit
11012  * ...
11013  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
11014  * we see that bash does not do that (set "finishes" with error code 1 instead,
11015  * and shell continues), and people rely on this behavior!
11016  * Testcase:
11017  * set -o barfoo 2>/dev/null
11018  * echo $?
11019  *
11020  * Oh well. Let's mimic that.
11021  */
11022 static int
11023 plus_minus_o(char *name, int val)
11024 {
11025         int i;
11026
11027         if (name) {
11028                 for (i = 0; i < NOPTS; i++) {
11029                         if (strcmp(name, optnames(i)) == 0) {
11030                                 optlist[i] = val;
11031                                 return 0;
11032                         }
11033                 }
11034                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
11035                 return 1;
11036         }
11037         for (i = 0; i < NOPTS; i++) {
11038                 if (val) {
11039                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
11040                 } else {
11041                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
11042                 }
11043         }
11044         return 0;
11045 }
11046 static void
11047 setoption(int flag, int val)
11048 {
11049         int i;
11050
11051         for (i = 0; i < NOPTS; i++) {
11052                 if (optletters(i) == flag) {
11053                         optlist[i] = val;
11054                         return;
11055                 }
11056         }
11057         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
11058         /* NOTREACHED */
11059 }
11060 static int
11061 options(int cmdline, int *login_sh)
11062 {
11063         char *p;
11064         int val;
11065         int c;
11066
11067         if (cmdline)
11068                 minusc = NULL;
11069         while ((p = *argptr) != NULL) {
11070                 c = *p++;
11071                 if (c != '-' && c != '+')
11072                         break;
11073                 argptr++;
11074                 val = 0; /* val = 0 if c == '+' */
11075                 if (c == '-') {
11076                         val = 1;
11077                         if (p[0] == '\0' || LONE_DASH(p)) {
11078                                 if (!cmdline) {
11079                                         /* "-" means turn off -x and -v */
11080                                         if (p[0] == '\0')
11081                                                 xflag = vflag = 0;
11082                                         /* "--" means reset params */
11083                                         else if (*argptr == NULL)
11084                                                 setparam(argptr);
11085                                 }
11086                                 break;    /* "-" or "--" terminates options */
11087                         }
11088                 }
11089                 /* first char was + or - */
11090                 while ((c = *p++) != '\0') {
11091                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11092                         if (c == 'c' && cmdline) {
11093                                 minusc = p;     /* command is after shell args */
11094                         } else if (c == 'o') {
11095                                 if (plus_minus_o(*argptr, val)) {
11096                                         /* it already printed err message */
11097                                         return 1; /* error */
11098                                 }
11099                                 if (*argptr)
11100                                         argptr++;
11101                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
11102                                 if (login_sh)
11103                                         *login_sh = 1;
11104                         /* bash does not accept +-login, we also won't */
11105                         } else if (cmdline && val && (c == '-')) { /* long options */
11106                                 if (strcmp(p, "login") == 0) {
11107                                         if (login_sh)
11108                                                 *login_sh = 1;
11109                                 }
11110                                 break;
11111                         } else {
11112                                 setoption(c, val);
11113                         }
11114                 }
11115         }
11116         return 0;
11117 }
11118
11119 /*
11120  * The shift builtin command.
11121  */
11122 static int FAST_FUNC
11123 shiftcmd(int argc UNUSED_PARAM, char **argv)
11124 {
11125         int n;
11126         char **ap1, **ap2;
11127
11128         n = 1;
11129         if (argv[1])
11130                 n = number(argv[1]);
11131         if (n > shellparam.nparam)
11132                 return 1;
11133         INT_OFF;
11134         shellparam.nparam -= n;
11135         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11136                 if (shellparam.malloced)
11137                         free(*ap1);
11138         }
11139         ap2 = shellparam.p;
11140         while ((*ap2++ = *ap1++) != NULL)
11141                 continue;
11142 #if ENABLE_ASH_GETOPTS
11143         shellparam.optind = 1;
11144         shellparam.optoff = -1;
11145 #endif
11146         INT_ON;
11147         return 0;
11148 }
11149
11150 /*
11151  * POSIX requires that 'set' (but not export or readonly) output the
11152  * variables in lexicographic order - by the locale's collating order (sigh).
11153  * Maybe we could keep them in an ordered balanced binary tree
11154  * instead of hashed lists.
11155  * For now just roll 'em through qsort for printing...
11156  */
11157 static int
11158 showvars(const char *sep_prefix, int on, int off)
11159 {
11160         const char *sep;
11161         char **ep, **epend;
11162
11163         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11164         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11165
11166         sep = *sep_prefix ? " " : sep_prefix;
11167
11168         for (; ep < epend; ep++) {
11169                 const char *p;
11170                 const char *q;
11171
11172                 p = endofname(*ep);
11173 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11174  * makes "export -p" to have output not suitable for "eval":
11175  * import os
11176  * os.environ["test-test"]="test"
11177  * if os.fork() == 0:
11178  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11179  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11180  */
11181                 q = nullstr;
11182                 if (*p == '=')
11183                         q = single_quote(++p);
11184                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11185         }
11186         return 0;
11187 }
11188
11189 /*
11190  * The set command builtin.
11191  */
11192 static int FAST_FUNC
11193 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11194 {
11195         int retval;
11196
11197         if (!argv[1])
11198                 return showvars(nullstr, 0, VUNSET);
11199
11200         INT_OFF;
11201         retval = options(/*cmdline:*/ 0, NULL);
11202         if (retval == 0) { /* if no parse error... */
11203                 optschanged();
11204                 if (*argptr != NULL) {
11205                         setparam(argptr);
11206                 }
11207         }
11208         INT_ON;
11209         return retval;
11210 }
11211
11212 #if ENABLE_ASH_RANDOM_SUPPORT
11213 static void FAST_FUNC
11214 change_random(const char *value)
11215 {
11216         uint32_t t;
11217
11218         if (value == NULL) {
11219                 /* "get", generate */
11220                 t = next_random(&random_gen);
11221                 /* set without recursion */
11222                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11223                 vrandom.flags &= ~VNOFUNC;
11224         } else {
11225                 /* set/reset */
11226                 t = strtoul(value, NULL, 10);
11227                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11228         }
11229 }
11230 #endif
11231
11232 #if ENABLE_ASH_GETOPTS
11233 static int
11234 getopts(char *optstr, char *optvar, char **optfirst)
11235 {
11236         char *p, *q;
11237         char c = '?';
11238         int done = 0;
11239         char sbuf[2];
11240         char **optnext;
11241         int ind = shellparam.optind;
11242         int off = shellparam.optoff;
11243
11244         sbuf[1] = '\0';
11245
11246         shellparam.optind = -1;
11247         optnext = optfirst + ind - 1;
11248
11249         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11250                 p = NULL;
11251         else
11252                 p = optnext[-1] + off;
11253         if (p == NULL || *p == '\0') {
11254                 /* Current word is done, advance */
11255                 p = *optnext;
11256                 if (p == NULL || *p != '-' || *++p == '\0') {
11257  atend:
11258                         unsetvar("OPTARG");
11259                         p = NULL;
11260                         done = 1;
11261                         goto out;
11262                 }
11263                 optnext++;
11264                 if (LONE_DASH(p))        /* check for "--" */
11265                         goto atend;
11266         }
11267
11268         c = *p++;
11269         for (q = optstr; *q != c;) {
11270                 if (*q == '\0') {
11271                         /* OPTERR is a bashism */
11272                         const char *cp = lookupvar("OPTERR");
11273                         if ((cp && LONE_CHAR(cp, '0'))
11274                          || (optstr[0] == ':')
11275                         ) {
11276                                 sbuf[0] = c;
11277                                 /*sbuf[1] = '\0'; - already is */
11278                                 setvar0("OPTARG", sbuf);
11279                         } else {
11280                                 fprintf(stderr, "Illegal option -%c\n", c);
11281                                 unsetvar("OPTARG");
11282                         }
11283                         c = '?';
11284                         goto out;
11285                 }
11286                 if (*++q == ':')
11287                         q++;
11288         }
11289
11290         if (*++q == ':') {
11291                 if (*p == '\0' && (p = *optnext) == NULL) {
11292                         /* OPTERR is a bashism */
11293                         const char *cp = lookupvar("OPTERR");
11294                         if ((cp && LONE_CHAR(cp, '0'))
11295                          || (optstr[0] == ':')
11296                         ) {
11297                                 sbuf[0] = c;
11298                                 /*sbuf[1] = '\0'; - already is */
11299                                 setvar0("OPTARG", sbuf);
11300                                 c = ':';
11301                         } else {
11302                                 fprintf(stderr, "No arg for -%c option\n", c);
11303                                 unsetvar("OPTARG");
11304                                 c = '?';
11305                         }
11306                         goto out;
11307                 }
11308
11309                 if (p == *optnext)
11310                         optnext++;
11311                 setvar0("OPTARG", p);
11312                 p = NULL;
11313         } else
11314                 setvar0("OPTARG", nullstr);
11315  out:
11316         ind = optnext - optfirst + 1;
11317         setvar("OPTIND", itoa(ind), VNOFUNC);
11318         sbuf[0] = c;
11319         /*sbuf[1] = '\0'; - already is */
11320         setvar0(optvar, sbuf);
11321
11322         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11323         shellparam.optind = ind;
11324
11325         return done;
11326 }
11327
11328 /*
11329  * The getopts builtin.  Shellparam.optnext points to the next argument
11330  * to be processed.  Shellparam.optptr points to the next character to
11331  * be processed in the current argument.  If shellparam.optnext is NULL,
11332  * then it's the first time getopts has been called.
11333  */
11334 static int FAST_FUNC
11335 getoptscmd(int argc, char **argv)
11336 {
11337         char **optbase;
11338
11339         if (argc < 3)
11340                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11341         if (argc == 3) {
11342                 optbase = shellparam.p;
11343                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11344                         shellparam.optind = 1;
11345                         shellparam.optoff = -1;
11346                 }
11347         } else {
11348                 optbase = &argv[3];
11349                 if ((unsigned)shellparam.optind > argc - 2) {
11350                         shellparam.optind = 1;
11351                         shellparam.optoff = -1;
11352                 }
11353         }
11354
11355         return getopts(argv[1], argv[2], optbase);
11356 }
11357 #endif /* ASH_GETOPTS */
11358
11359
11360 /* ============ Shell parser */
11361
11362 struct heredoc {
11363         struct heredoc *next;   /* next here document in list */
11364         union node *here;       /* redirection node */
11365         char *eofmark;          /* string indicating end of input */
11366         smallint striptabs;     /* if set, strip leading tabs */
11367 };
11368
11369 static smallint tokpushback;           /* last token pushed back */
11370 static smallint quoteflag;             /* set if (part of) last token was quoted */
11371 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11372 static struct heredoc *heredoclist;    /* list of here documents to read */
11373 static char *wordtext;                 /* text of last word returned by readtoken */
11374 static struct nodelist *backquotelist;
11375 static union node *redirnode;
11376 static struct heredoc *heredoc;
11377
11378 static const char *
11379 tokname(char *buf, int tok)
11380 {
11381         if (tok < TSEMI)
11382                 return tokname_array[tok];
11383         sprintf(buf, "\"%s\"", tokname_array[tok]);
11384         return buf;
11385 }
11386
11387 /* raise_error_unexpected_syntax:
11388  * Called when an unexpected token is read during the parse.  The argument
11389  * is the token that is expected, or -1 if more than one type of token can
11390  * occur at this point.
11391  */
11392 static void raise_error_unexpected_syntax(int) NORETURN;
11393 static void
11394 raise_error_unexpected_syntax(int token)
11395 {
11396         char msg[64];
11397         char buf[16];
11398         int l;
11399
11400         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11401         if (token >= 0)
11402                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11403         raise_error_syntax(msg);
11404         /* NOTREACHED */
11405 }
11406
11407 /* parsing is heavily cross-recursive, need these forward decls */
11408 static union node *andor(void);
11409 static union node *pipeline(void);
11410 static union node *parse_command(void);
11411 static void parseheredoc(void);
11412 static int peektoken(void);
11413 static int readtoken(void);
11414
11415 static union node *
11416 list(int nlflag)
11417 {
11418         union node *n1, *n2, *n3;
11419         int tok;
11420
11421         n1 = NULL;
11422         for (;;) {
11423                 switch (peektoken()) {
11424                 case TNL:
11425                         if (!(nlflag & 1))
11426                                 break;
11427                         parseheredoc();
11428                         return n1;
11429
11430                 case TEOF:
11431                         if (!n1 && (nlflag & 1))
11432                                 n1 = NODE_EOF;
11433                         parseheredoc();
11434                         return n1;
11435                 }
11436
11437                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11438                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11439                         return n1;
11440                 nlflag |= 2;
11441
11442                 n2 = andor();
11443                 tok = readtoken();
11444                 if (tok == TBACKGND) {
11445                         if (n2->type == NPIPE) {
11446                                 n2->npipe.pipe_backgnd = 1;
11447                         } else {
11448                                 if (n2->type != NREDIR) {
11449                                         n3 = stzalloc(sizeof(struct nredir));
11450                                         n3->nredir.n = n2;
11451                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11452                                         n2 = n3;
11453                                 }
11454                                 n2->type = NBACKGND;
11455                         }
11456                 }
11457                 if (n1 == NULL) {
11458                         n1 = n2;
11459                 } else {
11460                         n3 = stzalloc(sizeof(struct nbinary));
11461                         n3->type = NSEMI;
11462                         n3->nbinary.ch1 = n1;
11463                         n3->nbinary.ch2 = n2;
11464                         n1 = n3;
11465                 }
11466                 switch (tok) {
11467                 case TNL:
11468                 case TEOF:
11469                         tokpushback = 1;
11470                         /* fall through */
11471                 case TBACKGND:
11472                 case TSEMI:
11473                         break;
11474                 default:
11475                         if ((nlflag & 1))
11476                                 raise_error_unexpected_syntax(-1);
11477                         tokpushback = 1;
11478                         return n1;
11479                 }
11480         }
11481 }
11482
11483 static union node *
11484 andor(void)
11485 {
11486         union node *n1, *n2, *n3;
11487         int t;
11488
11489         n1 = pipeline();
11490         for (;;) {
11491                 t = readtoken();
11492                 if (t == TAND) {
11493                         t = NAND;
11494                 } else if (t == TOR) {
11495                         t = NOR;
11496                 } else {
11497                         tokpushback = 1;
11498                         return n1;
11499                 }
11500                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11501                 n2 = pipeline();
11502                 n3 = stzalloc(sizeof(struct nbinary));
11503                 n3->type = t;
11504                 n3->nbinary.ch1 = n1;
11505                 n3->nbinary.ch2 = n2;
11506                 n1 = n3;
11507         }
11508 }
11509
11510 static union node *
11511 pipeline(void)
11512 {
11513         union node *n1, *n2, *pipenode;
11514         struct nodelist *lp, *prev;
11515         int negate;
11516
11517         negate = 0;
11518         TRACE(("pipeline: entered\n"));
11519         if (readtoken() == TNOT) {
11520                 negate = !negate;
11521                 checkkwd = CHKKWD | CHKALIAS;
11522         } else
11523                 tokpushback = 1;
11524         n1 = parse_command();
11525         if (readtoken() == TPIPE) {
11526                 pipenode = stzalloc(sizeof(struct npipe));
11527                 pipenode->type = NPIPE;
11528                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11529                 lp = stzalloc(sizeof(struct nodelist));
11530                 pipenode->npipe.cmdlist = lp;
11531                 lp->n = n1;
11532                 do {
11533                         prev = lp;
11534                         lp = stzalloc(sizeof(struct nodelist));
11535                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11536                         lp->n = parse_command();
11537                         prev->next = lp;
11538                 } while (readtoken() == TPIPE);
11539                 lp->next = NULL;
11540                 n1 = pipenode;
11541         }
11542         tokpushback = 1;
11543         if (negate) {
11544                 n2 = stzalloc(sizeof(struct nnot));
11545                 n2->type = NNOT;
11546                 n2->nnot.com = n1;
11547                 return n2;
11548         }
11549         return n1;
11550 }
11551
11552 static union node *
11553 makename(void)
11554 {
11555         union node *n;
11556
11557         n = stzalloc(sizeof(struct narg));
11558         n->type = NARG;
11559         /*n->narg.next = NULL; - stzalloc did it */
11560         n->narg.text = wordtext;
11561         n->narg.backquote = backquotelist;
11562         return n;
11563 }
11564
11565 static void
11566 fixredir(union node *n, const char *text, int err)
11567 {
11568         int fd;
11569
11570         TRACE(("Fix redir %s %d\n", text, err));
11571         if (!err)
11572                 n->ndup.vname = NULL;
11573
11574         fd = bb_strtou(text, NULL, 10);
11575         if (!errno && fd >= 0)
11576                 n->ndup.dupfd = fd;
11577         else if (LONE_DASH(text))
11578                 n->ndup.dupfd = -1;
11579         else {
11580                 if (err)
11581                         raise_error_syntax("bad fd number");
11582                 n->ndup.vname = makename();
11583         }
11584 }
11585
11586 static void
11587 parsefname(void)
11588 {
11589         union node *n = redirnode;
11590
11591         if (n->type == NHERE)
11592                 checkkwd = CHKEOFMARK;
11593         if (readtoken() != TWORD)
11594                 raise_error_unexpected_syntax(-1);
11595         if (n->type == NHERE) {
11596                 struct heredoc *here = heredoc;
11597                 struct heredoc *p;
11598
11599                 if (quoteflag == 0)
11600                         n->type = NXHERE;
11601                 TRACE(("Here document %d\n", n->type));
11602                 rmescapes(wordtext, 0, NULL);
11603                 here->eofmark = wordtext;
11604                 here->next = NULL;
11605                 if (heredoclist == NULL)
11606                         heredoclist = here;
11607                 else {
11608                         for (p = heredoclist; p->next; p = p->next)
11609                                 continue;
11610                         p->next = here;
11611                 }
11612         } else if (n->type == NTOFD || n->type == NFROMFD) {
11613                 fixredir(n, wordtext, 0);
11614         } else {
11615                 n->nfile.fname = makename();
11616         }
11617 }
11618
11619 static union node *
11620 simplecmd(void)
11621 {
11622         union node *args, **app;
11623         union node *n = NULL;
11624         union node *vars, **vpp;
11625         union node **rpp, *redir;
11626         int savecheckkwd;
11627         int savelinno;
11628 #if BASH_TEST2
11629         smallint double_brackets_flag = 0;
11630 #endif
11631         IF_BASH_FUNCTION(smallint function_flag = 0;)
11632
11633         args = NULL;
11634         app = &args;
11635         vars = NULL;
11636         vpp = &vars;
11637         redir = NULL;
11638         rpp = &redir;
11639
11640         savecheckkwd = CHKALIAS;
11641         savelinno = g_parsefile->linno;
11642         for (;;) {
11643                 int t;
11644                 checkkwd = savecheckkwd;
11645                 t = readtoken();
11646                 switch (t) {
11647 #if BASH_FUNCTION
11648                 case TFUNCTION:
11649                         if (peektoken() != TWORD)
11650                                 raise_error_unexpected_syntax(TWORD);
11651                         function_flag = 1;
11652                         break;
11653 #endif
11654 #if BASH_TEST2
11655                 case TAND: /* "&&" */
11656                 case TOR: /* "||" */
11657                         if (!double_brackets_flag) {
11658                                 tokpushback = 1;
11659                                 goto out;
11660                         }
11661                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11662 #endif
11663                 case TWORD:
11664                         n = stzalloc(sizeof(struct narg));
11665                         n->type = NARG;
11666                         /*n->narg.next = NULL; - stzalloc did it */
11667                         n->narg.text = wordtext;
11668 #if BASH_TEST2
11669                         if (strcmp("[[", wordtext) == 0)
11670                                 double_brackets_flag = 1;
11671                         else if (strcmp("]]", wordtext) == 0)
11672                                 double_brackets_flag = 0;
11673 #endif
11674                         n->narg.backquote = backquotelist;
11675                         if (savecheckkwd && isassignment(wordtext)) {
11676                                 *vpp = n;
11677                                 vpp = &n->narg.next;
11678                         } else {
11679                                 *app = n;
11680                                 app = &n->narg.next;
11681                                 savecheckkwd = 0;
11682                         }
11683 #if BASH_FUNCTION
11684                         if (function_flag) {
11685                                 checkkwd = CHKNL | CHKKWD;
11686                                 switch (peektoken()) {
11687                                 case TBEGIN:
11688                                 case TIF:
11689                                 case TCASE:
11690                                 case TUNTIL:
11691                                 case TWHILE:
11692                                 case TFOR:
11693                                         goto do_func;
11694                                 case TLP:
11695                                         function_flag = 0;
11696                                         break;
11697 # if BASH_TEST2
11698                                 case TWORD:
11699                                         if (strcmp("[[", wordtext) == 0)
11700                                                 goto do_func;
11701                                         /* fall through */
11702 # endif
11703                                 default:
11704                                         raise_error_unexpected_syntax(-1);
11705                                 }
11706                         }
11707 #endif
11708                         break;
11709                 case TREDIR:
11710                         *rpp = n = redirnode;
11711                         rpp = &n->nfile.next;
11712                         parsefname();   /* read name of redirection file */
11713                         break;
11714                 case TLP:
11715  IF_BASH_FUNCTION(do_func:)
11716                         if (args && app == &args->narg.next
11717                          && !vars && !redir
11718                         ) {
11719                                 struct builtincmd *bcmd;
11720                                 const char *name;
11721
11722                                 /* We have a function */
11723                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11724                                         raise_error_unexpected_syntax(TRP);
11725                                 name = n->narg.text;
11726                                 if (!goodname(name)
11727                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11728                                 ) {
11729                                         raise_error_syntax("bad function name");
11730                                 }
11731                                 n->type = NDEFUN;
11732                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11733                                 n->ndefun.text = n->narg.text;
11734                                 n->ndefun.linno = g_parsefile->linno;
11735                                 n->ndefun.body = parse_command();
11736                                 return n;
11737                         }
11738                         IF_BASH_FUNCTION(function_flag = 0;)
11739                         /* fall through */
11740                 default:
11741                         tokpushback = 1;
11742                         goto out;
11743                 }
11744         }
11745  out:
11746         *app = NULL;
11747         *vpp = NULL;
11748         *rpp = NULL;
11749         n = stzalloc(sizeof(struct ncmd));
11750         if (NCMD != 0)
11751                 n->type = NCMD;
11752         n->ncmd.linno = savelinno;
11753         n->ncmd.args = args;
11754         n->ncmd.assign = vars;
11755         n->ncmd.redirect = redir;
11756         return n;
11757 }
11758
11759 static union node *
11760 parse_command(void)
11761 {
11762         union node *n1, *n2;
11763         union node *ap, **app;
11764         union node *cp, **cpp;
11765         union node *redir, **rpp;
11766         union node **rpp2;
11767         int t;
11768         int savelinno;
11769
11770         redir = NULL;
11771         rpp2 = &redir;
11772
11773         savelinno = g_parsefile->linno;
11774
11775         switch (readtoken()) {
11776         default:
11777                 raise_error_unexpected_syntax(-1);
11778                 /* NOTREACHED */
11779         case TIF:
11780                 n1 = stzalloc(sizeof(struct nif));
11781                 n1->type = NIF;
11782                 n1->nif.test = list(0);
11783                 if (readtoken() != TTHEN)
11784                         raise_error_unexpected_syntax(TTHEN);
11785                 n1->nif.ifpart = list(0);
11786                 n2 = n1;
11787                 while (readtoken() == TELIF) {
11788                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11789                         n2 = n2->nif.elsepart;
11790                         n2->type = NIF;
11791                         n2->nif.test = list(0);
11792                         if (readtoken() != TTHEN)
11793                                 raise_error_unexpected_syntax(TTHEN);
11794                         n2->nif.ifpart = list(0);
11795                 }
11796                 if (lasttoken == TELSE)
11797                         n2->nif.elsepart = list(0);
11798                 else {
11799                         n2->nif.elsepart = NULL;
11800                         tokpushback = 1;
11801                 }
11802                 t = TFI;
11803                 break;
11804         case TWHILE:
11805         case TUNTIL: {
11806                 int got;
11807                 n1 = stzalloc(sizeof(struct nbinary));
11808                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11809                 n1->nbinary.ch1 = list(0);
11810                 got = readtoken();
11811                 if (got != TDO) {
11812                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11813                                         got == TWORD ? wordtext : ""));
11814                         raise_error_unexpected_syntax(TDO);
11815                 }
11816                 n1->nbinary.ch2 = list(0);
11817                 t = TDONE;
11818                 break;
11819         }
11820         case TFOR:
11821                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11822                         raise_error_syntax("bad for loop variable");
11823                 n1 = stzalloc(sizeof(struct nfor));
11824                 n1->type = NFOR;
11825                 n1->nfor.linno = savelinno;
11826                 n1->nfor.var = wordtext;
11827                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11828                 if (readtoken() == TIN) {
11829                         app = &ap;
11830                         while (readtoken() == TWORD) {
11831                                 n2 = stzalloc(sizeof(struct narg));
11832                                 n2->type = NARG;
11833                                 /*n2->narg.next = NULL; - stzalloc did it */
11834                                 n2->narg.text = wordtext;
11835                                 n2->narg.backquote = backquotelist;
11836                                 *app = n2;
11837                                 app = &n2->narg.next;
11838                         }
11839                         *app = NULL;
11840                         n1->nfor.args = ap;
11841                         if (lasttoken != TNL && lasttoken != TSEMI)
11842                                 raise_error_unexpected_syntax(-1);
11843                 } else {
11844                         n2 = stzalloc(sizeof(struct narg));
11845                         n2->type = NARG;
11846                         /*n2->narg.next = NULL; - stzalloc did it */
11847                         n2->narg.text = (char *)dolatstr;
11848                         /*n2->narg.backquote = NULL;*/
11849                         n1->nfor.args = n2;
11850                         /*
11851                          * Newline or semicolon here is optional (but note
11852                          * that the original Bourne shell only allowed NL).
11853                          */
11854                         if (lasttoken != TSEMI)
11855                                 tokpushback = 1;
11856                 }
11857                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11858                 if (readtoken() != TDO)
11859                         raise_error_unexpected_syntax(TDO);
11860                 n1->nfor.body = list(0);
11861                 t = TDONE;
11862                 break;
11863         case TCASE:
11864                 n1 = stzalloc(sizeof(struct ncase));
11865                 n1->type = NCASE;
11866                 n1->ncase.linno = savelinno;
11867                 if (readtoken() != TWORD)
11868                         raise_error_unexpected_syntax(TWORD);
11869                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11870                 n2->type = NARG;
11871                 /*n2->narg.next = NULL; - stzalloc did it */
11872                 n2->narg.text = wordtext;
11873                 n2->narg.backquote = backquotelist;
11874                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11875                 if (readtoken() != TIN)
11876                         raise_error_unexpected_syntax(TIN);
11877                 cpp = &n1->ncase.cases;
11878  next_case:
11879                 checkkwd = CHKNL | CHKKWD;
11880                 t = readtoken();
11881                 while (t != TESAC) {
11882                         if (lasttoken == TLP)
11883                                 readtoken();
11884                         *cpp = cp = stzalloc(sizeof(struct nclist));
11885                         cp->type = NCLIST;
11886                         app = &cp->nclist.pattern;
11887                         for (;;) {
11888                                 *app = ap = stzalloc(sizeof(struct narg));
11889                                 ap->type = NARG;
11890                                 /*ap->narg.next = NULL; - stzalloc did it */
11891                                 ap->narg.text = wordtext;
11892                                 ap->narg.backquote = backquotelist;
11893                                 if (readtoken() != TPIPE)
11894                                         break;
11895                                 app = &ap->narg.next;
11896                                 readtoken();
11897                         }
11898                         //ap->narg.next = NULL;
11899                         if (lasttoken != TRP)
11900                                 raise_error_unexpected_syntax(TRP);
11901                         cp->nclist.body = list(2);
11902
11903                         cpp = &cp->nclist.next;
11904
11905                         checkkwd = CHKNL | CHKKWD;
11906                         t = readtoken();
11907                         if (t != TESAC) {
11908                                 if (t != TENDCASE)
11909                                         raise_error_unexpected_syntax(TENDCASE);
11910                                 goto next_case;
11911                         }
11912                 }
11913                 *cpp = NULL;
11914                 goto redir;
11915         case TLP:
11916                 n1 = stzalloc(sizeof(struct nredir));
11917                 n1->type = NSUBSHELL;
11918                 n1->nredir.linno = savelinno;
11919                 n1->nredir.n = list(0);
11920                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11921                 t = TRP;
11922                 break;
11923         case TBEGIN:
11924                 n1 = list(0);
11925                 t = TEND;
11926                 break;
11927         IF_BASH_FUNCTION(case TFUNCTION:)
11928         case TWORD:
11929         case TREDIR:
11930                 tokpushback = 1;
11931                 return simplecmd();
11932         }
11933
11934         if (readtoken() != t)
11935                 raise_error_unexpected_syntax(t);
11936
11937  redir:
11938         /* Now check for redirection which may follow command */
11939         checkkwd = CHKKWD | CHKALIAS;
11940         rpp = rpp2;
11941         while (readtoken() == TREDIR) {
11942                 *rpp = n2 = redirnode;
11943                 rpp = &n2->nfile.next;
11944                 parsefname();
11945         }
11946         tokpushback = 1;
11947         *rpp = NULL;
11948         if (redir) {
11949                 if (n1->type != NSUBSHELL) {
11950                         n2 = stzalloc(sizeof(struct nredir));
11951                         n2->type = NREDIR;
11952                         n2->nredir.linno = savelinno;
11953                         n2->nredir.n = n1;
11954                         n1 = n2;
11955                 }
11956                 n1->nredir.redirect = redir;
11957         }
11958         return n1;
11959 }
11960
11961 #if BASH_DOLLAR_SQUOTE
11962 static int
11963 decode_dollar_squote(void)
11964 {
11965         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11966         int c, cnt;
11967         char *p;
11968         char buf[4];
11969
11970         c = pgetc();
11971         p = strchr(C_escapes, c);
11972         if (p) {
11973                 buf[0] = c;
11974                 p = buf;
11975                 cnt = 3;
11976                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11977                         do {
11978                                 c = pgetc();
11979                                 *++p = c;
11980                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11981                         pungetc();
11982                 } else if (c == 'x') { /* \xHH */
11983                         do {
11984                                 c = pgetc();
11985                                 *++p = c;
11986                         } while (isxdigit(c) && --cnt);
11987                         pungetc();
11988                         if (cnt == 3) { /* \x but next char is "bad" */
11989                                 c = 'x';
11990                                 goto unrecognized;
11991                         }
11992                 } else { /* simple seq like \\ or \t */
11993                         p++;
11994                 }
11995                 *p = '\0';
11996                 p = buf;
11997                 c = bb_process_escape_sequence((void*)&p);
11998         } else { /* unrecognized "\z": print both chars unless ' or " */
11999                 if (c != '\'' && c != '"') {
12000  unrecognized:
12001                         c |= 0x100; /* "please encode \, then me" */
12002                 }
12003         }
12004         return c;
12005 }
12006 #endif
12007
12008 /* Used by expandstr to get here-doc like behaviour. */
12009 #define FAKEEOFMARK ((char*)(uintptr_t)1)
12010
12011 static ALWAYS_INLINE int
12012 realeofmark(const char *eofmark)
12013 {
12014         return eofmark && eofmark != FAKEEOFMARK;
12015 }
12016
12017 /*
12018  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
12019  * is not NULL, read a here document.  In the latter case, eofmark is the
12020  * word which marks the end of the document and striptabs is true if
12021  * leading tabs should be stripped from the document.  The argument c
12022  * is the first character of the input token or document.
12023  *
12024  * Because C does not have internal subroutines, I have simulated them
12025  * using goto's to implement the subroutine linkage.  The following macros
12026  * will run code that appears at the end of readtoken1.
12027  */
12028 #define CHECKEND()      {goto checkend; checkend_return:;}
12029 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
12030 #define PARSESUB()      {goto parsesub; parsesub_return:;}
12031 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
12032 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
12033 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
12034 static int
12035 readtoken1(int c, int syntax, char *eofmark, int striptabs)
12036 {
12037         /* NB: syntax parameter fits into smallint */
12038         /* c parameter is an unsigned char or PEOF or PEOA */
12039         char *out;
12040         size_t len;
12041         struct nodelist *bqlist;
12042         smallint quotef;
12043         smallint oldstyle;
12044         smallint pssyntax;   /* we are expanding a prompt string */
12045         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
12046         /* syntax stack */
12047         struct synstack synbase = { };
12048         struct synstack *synstack = &synbase;
12049
12050 #if ENABLE_ASH_EXPAND_PRMT
12051         pssyntax = (syntax == PSSYNTAX);
12052         if (pssyntax)
12053                 syntax = DQSYNTAX;
12054 #else
12055         pssyntax = 0; /* constant */
12056 #endif
12057         synstack->syntax = syntax;
12058
12059         if (syntax == DQSYNTAX)
12060                 synstack->dblquote = 1;
12061         quotef = 0;
12062         bqlist = NULL;
12063
12064         STARTSTACKSTR(out);
12065  loop:
12066         /* For each line, until end of word */
12067         CHECKEND();     /* set c to PEOF if at end of here document */
12068         for (;;) {      /* until end of line or end of word */
12069                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12070                 switch (SIT(c, synstack->syntax)) {
12071                 case CNL:       /* '\n' */
12072                         if (synstack->syntax == BASESYNTAX
12073                          && !synstack->varnest
12074                         ) {
12075                                 goto endword;   /* exit outer loop */
12076                         }
12077                         USTPUTC(c, out);
12078                         nlprompt();
12079                         c = pgetc();
12080                         goto loop;              /* continue outer loop */
12081                 case CWORD:
12082                         USTPUTC(c, out);
12083                         break;
12084                 case CCTL:
12085 #if BASH_DOLLAR_SQUOTE
12086                         if (c == '\\' && bash_dollar_squote) {
12087                                 c = decode_dollar_squote();
12088                                 if (c == '\0') {
12089                                         /* skip $'\000', $'\x00' (like bash) */
12090                                         break;
12091                                 }
12092                                 if (c & 0x100) {
12093                                         /* Unknown escape. Encode as '\z' */
12094                                         c = (unsigned char)c;
12095                                         if (eofmark == NULL || synstack->dblquote)
12096                                                 USTPUTC(CTLESC, out);
12097                                         USTPUTC('\\', out);
12098                                 }
12099                         }
12100 #endif
12101                         if (!eofmark || synstack->dblquote || synstack->varnest)
12102                                 USTPUTC(CTLESC, out);
12103                         USTPUTC(c, out);
12104                         break;
12105                 case CBACK:     /* backslash */
12106                         c = pgetc_without_PEOA();
12107                         if (c == PEOF) {
12108                                 USTPUTC(CTLESC, out);
12109                                 USTPUTC('\\', out);
12110                                 pungetc();
12111                         } else if (c == '\n') {
12112                                 nlprompt();
12113                         } else {
12114                                 if (pssyntax && c == '$') {
12115                                         USTPUTC(CTLESC, out);
12116                                         USTPUTC('\\', out);
12117                                 }
12118                                 /* Backslash is retained if we are in "str"
12119                                  * and next char isn't dquote-special.
12120                                  */
12121                                 if (synstack->dblquote
12122                                  && c != '\\'
12123                                  && c != '`'
12124                                  && c != '$'
12125                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12126                                  && (c != '}' || !synstack->varnest)
12127                                 ) {
12128                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12129                                         USTPUTC('\\', out);
12130                                 }
12131                                 USTPUTC(CTLESC, out);
12132                                 USTPUTC(c, out);
12133                                 quotef = 1;
12134                         }
12135                         break;
12136                 case CSQUOTE:
12137                         synstack->syntax = SQSYNTAX;
12138  quotemark:
12139                         if (eofmark == NULL) {
12140                                 USTPUTC(CTLQUOTEMARK, out);
12141                         }
12142                         break;
12143                 case CDQUOTE:
12144                         synstack->syntax = DQSYNTAX;
12145                         synstack->dblquote = 1;
12146  toggledq:
12147                         if (synstack->varnest)
12148                                 synstack->innerdq ^= 1;
12149                         goto quotemark;
12150                 case CENDQUOTE:
12151                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12152                         if (eofmark != NULL && synstack->varnest == 0) {
12153                                 USTPUTC(c, out);
12154                                 break;
12155                         }
12156
12157                         if (synstack->dqvarnest == 0) {
12158                                 synstack->syntax = BASESYNTAX;
12159                                 synstack->dblquote = 0;
12160                         }
12161
12162                         quotef = 1;
12163
12164                         if (c == '"')
12165                                 goto toggledq;
12166
12167                         goto quotemark;
12168                 case CVAR:      /* '$' */
12169                         PARSESUB();             /* parse substitution */
12170                         break;
12171                 case CENDVAR:   /* '}' */
12172                         if (!synstack->innerdq && synstack->varnest > 0) {
12173                                 if (!--synstack->varnest && synstack->varpushed)
12174                                         synstack_pop(&synstack);
12175                                 else if (synstack->dqvarnest > 0)
12176                                         synstack->dqvarnest--;
12177                                 c = CTLENDVAR;
12178                         }
12179                         USTPUTC(c, out);
12180                         break;
12181 #if ENABLE_FEATURE_SH_MATH
12182                 case CLP:       /* '(' in arithmetic */
12183                         synstack->parenlevel++;
12184                         USTPUTC(c, out);
12185                         break;
12186                 case CRP:       /* ')' in arithmetic */
12187                         if (synstack->parenlevel > 0) {
12188                                 synstack->parenlevel--;
12189                         } else {
12190                                 if (pgetc_eatbnl() == ')') {
12191                                         c = CTLENDARI;
12192                                         synstack_pop(&synstack);
12193                                 } else {
12194                                         /*
12195                                          * unbalanced parens
12196                                          * (don't 2nd guess - no error)
12197                                          */
12198                                         pungetc();
12199                                 }
12200                         }
12201                         USTPUTC(c, out);
12202                         break;
12203 #endif
12204                 case CBQUOTE:   /* '`' */
12205                         if (checkkwd & CHKEOFMARK) {
12206                                 quotef = 1;
12207                                 USTPUTC('`', out);
12208                                 break;
12209                         }
12210
12211                         PARSEBACKQOLD();
12212                         break;
12213                 case CENDFILE:
12214                         goto endword;           /* exit outer loop */
12215                 case CIGN:
12216                         break;
12217                 default:
12218                         if (synstack->varnest == 0) {
12219 #if BASH_REDIR_OUTPUT
12220                                 if (c == '&') {
12221 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12222                                         if (pgetc() == '>')
12223                                                 c = 0x100 + '>'; /* flag &> */
12224                                         pungetc();
12225                                 }
12226 #endif
12227                                 goto endword;   /* exit outer loop */
12228                         }
12229                         IF_ASH_ALIAS(if (c != PEOA))
12230                                 USTPUTC(c, out);
12231                 }
12232                 c = pgetc();
12233         } /* for (;;) */
12234  endword:
12235
12236 #if ENABLE_FEATURE_SH_MATH
12237         if (synstack->syntax == ARISYNTAX)
12238                 raise_error_syntax("missing '))'");
12239 #endif
12240         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12241                 raise_error_syntax("unterminated quoted string");
12242         if (synstack->varnest != 0) {
12243                 /* { */
12244                 raise_error_syntax("missing '}'");
12245         }
12246         USTPUTC('\0', out);
12247         len = out - (char *)stackblock();
12248         out = stackblock();
12249         if (eofmark == NULL) {
12250                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12251                  && quotef == 0
12252                 ) {
12253                         if (isdigit_str9(out)) {
12254                                 PARSEREDIR(); /* passed as params: out, c */
12255                                 lasttoken = TREDIR;
12256                                 return lasttoken;
12257                         }
12258                         /* else: non-number X seen, interpret it
12259                          * as "NNNX>file" = "NNNX >file" */
12260                 }
12261                 pungetc();
12262         }
12263         quoteflag = quotef;
12264         backquotelist = bqlist;
12265         grabstackblock(len);
12266         wordtext = out;
12267         lasttoken = TWORD;
12268         return lasttoken;
12269 /* end of readtoken routine */
12270
12271 /*
12272  * Check to see whether we are at the end of the here document.  When this
12273  * is called, c is set to the first character of the next input line.  If
12274  * we are at the end of the here document, this routine sets the c to PEOF.
12275  */
12276 checkend: {
12277         if (realeofmark(eofmark)) {
12278                 int markloc;
12279                 char *p;
12280
12281 #if ENABLE_ASH_ALIAS
12282                 if (c == PEOA)
12283                         c = pgetc_without_PEOA();
12284 #endif
12285                 if (striptabs) {
12286                         while (c == '\t') {
12287                                 c = pgetc_without_PEOA();
12288                         }
12289                 }
12290
12291                 markloc = out - (char *)stackblock();
12292                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12293                         if (c != *p)
12294                                 goto more_heredoc;
12295
12296                         c = pgetc_without_PEOA();
12297                 }
12298
12299                 if (c == '\n' || c == PEOF) {
12300                         c = PEOF;
12301                         g_parsefile->linno++;
12302                         needprompt = doprompt;
12303                 } else {
12304                         int len_here;
12305
12306  more_heredoc:
12307                         p = (char *)stackblock() + markloc + 1;
12308                         len_here = out - p;
12309
12310                         if (len_here) {
12311                                 len_here -= (c >= PEOF);
12312                                 c = p[-1];
12313
12314                                 if (len_here) {
12315                                         char *str;
12316
12317                                         str = alloca(len_here + 1);
12318                                         *(char *)mempcpy(str, p, len_here) = '\0';
12319
12320                                         pushstring(str, NULL);
12321                                 }
12322                         }
12323                 }
12324
12325                 STADJUST((char *)stackblock() + markloc - out, out);
12326         }
12327         goto checkend_return;
12328 }
12329
12330 /*
12331  * Parse a redirection operator.  The variable "out" points to a string
12332  * specifying the fd to be redirected.  The variable "c" contains the
12333  * first character of the redirection operator.
12334  */
12335 parseredir: {
12336         /* out is already checked to be a valid number or "" */
12337         int fd = (*out == '\0' ? -1 : atoi(out));
12338         union node *np;
12339
12340         np = stzalloc(sizeof(struct nfile));
12341         if (c == '>') {
12342                 np->nfile.fd = 1;
12343                 c = pgetc_eatbnl();
12344                 if (c == '>')
12345                         np->type = NAPPEND;
12346                 else if (c == '|')
12347                         np->type = NCLOBBER;
12348                 else if (c == '&')
12349                         np->type = NTOFD;
12350                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12351                 else {
12352                         np->type = NTO;
12353                         pungetc();
12354                 }
12355         }
12356 #if BASH_REDIR_OUTPUT
12357         else if (c == 0x100 + '>') { /* this flags &> redirection */
12358                 np->nfile.fd = 1;
12359                 pgetc(); /* this is '>', no need to check */
12360                 np->type = NTO2;
12361         }
12362 #endif
12363         else { /* c == '<' */
12364                 /*np->nfile.fd = 0; - stzalloc did it */
12365                 c = pgetc_eatbnl();
12366                 switch (c) {
12367                 case '<':
12368                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12369                                 np = stzalloc(sizeof(struct nhere));
12370                                 /*np->nfile.fd = 0; - stzalloc did it */
12371                         }
12372                         np->type = NHERE;
12373                         heredoc = stzalloc(sizeof(struct heredoc));
12374                         heredoc->here = np;
12375                         c = pgetc_eatbnl();
12376                         if (c == '-') {
12377                                 heredoc->striptabs = 1;
12378                         } else {
12379                                 /*heredoc->striptabs = 0; - stzalloc did it */
12380                                 pungetc();
12381                         }
12382                         break;
12383
12384                 case '&':
12385                         np->type = NFROMFD;
12386                         break;
12387
12388                 case '>':
12389                         np->type = NFROMTO;
12390                         break;
12391
12392                 default:
12393                         np->type = NFROM;
12394                         pungetc();
12395                         break;
12396                 }
12397         }
12398         if (fd >= 0)
12399                 np->nfile.fd = fd;
12400         redirnode = np;
12401         goto parseredir_return;
12402 }
12403
12404 /*
12405  * Parse a substitution.  At this point, we have read the dollar sign
12406  * and nothing else.
12407  */
12408
12409 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12410  * (assuming ascii char codes, as the original implementation did) */
12411 #define is_special(c) \
12412         (((unsigned)(c) - 33 < 32) \
12413                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12414 parsesub: {
12415         unsigned char subtype;
12416         int typeloc;
12417
12418         c = pgetc_eatbnl();
12419         if ((checkkwd & CHKEOFMARK)
12420          || c > 255 /* PEOA or PEOF */
12421          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12422         ) {
12423 #if BASH_DOLLAR_SQUOTE
12424                 if (synstack->syntax != DQSYNTAX && c == '\'')
12425                         bash_dollar_squote = 1;
12426                 else
12427 #endif
12428                         USTPUTC('$', out);
12429                 pungetc();
12430         } else if (c == '(') {
12431                 /* $(command) or $((arith)) */
12432                 if (pgetc_eatbnl() == '(') {
12433 #if ENABLE_FEATURE_SH_MATH
12434                         PARSEARITH();
12435 #else
12436                         raise_error_syntax("support for $((arith)) is disabled");
12437 #endif
12438                 } else {
12439                         pungetc();
12440                         PARSEBACKQNEW();
12441                 }
12442         } else {
12443                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12444                 smalluint newsyn = synstack->syntax;
12445
12446                 USTPUTC(CTLVAR, out);
12447                 typeloc = out - (char *)stackblock();
12448                 STADJUST(1, out);
12449                 subtype = VSNORMAL;
12450                 if (c == '{') {
12451                         c = pgetc_eatbnl();
12452                         subtype = 0;
12453                 }
12454  varname:
12455                 if (is_name(c)) {
12456                         /* $[{[#]]NAME[}] */
12457                         do {
12458                                 STPUTC(c, out);
12459                                 c = pgetc_eatbnl();
12460                         } while (is_in_name(c));
12461                 } else if (isdigit(c)) {
12462                         /* $[{[#]]NUM[}] */
12463                         do {
12464                                 STPUTC(c, out);
12465                                 c = pgetc_eatbnl();
12466                         } while (isdigit(c));
12467                 } else if (c != '}') {
12468                         /* $[{[#]]<specialchar>[}] */
12469                         int cc = c;
12470
12471                         c = pgetc_eatbnl();
12472                         if (!subtype && cc == '#') {
12473                                 subtype = VSLENGTH;
12474                                 if (c == '_' || isalnum(c))
12475                                         goto varname;
12476                                 cc = c;
12477                                 c = pgetc_eatbnl();
12478                                 if (cc == '}' || c != '}') {
12479                                         pungetc();
12480                                         subtype = 0;
12481                                         c = cc;
12482                                         cc = '#';
12483                                 }
12484                         }
12485
12486                         if (!is_special(cc)) {
12487                                 if (subtype == VSLENGTH)
12488                                         subtype = 0;
12489                                 goto badsub;
12490                         }
12491
12492                         USTPUTC(cc, out);
12493                 } else
12494                         goto badsub;
12495
12496                 if (c != '}' && subtype == VSLENGTH) {
12497                         /* ${#VAR didn't end with } */
12498                         goto badsub;
12499                 }
12500
12501                 if (subtype == 0) {
12502                         static const char types[] ALIGN1 = "}-+?=";
12503                         /* ${VAR...} but not $VAR or ${#VAR} */
12504                         /* c == first char after VAR */
12505                         int cc = c;
12506
12507                         switch (c) {
12508                         case ':':
12509                                 c = pgetc_eatbnl();
12510 #if BASH_SUBSTR
12511                                 /* This check is only needed to not misinterpret
12512                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12513                                  * constructs.
12514                                  */
12515                                 if (!strchr(types, c)) {
12516                                         subtype = VSSUBSTR;
12517                                         pungetc();
12518                                         break; /* "goto badsub" is bigger (!) */
12519                                 }
12520 #endif
12521                                 subtype = VSNUL;
12522                                 /*FALLTHROUGH*/
12523                         default: {
12524                                 const char *p = strchr(types, c);
12525                                 if (p == NULL)
12526                                         break;
12527                                 subtype |= p - types + VSNORMAL;
12528                                 break;
12529                         }
12530                         case '%':
12531                         case '#':
12532                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12533                                 c = pgetc_eatbnl();
12534                                 if (c == cc)
12535                                         subtype++;
12536                                 else
12537                                         pungetc();
12538
12539                                 newsyn = BASESYNTAX;
12540                                 break;
12541 #if BASH_PATTERN_SUBST
12542                         case '/':
12543                                 /* ${v/[/]pattern/repl} */
12544 //TODO: encode pattern and repl separately.
12545 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12546 // are broken (should print "ONE")
12547                                 subtype = VSREPLACE;
12548                                 newsyn = BASESYNTAX;
12549                                 c = pgetc_eatbnl();
12550                                 if (c != '/')
12551                                         goto badsub;
12552                                 subtype++; /* VSREPLACEALL */
12553                                 break;
12554 #endif
12555                         }
12556                 } else {
12557  badsub:
12558                         pungetc();
12559                 }
12560
12561                 if (newsyn == ARISYNTAX)
12562                         newsyn = DQSYNTAX;
12563
12564                 if ((newsyn != synstack->syntax || synstack->innerdq)
12565                  && subtype != VSNORMAL
12566                 ) {
12567                         synstack_push(&synstack,
12568                                 synstack->prev ?: alloca(sizeof(*synstack)),
12569                                 newsyn);
12570
12571                         synstack->varpushed = 1;
12572                         synstack->dblquote = newsyn != BASESYNTAX;
12573                 }
12574
12575                 ((unsigned char *)stackblock())[typeloc] = subtype;
12576                 if (subtype != VSNORMAL) {
12577                         synstack->varnest++;
12578                         if (synstack->dblquote)
12579                                 synstack->dqvarnest++;
12580                 }
12581                 STPUTC('=', out);
12582         }
12583         goto parsesub_return;
12584 }
12585
12586 /*
12587  * Called to parse command substitutions.  Newstyle is set if the command
12588  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12589  * list of commands (passed by reference), and savelen is the number of
12590  * characters on the top of the stack which must be preserved.
12591  */
12592 parsebackq: {
12593         struct nodelist **nlpp;
12594         union node *n;
12595         char *str;
12596         size_t savelen;
12597         smallint saveprompt = 0;
12598
12599         str = NULL;
12600         savelen = out - (char *)stackblock();
12601         if (savelen > 0) {
12602                 /*
12603                  * FIXME: this can allocate very large block on stack and SEGV.
12604                  * Example:
12605                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12606                  * allocates 100kb for every command subst. With about
12607                  * a hundred command substitutions stack overflows.
12608                  * With larger prepended string, SEGV happens sooner.
12609                  */
12610                 str = alloca(savelen);
12611                 memcpy(str, stackblock(), savelen);
12612         }
12613
12614         if (oldstyle) {
12615                 /* We must read until the closing backquote, giving special
12616                  * treatment to some slashes, and then push the string and
12617                  * reread it as input, interpreting it normally.
12618                  */
12619                 char *pout;
12620                 size_t psavelen;
12621                 char *pstr;
12622
12623                 STARTSTACKSTR(pout);
12624                 for (;;) {
12625                         int pc;
12626
12627                         setprompt_if(needprompt, 2);
12628                         pc = pgetc_eatbnl();
12629                         switch (pc) {
12630                         case '`':
12631                                 goto done;
12632
12633                         case '\\':
12634                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12635                                 if (pc != '\\' && pc != '`' && pc != '$'
12636                                  && (!synstack->dblquote || pc != '"')
12637                                 ) {
12638                                         STPUTC('\\', pout);
12639                                 }
12640                                 if (pc <= 255 /* not PEOA or PEOF */) {
12641                                         break;
12642                                 }
12643                                 /* fall through */
12644
12645                         case PEOF:
12646                         IF_ASH_ALIAS(case PEOA:)
12647                                 raise_error_syntax("EOF in backquote substitution");
12648
12649                         case '\n':
12650                                 nlnoprompt();
12651                                 break;
12652
12653                         default:
12654                                 break;
12655                         }
12656                         STPUTC(pc, pout);
12657                 }
12658  done:
12659                 STPUTC('\0', pout);
12660                 psavelen = pout - (char *)stackblock();
12661                 if (psavelen > 0) {
12662                         pstr = grabstackstr(pout);
12663                         setinputstring(pstr);
12664                 }
12665         }
12666         nlpp = &bqlist;
12667         while (*nlpp)
12668                 nlpp = &(*nlpp)->next;
12669         *nlpp = stzalloc(sizeof(**nlpp));
12670         /* (*nlpp)->next = NULL; - stzalloc did it */
12671
12672         if (oldstyle) {
12673                 saveprompt = doprompt;
12674                 doprompt = 0;
12675         }
12676
12677         n = list(2);
12678
12679         if (oldstyle)
12680                 doprompt = saveprompt;
12681         else if (readtoken() != TRP)
12682                 raise_error_unexpected_syntax(TRP);
12683
12684         (*nlpp)->n = n;
12685         if (oldstyle) {
12686                 /*
12687                  * Start reading from old file again, ignoring any pushed back
12688                  * tokens left from the backquote parsing
12689                  */
12690                 popfile();
12691                 tokpushback = 0;
12692         }
12693         while (stackblocksize() <= savelen)
12694                 growstackblock();
12695         STARTSTACKSTR(out);
12696         if (str) {
12697                 memcpy(out, str, savelen);
12698                 STADJUST(savelen, out);
12699         }
12700         USTPUTC(CTLBACKQ, out);
12701         if (oldstyle)
12702                 goto parsebackq_oldreturn;
12703         goto parsebackq_newreturn;
12704 }
12705
12706 #if ENABLE_FEATURE_SH_MATH
12707 /*
12708  * Parse an arithmetic expansion (indicate start of one and set state)
12709  */
12710 parsearith: {
12711
12712         synstack_push(&synstack,
12713                         synstack->prev ?: alloca(sizeof(*synstack)),
12714                         ARISYNTAX);
12715         synstack->dblquote = 1;
12716         USTPUTC(CTLARI, out);
12717         goto parsearith_return;
12718 }
12719 #endif
12720 } /* end of readtoken */
12721
12722 /*
12723  * Read the next input token.
12724  * If the token is a word, we set backquotelist to the list of cmds in
12725  *      backquotes.  We set quoteflag to true if any part of the word was
12726  *      quoted.
12727  * If the token is TREDIR, then we set redirnode to a structure containing
12728  *      the redirection.
12729  *
12730  * [Change comment:  here documents and internal procedures]
12731  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12732  *  word parsing code into a separate routine.  In this case, readtoken
12733  *  doesn't need to have any internal procedures, but parseword does.
12734  *  We could also make parseoperator in essence the main routine, and
12735  *  have parseword (readtoken1?) handle both words and redirection.]
12736  */
12737 #define NEW_xxreadtoken
12738 #ifdef NEW_xxreadtoken
12739 /* singles must be first! */
12740 static const char xxreadtoken_chars[7] ALIGN1 = {
12741         '\n', '(', ')', /* singles */
12742         '&', '|', ';',  /* doubles */
12743         0
12744 };
12745
12746 #define xxreadtoken_singles 3
12747 #define xxreadtoken_doubles 3
12748
12749 static const char xxreadtoken_tokens[] ALIGN1 = {
12750         TNL, TLP, TRP,          /* only single occurrence allowed */
12751         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12752         TEOF,                   /* corresponds to trailing nul */
12753         TAND, TOR, TENDCASE     /* if double occurrence */
12754 };
12755
12756 static int
12757 xxreadtoken(void)
12758 {
12759         int c;
12760
12761         if (tokpushback) {
12762                 tokpushback = 0;
12763                 return lasttoken;
12764         }
12765         setprompt_if(needprompt, 2);
12766         for (;;) {                      /* until token or start of word found */
12767                 c = pgetc_eatbnl();
12768                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12769                         continue;
12770
12771                 if (c == '#') {
12772                         while ((c = pgetc()) != '\n' && c != PEOF)
12773                                 continue;
12774                         pungetc();
12775                 } else if (c == '\\') {
12776                         break; /* return readtoken1(...) */
12777                 } else {
12778                         const char *p;
12779
12780                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12781                         if (c != PEOF) {
12782                                 if (c == '\n') {
12783                                         nlnoprompt();
12784                                 }
12785
12786                                 p = strchr(xxreadtoken_chars, c);
12787                                 if (p == NULL)
12788                                         break; /* return readtoken1(...) */
12789
12790                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12791                                         int cc = pgetc_eatbnl();
12792                                         if (cc == c) {    /* double occurrence? */
12793                                                 p += xxreadtoken_doubles + 1;
12794                                         } else {
12795                                                 pungetc();
12796 #if BASH_REDIR_OUTPUT
12797                                                 if (c == '&' && cc == '>') /* &> */
12798                                                         break; /* return readtoken1(...) */
12799 #endif
12800                                         }
12801                                 }
12802                         }
12803                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12804                         return lasttoken;
12805                 }
12806         } /* for (;;) */
12807
12808         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12809 }
12810 #else /* old xxreadtoken */
12811 #define RETURN(token)   return lasttoken = token
12812 static int
12813 xxreadtoken(void)
12814 {
12815         int c;
12816
12817         if (tokpushback) {
12818                 tokpushback = 0;
12819                 return lasttoken;
12820         }
12821         setprompt_if(needprompt, 2);
12822         for (;;) {      /* until token or start of word found */
12823                 c = pgetc_eatbnl();
12824                 switch (c) {
12825                 case ' ': case '\t':
12826                 IF_ASH_ALIAS(case PEOA:)
12827                         continue;
12828                 case '#':
12829                         while ((c = pgetc()) != '\n' && c != PEOF)
12830                                 continue;
12831                         pungetc();
12832                         continue;
12833                 case '\n':
12834                         nlnoprompt();
12835                         RETURN(TNL);
12836                 case PEOF:
12837                         RETURN(TEOF);
12838                 case '&':
12839                         if (pgetc_eatbnl() == '&')
12840                                 RETURN(TAND);
12841                         pungetc();
12842                         RETURN(TBACKGND);
12843                 case '|':
12844                         if (pgetc_eatbnl() == '|')
12845                                 RETURN(TOR);
12846                         pungetc();
12847                         RETURN(TPIPE);
12848                 case ';':
12849                         if (pgetc_eatbnl() == ';')
12850                                 RETURN(TENDCASE);
12851                         pungetc();
12852                         RETURN(TSEMI);
12853                 case '(':
12854                         RETURN(TLP);
12855                 case ')':
12856                         RETURN(TRP);
12857                 }
12858                 break;
12859         }
12860         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12861 #undef RETURN
12862 }
12863 #endif /* old xxreadtoken */
12864
12865 static int
12866 readtoken(void)
12867 {
12868         int t;
12869         int kwd = checkkwd;
12870 #if DEBUG
12871         smallint alreadyseen = tokpushback;
12872 #endif
12873
12874 #if ENABLE_ASH_ALIAS
12875  top:
12876 #endif
12877
12878         t = xxreadtoken();
12879
12880         /*
12881          * eat newlines
12882          */
12883         if (kwd & CHKNL) {
12884                 while (t == TNL) {
12885                         parseheredoc();
12886                         t = xxreadtoken();
12887                 }
12888         }
12889
12890         if (t != TWORD || quoteflag) {
12891                 goto out;
12892         }
12893
12894         /*
12895          * check for keywords
12896          */
12897         if (kwd & CHKKWD) {
12898                 const char *const *pp;
12899
12900                 pp = findkwd(wordtext);
12901                 if (pp) {
12902                         lasttoken = t = pp - tokname_array;
12903                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12904                         goto out;
12905                 }
12906         }
12907
12908         if (checkkwd & CHKALIAS) {
12909 #if ENABLE_ASH_ALIAS
12910                 struct alias *ap;
12911                 ap = lookupalias(wordtext, 1);
12912                 if (ap != NULL) {
12913                         if (*ap->val) {
12914                                 pushstring(ap->val, ap);
12915                         }
12916                         goto top;
12917                 }
12918 #endif
12919         }
12920  out:
12921         checkkwd = 0;
12922 #if DEBUG
12923         if (!alreadyseen)
12924                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12925         else
12926                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12927 #endif
12928         return t;
12929 }
12930
12931 static int
12932 peektoken(void)
12933 {
12934         int t;
12935
12936         t = readtoken();
12937         tokpushback = 1;
12938         return t;
12939 }
12940
12941 /*
12942  * Read and parse a command.  Returns NODE_EOF on end of file.
12943  * (NULL is a valid parse tree indicating a blank line.)
12944  */
12945 static union node *
12946 parsecmd(int interact)
12947 {
12948         tokpushback = 0;
12949         checkkwd = 0;
12950         heredoclist = 0;
12951         doprompt = interact;
12952         setprompt_if(doprompt, doprompt);
12953         needprompt = 0;
12954         return list(1);
12955 }
12956
12957 /*
12958  * Input any here documents.
12959  */
12960 static void
12961 parseheredoc(void)
12962 {
12963         struct heredoc *here;
12964         union node *n;
12965
12966         here = heredoclist;
12967         heredoclist = NULL;
12968
12969         while (here) {
12970                 setprompt_if(needprompt, 2);
12971                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12972                                 here->eofmark, here->striptabs);
12973                 n = stzalloc(sizeof(struct narg));
12974                 n->narg.type = NARG;
12975                 /*n->narg.next = NULL; - stzalloc did it */
12976                 n->narg.text = wordtext;
12977                 n->narg.backquote = backquotelist;
12978                 here->here->nhere.doc = n;
12979                 here = here->next;
12980         }
12981 }
12982
12983
12984 static const char *
12985 expandstr(const char *ps, int syntax_type)
12986 {
12987         union node n;
12988         int saveprompt;
12989
12990         /* XXX Fix (char *) cast. */
12991         setinputstring((char *)ps);
12992
12993         saveprompt = doprompt;
12994         doprompt = 0;
12995
12996         /* readtoken1() might die horribly.
12997          * Try a prompt with syntactically wrong command:
12998          * PS1='$(date "+%H:%M:%S) > '
12999          */
13000         {
13001                 volatile int saveint;
13002                 struct jmploc *volatile savehandler = exception_handler;
13003                 struct jmploc jmploc;
13004                 SAVE_INT(saveint);
13005                 if (setjmp(jmploc.loc) == 0) {
13006                         exception_handler = &jmploc;
13007                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
13008                 }
13009                 exception_handler = savehandler;
13010                 RESTORE_INT(saveint);
13011         }
13012
13013         doprompt = saveprompt;
13014
13015         popfile();
13016
13017         n.narg.type = NARG;
13018         n.narg.next = NULL;
13019         n.narg.text = wordtext;
13020         n.narg.backquote = backquotelist;
13021
13022         expandarg(&n, NULL, EXP_QUOTED);
13023         return stackblock();
13024 }
13025
13026 static inline int
13027 parser_eof(void)
13028 {
13029         return tokpushback && lasttoken == TEOF;
13030 }
13031
13032 /*
13033  * Execute a command or commands contained in a string.
13034  */
13035 static int
13036 evalstring(char *s, int flags)
13037 {
13038         struct jmploc *volatile savehandler;
13039         struct jmploc jmploc;
13040         int ex;
13041
13042         union node *n;
13043         struct stackmark smark;
13044         int status;
13045
13046         s = sstrdup(s);
13047         setinputstring(s);
13048         setstackmark(&smark);
13049
13050         status = 0;
13051         /* On exception inside execution loop, we must popfile().
13052          * Try interactively:
13053          *      readonly a=a
13054          *      command eval "a=b"  # throws "is read only" error
13055          * "command BLTIN" is not supposed to abort (even in non-interactive use).
13056          * But if we skip popfile(), we hit EOF in eval's string, and exit.
13057          */
13058         savehandler = exception_handler;
13059         ex = setjmp(jmploc.loc);
13060         if (ex)
13061                 goto out;
13062         exception_handler = &jmploc;
13063
13064         while ((n = parsecmd(0)) != NODE_EOF) {
13065                 int i;
13066
13067                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13068                 if (n)
13069                         status = i;
13070                 popstackmark(&smark);
13071                 if (evalskip)
13072                         break;
13073         }
13074  out:
13075         popstackmark(&smark);
13076         popfile();
13077         stunalloc(s);
13078
13079         exception_handler = savehandler;
13080         if (ex)
13081                 longjmp(exception_handler->loc, ex);
13082
13083         return status;
13084 }
13085
13086 /*
13087  * The eval command.
13088  */
13089 static int FAST_FUNC
13090 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13091 {
13092         char *p;
13093         char *concat;
13094
13095         if (argv[1]) {
13096                 p = argv[1];
13097                 argv += 2;
13098                 if (argv[0]) {
13099                         STARTSTACKSTR(concat);
13100                         for (;;) {
13101                                 concat = stack_putstr(p, concat);
13102                                 p = *argv++;
13103                                 if (p == NULL)
13104                                         break;
13105                                 STPUTC(' ', concat);
13106                         }
13107                         STPUTC('\0', concat);
13108                         p = grabstackstr(concat);
13109                 }
13110                 return evalstring(p, flags & EV_TESTED);
13111         }
13112         return 0;
13113 }
13114
13115 /*
13116  * Read and execute commands.
13117  * "Top" is nonzero for the top level command loop;
13118  * it turns on prompting if the shell is interactive.
13119  */
13120 static int
13121 cmdloop(int top)
13122 {
13123         union node *n;
13124         struct stackmark smark;
13125         int inter;
13126         int status = 0;
13127         int numeof = 0;
13128
13129         TRACE(("cmdloop(%d) called\n", top));
13130         for (;;) {
13131                 int skip;
13132
13133                 setstackmark(&smark);
13134 #if JOBS
13135                 if (doing_jobctl)
13136                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13137 #endif
13138                 inter = 0;
13139                 if (iflag && top) {
13140                         inter++;
13141                         chkmail();
13142                 }
13143                 n = parsecmd(inter);
13144 #if DEBUG
13145                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13146                         showtree(n);
13147 #endif
13148                 if (n == NODE_EOF) {
13149                         if (!top || numeof >= 50)
13150                                 break;
13151                         if (!stoppedjobs()) {
13152                                 if (!Iflag)
13153                                         break;
13154                                 out2str("\nUse \"exit\" to leave shell.\n");
13155                         }
13156                         numeof++;
13157                 } else if (nflag == 0) {
13158                         int i;
13159
13160                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13161                         job_warning >>= 1;
13162                         numeof = 0;
13163                         i = evaltree(n, 0);
13164                         if (n)
13165                                 status = i;
13166                 }
13167                 popstackmark(&smark);
13168                 skip = evalskip;
13169
13170                 if (skip) {
13171                         evalskip &= ~SKIPFUNC;
13172                         break;
13173                 }
13174         }
13175         return status;
13176 }
13177
13178 /*
13179  * Take commands from a file.  To be compatible we should do a path
13180  * search for the file, which is necessary to find sub-commands.
13181  */
13182 static char *
13183 find_dot_file(char *name)
13184 {
13185         char *fullname;
13186         const char *path = pathval();
13187         struct stat statb;
13188
13189         /* don't try this for absolute or relative paths */
13190         if (strchr(name, '/'))
13191                 return name;
13192
13193         while ((fullname = path_advance(&path, name)) != NULL) {
13194                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13195                         /*
13196                          * Don't bother freeing here, since it will
13197                          * be freed by the caller.
13198                          */
13199                         return fullname;
13200                 }
13201                 if (fullname != name)
13202                         stunalloc(fullname);
13203         }
13204         /* not found in PATH */
13205
13206 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13207         return name;
13208 #else
13209         ash_msg_and_raise_error("%s: not found", name);
13210         /* NOTREACHED */
13211 #endif
13212 }
13213
13214 static int FAST_FUNC
13215 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13216 {
13217         /* "false; . empty_file; echo $?" should print 0, not 1: */
13218         int status = 0;
13219         char *fullname;
13220         char **argv;
13221         char *args_need_save;
13222         volatile struct shparam saveparam;
13223
13224 //???
13225 //      struct strlist *sp;
13226 //      for (sp = cmdenviron; sp; sp = sp->next)
13227 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13228
13229         nextopt(nullstr); /* handle possible "--" */
13230         argv = argptr;
13231
13232         if (!argv[0]) {
13233                 /* bash says: "bash: .: filename argument required" */
13234                 return 2; /* bash compat */
13235         }
13236
13237         /* This aborts if file isn't found, which is POSIXly correct.
13238          * bash returns exitcode 1 instead.
13239          */
13240         fullname = find_dot_file(argv[0]);
13241         argv++;
13242         args_need_save = argv[0];
13243         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13244                 int argc;
13245                 saveparam = shellparam;
13246                 shellparam.malloced = 0;
13247                 argc = 1;
13248                 while (argv[argc])
13249                         argc++;
13250                 shellparam.nparam = argc;
13251                 shellparam.p = argv;
13252         };
13253
13254         /* This aborts if file can't be opened, which is POSIXly correct.
13255          * bash returns exitcode 1 instead.
13256          */
13257         setinputfile(fullname, INPUT_PUSH_FILE);
13258         commandname = fullname;
13259         status = cmdloop(0);
13260         popfile();
13261
13262         if (args_need_save) {
13263                 freeparam(&shellparam);
13264                 shellparam = saveparam;
13265         };
13266
13267         return status;
13268 }
13269
13270 static int FAST_FUNC
13271 exitcmd(int argc UNUSED_PARAM, char **argv)
13272 {
13273         if (stoppedjobs())
13274                 return 0;
13275         if (argv[1])
13276                 exitstatus = number(argv[1]);
13277         raise_exception(EXEXIT);
13278         /* NOTREACHED */
13279 }
13280
13281 /*
13282  * Read a file containing shell functions.
13283  */
13284 static void
13285 readcmdfile(char *name)
13286 {
13287         setinputfile(name, INPUT_PUSH_FILE);
13288         cmdloop(0);
13289         popfile();
13290 }
13291
13292
13293 /* ============ find_command inplementation */
13294
13295 /*
13296  * Resolve a command name.  If you change this routine, you may have to
13297  * change the shellexec routine as well.
13298  */
13299 static void
13300 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13301 {
13302         struct tblentry *cmdp;
13303         int idx;
13304         int prev;
13305         char *fullname;
13306         struct stat statb;
13307         int e;
13308         int updatetbl;
13309         struct builtincmd *bcmd;
13310
13311         /* If name contains a slash, don't use PATH or hash table */
13312         if (strchr(name, '/') != NULL) {
13313                 entry->u.index = -1;
13314                 if (act & DO_ABS) {
13315                         while (stat(name, &statb) < 0) {
13316 #ifdef SYSV
13317                                 if (errno == EINTR)
13318                                         continue;
13319 #endif
13320                                 entry->cmdtype = CMDUNKNOWN;
13321                                 return;
13322                         }
13323                 }
13324                 entry->cmdtype = CMDNORMAL;
13325                 return;
13326         }
13327
13328 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13329
13330         updatetbl = (path == pathval());
13331         if (!updatetbl) {
13332                 act |= DO_ALTPATH;
13333                 if (strstr(path, "%builtin") != NULL)
13334                         act |= DO_ALTBLTIN;
13335         }
13336
13337         /* If name is in the table, check answer will be ok */
13338         cmdp = cmdlookup(name, 0);
13339         if (cmdp != NULL) {
13340                 int bit;
13341
13342                 switch (cmdp->cmdtype) {
13343                 default:
13344 #if DEBUG
13345                         abort();
13346 #endif
13347                 case CMDNORMAL:
13348                         bit = DO_ALTPATH;
13349                         break;
13350                 case CMDFUNCTION:
13351                         bit = DO_NOFUNC;
13352                         break;
13353                 case CMDBUILTIN:
13354                         bit = DO_ALTBLTIN;
13355                         break;
13356                 }
13357                 if (act & bit) {
13358                         updatetbl = 0;
13359                         cmdp = NULL;
13360                 } else if (cmdp->rehash == 0)
13361                         /* if not invalidated by cd, we're done */
13362                         goto success;
13363         }
13364
13365         /* If %builtin not in path, check for builtin next */
13366         bcmd = find_builtin(name);
13367         if (bcmd) {
13368                 if (IS_BUILTIN_REGULAR(bcmd))
13369                         goto builtin_success;
13370                 if (act & DO_ALTPATH) {
13371                         if (!(act & DO_ALTBLTIN))
13372                                 goto builtin_success;
13373                 } else if (builtinloc <= 0) {
13374                         goto builtin_success;
13375                 }
13376         }
13377
13378 #if ENABLE_FEATURE_SH_STANDALONE
13379         {
13380                 int applet_no = find_applet_by_name(name);
13381 # if NUM_SCRIPTS > 0
13382                 if (applet_no < 0)
13383                         /* embedded script indices are offset by NUM_APPLETS */
13384                         applet_no = NUM_APPLETS + find_script_by_name(name);
13385 # endif
13386                 if (applet_no >= 0) {
13387                         entry->cmdtype = CMDNORMAL;
13388                         entry->u.index = -2 - applet_no;
13389                         return;
13390                 }
13391         }
13392 #endif
13393
13394         /* We have to search path. */
13395         prev = -1;              /* where to start */
13396         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13397                 if (cmdp->cmdtype == CMDBUILTIN)
13398                         prev = builtinloc;
13399                 else
13400                         prev = cmdp->param.index;
13401         }
13402
13403         e = ENOENT;
13404         idx = -1;
13405  loop:
13406         while ((fullname = path_advance(&path, name)) != NULL) {
13407                 stunalloc(fullname);
13408                 /* NB: code below will still use fullname
13409                  * despite it being "unallocated" */
13410                 idx++;
13411                 if (pathopt) {
13412                         if (prefix(pathopt, "builtin")) {
13413                                 if (bcmd)
13414                                         goto builtin_success;
13415                                 continue;
13416                         }
13417                         if ((act & DO_NOFUNC)
13418                          || !prefix(pathopt, "func")
13419                         ) {     /* ignore unimplemented options */
13420                                 continue;
13421                         }
13422                 }
13423                 /* if rehash, don't redo absolute path names */
13424                 if (fullname[0] == '/' && idx <= prev) {
13425                         if (idx < prev)
13426                                 continue;
13427                         TRACE(("searchexec \"%s\": no change\n", name));
13428                         goto success;
13429                 }
13430                 while (stat(fullname, &statb) < 0) {
13431 #ifdef SYSV
13432                         if (errno == EINTR)
13433                                 continue;
13434 #endif
13435                         if (errno != ENOENT && errno != ENOTDIR)
13436                                 e = errno;
13437                         goto loop;
13438                 }
13439                 e = EACCES;     /* if we fail, this will be the error */
13440                 if (!S_ISREG(statb.st_mode))
13441                         continue;
13442                 if (pathopt) {          /* this is a %func directory */
13443                         stalloc(strlen(fullname) + 1);
13444                         /* NB: stalloc will return space pointed by fullname
13445                          * (because we don't have any intervening allocations
13446                          * between stunalloc above and this stalloc) */
13447                         readcmdfile(fullname);
13448                         cmdp = cmdlookup(name, 0);
13449                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13450                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13451                         stunalloc(fullname);
13452                         goto success;
13453                 }
13454                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13455                 if (!updatetbl) {
13456                         entry->cmdtype = CMDNORMAL;
13457                         entry->u.index = idx;
13458                         return;
13459                 }
13460                 INT_OFF;
13461                 cmdp = cmdlookup(name, 1);
13462                 cmdp->cmdtype = CMDNORMAL;
13463                 cmdp->param.index = idx;
13464                 INT_ON;
13465                 goto success;
13466         }
13467
13468         /* We failed.  If there was an entry for this command, delete it */
13469         if (cmdp && updatetbl)
13470                 delete_cmd_entry();
13471         if (act & DO_ERR) {
13472 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13473                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13474                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13475                         char *argv[3];
13476                         argv[0] = (char*) "command_not_found_handle";
13477                         argv[1] = name;
13478                         argv[2] = NULL;
13479                         evalfun(hookp->param.func, 2, argv, 0);
13480                         entry->cmdtype = CMDUNKNOWN;
13481                         return;
13482                 }
13483 #endif
13484                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13485         }
13486         entry->cmdtype = CMDUNKNOWN;
13487         return;
13488
13489  builtin_success:
13490         if (!updatetbl) {
13491                 entry->cmdtype = CMDBUILTIN;
13492                 entry->u.cmd = bcmd;
13493                 return;
13494         }
13495         INT_OFF;
13496         cmdp = cmdlookup(name, 1);
13497         cmdp->cmdtype = CMDBUILTIN;
13498         cmdp->param.cmd = bcmd;
13499         INT_ON;
13500  success:
13501         cmdp->rehash = 0;
13502         entry->cmdtype = cmdp->cmdtype;
13503         entry->u = cmdp->param;
13504 }
13505
13506
13507 /*
13508  * The trap builtin.
13509  */
13510 static int FAST_FUNC
13511 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13512 {
13513         char *action;
13514         char **ap;
13515         int signo, exitcode;
13516
13517         nextopt(nullstr);
13518         ap = argptr;
13519         if (!*ap) {
13520                 for (signo = 0; signo < NSIG; signo++) {
13521                         char *tr = trap_ptr[signo];
13522                         if (tr) {
13523                                 /* note: bash adds "SIG", but only if invoked
13524                                  * as "bash". If called as "sh", or if set -o posix,
13525                                  * then it prints short signal names.
13526                                  * We are printing short names: */
13527                                 out1fmt("trap -- %s %s\n",
13528                                                 single_quote(tr),
13529                                                 get_signame(signo));
13530                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13531                  * In this case, we will exit very soon, no need to free(). */
13532                                 /* if (trap_ptr != trap && tp[0]) */
13533                                 /*      free(tr); */
13534                         }
13535                 }
13536                 /*
13537                 if (trap_ptr != trap) {
13538                         free(trap_ptr);
13539                         trap_ptr = trap;
13540                 }
13541                 */
13542                 return 0;
13543         }
13544
13545         /* Why the second check?
13546          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13547          * In this case, NUM is signal no, not an action.
13548          */
13549         action = NULL;
13550         if (ap[1] && !is_number(ap[0]))
13551                 action = *ap++;
13552
13553         exitcode = 0;
13554         while (*ap) {
13555                 signo = get_signum(*ap);
13556                 if (signo < 0) {
13557                         /* Mimic bash message exactly */
13558                         ash_msg("%s: invalid signal specification", *ap);
13559                         exitcode = 1;
13560                         goto next;
13561                 }
13562                 INT_OFF;
13563                 if (action) {
13564                         if (LONE_DASH(action))
13565                                 action = NULL;
13566                         else {
13567                                 if (action[0]) /* not NULL and not "" and not "-" */
13568                                         may_have_traps = 1;
13569                                 action = ckstrdup(action);
13570                         }
13571                 }
13572                 free(trap[signo]);
13573                 trap[signo] = action;
13574                 if (signo != 0)
13575                         setsignal(signo);
13576                 INT_ON;
13577  next:
13578                 ap++;
13579         }
13580         return exitcode;
13581 }
13582
13583
13584 /* ============ Builtins */
13585
13586 #if ENABLE_ASH_HELP
13587 static int FAST_FUNC
13588 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13589 {
13590         unsigned col;
13591         unsigned i;
13592
13593         out1fmt(
13594                 "Built-in commands:\n"
13595                 "------------------\n");
13596         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13597                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13598                                         builtintab[i].name + 1);
13599                 if (col > 60) {
13600                         out1fmt("\n");
13601                         col = 0;
13602                 }
13603         }
13604 # if ENABLE_FEATURE_SH_STANDALONE
13605         {
13606                 const char *a = applet_names;
13607                 while (*a) {
13608                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13609                         if (col > 60) {
13610                                 out1fmt("\n");
13611                                 col = 0;
13612                         }
13613                         while (*a++ != '\0')
13614                                 continue;
13615                 }
13616         }
13617 # endif
13618         newline_and_flush(stdout);
13619         return EXIT_SUCCESS;
13620 }
13621 #endif
13622
13623 #if MAX_HISTORY
13624 static int FAST_FUNC
13625 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13626 {
13627         show_history(line_input_state);
13628         return EXIT_SUCCESS;
13629 }
13630 #endif
13631
13632 /*
13633  * The export and readonly commands.
13634  */
13635 static int FAST_FUNC
13636 exportcmd(int argc UNUSED_PARAM, char **argv)
13637 {
13638         struct var *vp;
13639         char *name;
13640         const char *p;
13641         char **aptr;
13642         char opt;
13643         int flag;
13644         int flag_off;
13645
13646         /* "readonly" in bash accepts, but ignores -n.
13647          * We do the same: it saves a conditional in nextopt's param.
13648          */
13649         flag_off = 0;
13650         while ((opt = nextopt("np")) != '\0') {
13651                 if (opt == 'n')
13652                         flag_off = VEXPORT;
13653         }
13654         flag = VEXPORT;
13655         if (argv[0][0] == 'r') {
13656                 flag = VREADONLY;
13657                 flag_off = 0; /* readonly ignores -n */
13658         }
13659         flag_off = ~flag_off;
13660
13661         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13662         {
13663                 aptr = argptr;
13664                 name = *aptr;
13665                 if (name) {
13666                         do {
13667                                 p = strchr(name, '=');
13668                                 if (p != NULL) {
13669                                         p++;
13670                                 } else {
13671                                         vp = *findvar(hashvar(name), name);
13672                                         if (vp) {
13673                                                 vp->flags = ((vp->flags | flag) & flag_off);
13674                                                 continue;
13675                                         }
13676                                 }
13677                                 setvar(name, p, (flag & flag_off));
13678                         } while ((name = *++aptr) != NULL);
13679                         return 0;
13680                 }
13681         }
13682
13683         /* No arguments. Show the list of exported or readonly vars.
13684          * -n is ignored.
13685          */
13686         showvars(argv[0], flag, 0);
13687         return 0;
13688 }
13689
13690 /*
13691  * Delete a function if it exists.
13692  */
13693 static void
13694 unsetfunc(const char *name)
13695 {
13696         struct tblentry *cmdp;
13697
13698         cmdp = cmdlookup(name, 0);
13699         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13700                 delete_cmd_entry();
13701 }
13702
13703 /*
13704  * The unset builtin command.  We unset the function before we unset the
13705  * variable to allow a function to be unset when there is a readonly variable
13706  * with the same name.
13707  */
13708 static int FAST_FUNC
13709 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13710 {
13711         char **ap;
13712         int i;
13713         int flag = 0;
13714
13715         while ((i = nextopt("vf")) != 0) {
13716                 flag = i;
13717         }
13718
13719         for (ap = argptr; *ap; ap++) {
13720                 if (flag != 'f') {
13721                         unsetvar(*ap);
13722                         continue;
13723                 }
13724                 if (flag != 'v')
13725                         unsetfunc(*ap);
13726         }
13727         return 0;
13728 }
13729
13730 static const unsigned char timescmd_str[] ALIGN1 = {
13731         ' ',  offsetof(struct tms, tms_utime),
13732         '\n', offsetof(struct tms, tms_stime),
13733         ' ',  offsetof(struct tms, tms_cutime),
13734         '\n', offsetof(struct tms, tms_cstime),
13735         0
13736 };
13737 static int FAST_FUNC
13738 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13739 {
13740         unsigned clk_tck;
13741         const unsigned char *p;
13742         struct tms buf;
13743
13744         clk_tck = bb_clk_tck();
13745
13746         times(&buf);
13747         p = timescmd_str;
13748         do {
13749                 unsigned sec, frac;
13750                 unsigned long t;
13751                 t = *(clock_t *)(((char *) &buf) + p[1]);
13752                 sec = t / clk_tck;
13753                 frac = t % clk_tck;
13754                 out1fmt("%um%u.%03us%c",
13755                         sec / 60, sec % 60,
13756                         (frac * 1000) / clk_tck,
13757                         p[0]);
13758                 p += 2;
13759         } while (*p);
13760
13761         return 0;
13762 }
13763
13764 #if ENABLE_FEATURE_SH_MATH
13765 /*
13766  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13767  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13768  *
13769  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13770  */
13771 static int FAST_FUNC
13772 letcmd(int argc UNUSED_PARAM, char **argv)
13773 {
13774         arith_t i;
13775
13776         argv++;
13777         if (!*argv)
13778                 ash_msg_and_raise_error("expression expected");
13779         do {
13780                 i = ash_arith(*argv);
13781         } while (*++argv);
13782
13783         return !i;
13784 }
13785 #endif
13786
13787 /*
13788  * The read builtin. Options:
13789  *      -r              Do not interpret '\' specially
13790  *      -s              Turn off echo (tty only)
13791  *      -n NCHARS       Read NCHARS max
13792  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13793  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13794  *      -u FD           Read from given FD instead of fd 0
13795  *      -d DELIM        End on DELIM char, not newline
13796  * This uses unbuffered input, which may be avoidable in some cases.
13797  * TODO: bash also has:
13798  *      -a ARRAY        Read into array[0],[1],etc
13799  *      -e              Use line editing (tty only)
13800  */
13801 static int FAST_FUNC
13802 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13803 {
13804         struct builtin_read_params params;
13805         const char *r;
13806         int i;
13807
13808         memset(&params, 0, sizeof(params));
13809
13810         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13811                 switch (i) {
13812                 case 'p':
13813                         params.opt_p = optionarg;
13814                         break;
13815                 case 'n':
13816                         params.opt_n = optionarg;
13817                         break;
13818                 case 's':
13819                         params.read_flags |= BUILTIN_READ_SILENT;
13820                         break;
13821                 case 't':
13822                         params.opt_t = optionarg;
13823                         break;
13824                 case 'r':
13825                         params.read_flags |= BUILTIN_READ_RAW;
13826                         break;
13827                 case 'u':
13828                         params.opt_u = optionarg;
13829                         break;
13830 #if BASH_READ_D
13831                 case 'd':
13832                         params.opt_d = optionarg;
13833                         break;
13834 #endif
13835                 default:
13836                         break;
13837                 }
13838         }
13839
13840         params.argv = argptr;
13841         params.setvar = setvar0;
13842         params.ifs = bltinlookup("IFS"); /* can be NULL */
13843
13844         /* "read -s" needs to save/restore termios, can't allow ^C
13845          * to jump out of it.
13846          */
13847  again:
13848         INT_OFF;
13849         r = shell_builtin_read(&params);
13850         INT_ON;
13851
13852         if ((uintptr_t)r == 1 && errno == EINTR) {
13853                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13854                  * Correct behavior is to not exit "read"
13855                  */
13856                 if (pending_sig == 0)
13857                         goto again;
13858         }
13859
13860         if ((uintptr_t)r > 1)
13861                 ash_msg_and_raise_error(r);
13862
13863         return (uintptr_t)r;
13864 }
13865
13866 static int FAST_FUNC
13867 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13868 {
13869         static const char permuser[3] ALIGN1 = "ogu";
13870
13871         mode_t mask;
13872         int symbolic_mode = 0;
13873
13874         while (nextopt("S") != '\0') {
13875                 symbolic_mode = 1;
13876         }
13877
13878         INT_OFF;
13879         mask = umask(0);
13880         umask(mask);
13881         INT_ON;
13882
13883         if (*argptr == NULL) {
13884                 if (symbolic_mode) {
13885                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13886                         char *p = buf;
13887                         int i;
13888
13889                         i = 2;
13890                         for (;;) {
13891                                 *p++ = ',';
13892                                 *p++ = permuser[i];
13893                                 *p++ = '=';
13894                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13895                                 if (!(mask & 0400)) *p++ = 'r';
13896                                 if (!(mask & 0200)) *p++ = 'w';
13897                                 if (!(mask & 0100)) *p++ = 'x';
13898                                 mask <<= 3;
13899                                 if (--i < 0)
13900                                         break;
13901                         }
13902                         *p = '\0';
13903                         puts(buf + 1);
13904                 } else {
13905                         out1fmt("%04o\n", mask);
13906                 }
13907         } else {
13908                 char *modestr = *argptr;
13909                 /* numeric umasks are taken as-is */
13910                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13911                 if (!isdigit(modestr[0]))
13912                         mask ^= 0777;
13913                 mask = bb_parse_mode(modestr, mask);
13914                 if ((unsigned)mask > 0777) {
13915                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13916                 }
13917                 if (!isdigit(modestr[0]))
13918                         mask ^= 0777;
13919                 umask(mask);
13920         }
13921         return 0;
13922 }
13923
13924 static int FAST_FUNC
13925 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13926 {
13927         return shell_builtin_ulimit(argv);
13928 }
13929
13930 /* ============ main() and helpers */
13931
13932 /*
13933  * Called to exit the shell.
13934  */
13935 static void
13936 exitshell(void)
13937 {
13938         struct jmploc loc;
13939         char *p;
13940         int status;
13941
13942 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13943         save_history(line_input_state);
13944 #endif
13945         status = exitstatus;
13946         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13947         if (setjmp(loc.loc)) {
13948                 if (exception_type == EXEXIT)
13949                         status = exitstatus;
13950                 goto out;
13951         }
13952         exception_handler = &loc;
13953         p = trap[0];
13954         if (p) {
13955                 trap[0] = NULL;
13956                 evalskip = 0;
13957                 evalstring(p, 0);
13958                 /*free(p); - we'll exit soon */
13959         }
13960  out:
13961         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13962          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13963          */
13964         setjobctl(0);
13965         flush_stdout_stderr();
13966         _exit(status);
13967         /* NOTREACHED */
13968 }
13969
13970 /* Don't inline: conserve stack of caller from having our locals too */
13971 static NOINLINE void
13972 init(void)
13973 {
13974         /* we will never free this */
13975         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13976         basepf.linno = 1;
13977
13978         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13979         setsignal(SIGCHLD);
13980
13981         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13982          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13983          */
13984         signal(SIGHUP, SIG_DFL);
13985
13986         {
13987                 char **envp;
13988                 const char *p;
13989
13990                 initvar();
13991                 for (envp = environ; envp && *envp; envp++) {
13992 /* Used to have
13993  *                      p = endofname(*envp);
13994  *                      if (p != *envp && *p == '=') {
13995  * here to weed out badly-named variables, but this breaks
13996  * scenarios where people do want them passed to children:
13997  * import os
13998  * os.environ["test-test"]="test"
13999  * if os.fork() == 0:
14000  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
14001  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
14002  */
14003                         if (strchr(*envp, '=')) {
14004                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
14005                         }
14006                 }
14007
14008                 setvareq((char*)defifsvar, VTEXTFIXED);
14009                 setvareq((char*)defoptindvar, VTEXTFIXED);
14010
14011                 setvar0("PPID", utoa(getppid()));
14012 #if BASH_SHLVL_VAR
14013                 p = lookupvar("SHLVL");
14014                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
14015 #endif
14016 #if BASH_HOSTNAME_VAR
14017                 if (!lookupvar("HOSTNAME")) {
14018                         struct utsname uts;
14019                         uname(&uts);
14020                         setvar0("HOSTNAME", uts.nodename);
14021                 }
14022 #endif
14023                 p = lookupvar("PWD");
14024                 if (p) {
14025                         struct stat st1, st2;
14026                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
14027                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
14028                         ) {
14029                                 p = NULL;
14030                         }
14031                 }
14032                 setpwd(p, 0);
14033         }
14034 }
14035
14036
14037 //usage:#define ash_trivial_usage
14038 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
14039 //usage:#define ash_full_usage "\n\n"
14040 //usage:        "Unix shell interpreter"
14041
14042 /*
14043  * Process the shell command line arguments.
14044  */
14045 static int
14046 procargs(char **argv)
14047 {
14048         int i;
14049         const char *xminusc;
14050         char **xargv;
14051         int login_sh;
14052
14053         xargv = argv;
14054         login_sh = xargv[0] && xargv[0][0] == '-';
14055 #if NUM_SCRIPTS > 0
14056         if (minusc)
14057                 goto setarg0;
14058 #endif
14059         arg0 = xargv[0];
14060         /* if (xargv[0]) - mmm, this is always true! */
14061                 xargv++;
14062         argptr = xargv;
14063         for (i = 0; i < NOPTS; i++)
14064                 optlist[i] = 2;
14065         if (options(/*cmdline:*/ 1, &login_sh)) {
14066                 /* it already printed err message */
14067                 raise_exception(EXERROR);
14068         }
14069         xargv = argptr;
14070         xminusc = minusc;
14071         if (*xargv == NULL) {
14072                 if (xminusc)
14073                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
14074                 sflag = 1;
14075         }
14076         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
14077                 iflag = 1;
14078         if (mflag == 2)
14079                 mflag = iflag;
14080         for (i = 0; i < NOPTS; i++)
14081                 if (optlist[i] == 2)
14082                         optlist[i] = 0;
14083 #if DEBUG == 2
14084         debug = 1;
14085 #endif
14086         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14087         if (xminusc) {
14088                 minusc = *xargv++;
14089                 if (*xargv)
14090                         goto setarg0;
14091         } else if (!sflag) {
14092                 setinputfile(*xargv, 0);
14093  setarg0:
14094                 arg0 = *xargv++;
14095                 commandname = arg0;
14096         }
14097
14098         shellparam.p = xargv;
14099 #if ENABLE_ASH_GETOPTS
14100         shellparam.optind = 1;
14101         shellparam.optoff = -1;
14102 #endif
14103         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14104         while (*xargv) {
14105                 shellparam.nparam++;
14106                 xargv++;
14107         }
14108         optschanged();
14109
14110         return login_sh;
14111 }
14112
14113 /*
14114  * Read /etc/profile, ~/.profile, $ENV.
14115  */
14116 static void
14117 read_profile(const char *name)
14118 {
14119         name = expandstr(name, DQSYNTAX);
14120         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14121                 return;
14122         cmdloop(0);
14123         popfile();
14124 }
14125
14126 /*
14127  * This routine is called when an error or an interrupt occurs in an
14128  * interactive shell and control is returned to the main command loop.
14129  * (In dash, this function is auto-generated by build machinery).
14130  */
14131 static void
14132 reset(void)
14133 {
14134         /* from eval.c: */
14135         evalskip = 0;
14136         loopnest = 0;
14137
14138         /* from expand.c: */
14139         ifsfree();
14140
14141         /* from input.c: */
14142         g_parsefile->left_in_buffer = 0;
14143         g_parsefile->left_in_line = 0;      /* clear input buffer */
14144         popallfiles();
14145
14146         /* from redir.c: */
14147         unwindredir(NULL);
14148
14149         /* from var.c: */
14150         unwindlocalvars(NULL);
14151 }
14152
14153 #if PROFILE
14154 static short profile_buf[16384];
14155 extern int etext();
14156 #endif
14157
14158 /*
14159  * Main routine.  We initialize things, parse the arguments, execute
14160  * profiles if we're a login shell, and then call cmdloop to execute
14161  * commands.  The setjmp call sets up the location to jump to when an
14162  * exception occurs.  When an exception occurs the variable "state"
14163  * is used to figure out how far we had gotten.
14164  */
14165 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14166 #if NUM_SCRIPTS > 0
14167 int ash_main(int argc, char **argv)
14168 #else
14169 int ash_main(int argc UNUSED_PARAM, char **argv)
14170 #endif
14171 /* note: 'argc' is used only if embedded scripts are enabled */
14172 {
14173         volatile smallint state;
14174         struct jmploc jmploc;
14175         struct stackmark smark;
14176         int login_sh;
14177
14178         /* Initialize global data */
14179         INIT_G_misc();
14180         INIT_G_memstack();
14181         INIT_G_var();
14182 #if ENABLE_ASH_ALIAS
14183         INIT_G_alias();
14184 #endif
14185         INIT_G_cmdtable();
14186
14187 #if PROFILE
14188         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14189 #endif
14190
14191 #if ENABLE_FEATURE_EDITING
14192         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14193 #endif
14194         state = 0;
14195         if (setjmp(jmploc.loc)) {
14196                 smallint e;
14197                 smallint s;
14198
14199                 reset();
14200
14201                 e = exception_type;
14202                 s = state;
14203                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14204                         exitshell();
14205                 }
14206                 if (e == EXINT) {
14207                         newline_and_flush(stderr);
14208                 }
14209
14210                 popstackmark(&smark);
14211                 FORCE_INT_ON; /* enable interrupts */
14212                 if (s == 1)
14213                         goto state1;
14214                 if (s == 2)
14215                         goto state2;
14216                 if (s == 3)
14217                         goto state3;
14218                 goto state4;
14219         }
14220         exception_handler = &jmploc;
14221         rootpid = getpid();
14222
14223         init();
14224         setstackmark(&smark);
14225
14226 #if NUM_SCRIPTS > 0
14227         if (argc < 0)
14228                 /* Non-NULL minusc tells procargs that an embedded script is being run */
14229                 minusc = get_script_content(-argc - 1);
14230 #endif
14231         login_sh = procargs(argv);
14232 #if DEBUG
14233         TRACE(("Shell args: "));
14234         trace_puts_args(argv);
14235 #endif
14236
14237         if (login_sh) {
14238                 const char *hp;
14239
14240                 state = 1;
14241                 read_profile("/etc/profile");
14242  state1:
14243                 state = 2;
14244                 hp = lookupvar("HOME");
14245                 if (hp)
14246                         read_profile("$HOME/.profile");
14247         }
14248  state2:
14249         state = 3;
14250         if (
14251 #ifndef linux
14252          getuid() == geteuid() && getgid() == getegid() &&
14253 #endif
14254          iflag
14255         ) {
14256                 const char *shinit = lookupvar("ENV");
14257                 if (shinit != NULL && *shinit != '\0')
14258                         read_profile(shinit);
14259         }
14260         popstackmark(&smark);
14261  state3:
14262         state = 4;
14263         if (minusc) {
14264                 /* evalstring pushes parsefile stack.
14265                  * Ensure we don't falsely claim that 0 (stdin)
14266                  * is one of stacked source fds.
14267                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14268                 // if (!sflag) g_parsefile->pf_fd = -1;
14269                 // ^^ not necessary since now we special-case fd 0
14270                 // in save_fd_on_redirect()
14271                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14272         }
14273
14274         if (sflag || minusc == NULL) {
14275 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14276                 if (iflag) {
14277                         const char *hp = lookupvar("HISTFILE");
14278                         if (!hp) {
14279                                 hp = lookupvar("HOME");
14280                                 if (hp) {
14281                                         INT_OFF;
14282                                         hp = concat_path_file(hp, ".ash_history");
14283                                         setvar0("HISTFILE", hp);
14284                                         free((char*)hp);
14285                                         INT_ON;
14286                                         hp = lookupvar("HISTFILE");
14287                                 }
14288                         }
14289                         if (hp)
14290                                 line_input_state->hist_file = hp;
14291 # if ENABLE_FEATURE_SH_HISTFILESIZE
14292                         hp = lookupvar("HISTFILESIZE");
14293                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14294 # endif
14295                 }
14296 #endif
14297  state4: /* XXX ??? - why isn't this before the "if" statement */
14298                 cmdloop(1);
14299         }
14300 #if PROFILE
14301         monitor(0);
14302 #endif
14303 #ifdef GPROF
14304         {
14305                 extern void _mcleanup(void);
14306                 _mcleanup();
14307         }
14308 #endif
14309         TRACE(("End of main reached\n"));
14310         exitshell();
14311         /* NOTREACHED */
14312 }
14313
14314
14315 /*-
14316  * Copyright (c) 1989, 1991, 1993, 1994
14317  *      The Regents of the University of California.  All rights reserved.
14318  *
14319  * This code is derived from software contributed to Berkeley by
14320  * Kenneth Almquist.
14321  *
14322  * Redistribution and use in source and binary forms, with or without
14323  * modification, are permitted provided that the following conditions
14324  * are met:
14325  * 1. Redistributions of source code must retain the above copyright
14326  *    notice, this list of conditions and the following disclaimer.
14327  * 2. Redistributions in binary form must reproduce the above copyright
14328  *    notice, this list of conditions and the following disclaimer in the
14329  *    documentation and/or other materials provided with the distribution.
14330  * 3. Neither the name of the University nor the names of its contributors
14331  *    may be used to endorse or promote products derived from this software
14332  *    without specific prior written permission.
14333  *
14334  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14335  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14336  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14337  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14338  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14339  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14340  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14341  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14342  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14343  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14344  * SUCH DAMAGE.
14345  */