bzip2: fix two crashes on corrupted archives
[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:endif # ash options
152
153 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
154 //                      APPLET_ODDNAME:name  main location    suid_type     help
155 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
156 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
157
158 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
159 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
160 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
161 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
162
163 /*
164  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
165  * DEBUG=2 to compile in and turn on debugging.
166  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
167  * debugging info is written to ./trace, quit signal generates core dump.
168  */
169 #define DEBUG 0
170 /* Tweak debug output verbosity here */
171 #define DEBUG_TIME 0
172 #define DEBUG_PID 1
173 #define DEBUG_SIG 1
174 #define DEBUG_INTONOFF 0
175
176 #define PROFILE 0
177
178 #define JOBS ENABLE_ASH_JOB_CONTROL
179
180 #include <fnmatch.h>
181 #include <sys/times.h>
182 #include <sys/utsname.h> /* for setting $HOSTNAME */
183 #include "busybox.h" /* for applet_names */
184
185 /* So far, all bash compat is controlled by one config option */
186 /* Separate defines document which part of code implements what */
187 /* function keyword */
188 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
189 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
190 /* &>file */
191 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
192 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
193 /* $'...' */
194 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
195 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
196 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
197 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
198 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
199 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
200 /* [[ EXPR ]] */
201 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
202 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
203 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
204 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
205 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
206 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
207 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
208 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
209
210 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
211 /* Bionic at least up to version 24 has no glob() */
212 # undef  ENABLE_ASH_INTERNAL_GLOB
213 # define ENABLE_ASH_INTERNAL_GLOB 1
214 #endif
215
216 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
217 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
218 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
219 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
220 # error glob() should unbackslash them and match. uClibc does not unbackslash,
221 # error fails to match dirname, subsequently not expanding <pattern> in it.
222 // Testcase:
223 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
224 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
225 #endif
226
227 #if !ENABLE_ASH_INTERNAL_GLOB
228 # include <glob.h>
229 #endif
230
231 #include "unicode.h"
232 #include "shell_common.h"
233 #if ENABLE_FEATURE_SH_MATH
234 # include "math.h"
235 #else
236 typedef long arith_t;
237 # define ARITH_FMT "%ld"
238 #endif
239 #if ENABLE_ASH_RANDOM_SUPPORT
240 # include "random.h"
241 #else
242 # define CLEAR_RANDOM_T(rnd) ((void)0)
243 #endif
244
245 #include "NUM_APPLETS.h"
246 #if NUM_APPLETS == 1
247 /* STANDALONE does not make sense, and won't compile */
248 # undef CONFIG_FEATURE_SH_STANDALONE
249 # undef ENABLE_FEATURE_SH_STANDALONE
250 # undef IF_FEATURE_SH_STANDALONE
251 # undef IF_NOT_FEATURE_SH_STANDALONE
252 # define ENABLE_FEATURE_SH_STANDALONE 0
253 # define IF_FEATURE_SH_STANDALONE(...)
254 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
255 #endif
256
257 #ifndef F_DUPFD_CLOEXEC
258 # define F_DUPFD_CLOEXEC F_DUPFD
259 #endif
260 #ifndef O_CLOEXEC
261 # define O_CLOEXEC 0
262 #endif
263 #ifndef PIPE_BUF
264 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
265 #endif
266
267 #if !BB_MMU
268 # error "Do not even bother, ash will not run on NOMMU machine"
269 #endif
270
271 /* We use a trick to have more optimized code (fewer pointer reloads):
272  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
273  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
274  * This way, compiler in ash.c knows the pointer can not change.
275  *
276  * However, this may break on weird arches or toolchains. In this case,
277  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
278  * this optimization.
279  */
280 #ifndef BB_GLOBAL_CONST
281 # define BB_GLOBAL_CONST const
282 #endif
283
284
285 /* ============ Hash table sizes. Configurable. */
286
287 #define VTABSIZE 39
288 #define ATABSIZE 39
289 #define CMDTABLESIZE 31         /* should be prime */
290
291
292 /* ============ Shell options */
293
294 static const char *const optletters_optnames[] = {
295         "e"   "errexit",
296         "f"   "noglob",
297         "I"   "ignoreeof",
298         "i"   "interactive",
299         "m"   "monitor",
300         "n"   "noexec",
301         "s"   "stdin",
302         "x"   "xtrace",
303         "v"   "verbose",
304         "C"   "noclobber",
305         "a"   "allexport",
306         "b"   "notify",
307         "u"   "nounset",
308         "\0"  "vi"
309 #if BASH_PIPEFAIL
310         ,"\0"  "pipefail"
311 #endif
312 #if DEBUG
313         ,"\0"  "nolog"
314         ,"\0"  "debug"
315 #endif
316 };
317
318 #define optletters(n)  optletters_optnames[n][0]
319 #define optnames(n)   (optletters_optnames[n] + 1)
320
321 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
322
323
324 /* ============ Misc data */
325
326 #define msg_illnum "Illegal number: %s"
327
328 /*
329  * We enclose jmp_buf in a structure so that we can declare pointers to
330  * jump locations.  The global variable handler contains the location to
331  * jump to when an exception occurs, and the global variable exception_type
332  * contains a code identifying the exception.  To implement nested
333  * exception handlers, the user should save the value of handler on entry
334  * to an inner scope, set handler to point to a jmploc structure for the
335  * inner scope, and restore handler on exit from the scope.
336  */
337 struct jmploc {
338         jmp_buf loc;
339 };
340
341 struct globals_misc {
342         uint8_t exitstatus;     /* exit status of last command */
343         uint8_t back_exitstatus;/* exit status of backquoted command */
344         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
345         int rootpid;            /* pid of main shell */
346         /* shell level: 0 for the main shell, 1 for its children, and so on */
347         int shlvl;
348 #define rootshell (!shlvl)
349         int errlinno;
350
351         char *minusc;  /* argument to -c option */
352
353         char *curdir; // = nullstr;     /* current working directory */
354         char *physdir; // = nullstr;    /* physical working directory */
355
356         char *arg0; /* value of $0 */
357
358         struct jmploc *exception_handler;
359
360         volatile int suppress_int; /* counter */
361         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
362         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
363         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
364         smallint exception_type; /* kind of exception (0..5) */
365         /* exceptions */
366 #define EXINT 0         /* SIGINT received */
367 #define EXERROR 1       /* a generic error */
368 #define EXEXIT 4        /* exit the shell */
369
370         char nullstr[1];        /* zero length string */
371
372         char optlist[NOPTS];
373 #define eflag optlist[0]
374 #define fflag optlist[1]
375 #define Iflag optlist[2]
376 #define iflag optlist[3]
377 #define mflag optlist[4]
378 #define nflag optlist[5]
379 #define sflag optlist[6]
380 #define xflag optlist[7]
381 #define vflag optlist[8]
382 #define Cflag optlist[9]
383 #define aflag optlist[10]
384 #define bflag optlist[11]
385 #define uflag optlist[12]
386 #define viflag optlist[13]
387 #if BASH_PIPEFAIL
388 # define pipefail optlist[14]
389 #else
390 # define pipefail 0
391 #endif
392 #if DEBUG
393 # define nolog optlist[14 + BASH_PIPEFAIL]
394 # define debug optlist[15 + BASH_PIPEFAIL]
395 #endif
396
397         /* trap handler commands */
398         /*
399          * Sigmode records the current value of the signal handlers for the various
400          * modes.  A value of zero means that the current handler is not known.
401          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
402          */
403         char sigmode[NSIG - 1];
404 #define S_DFL      1            /* default signal handling (SIG_DFL) */
405 #define S_CATCH    2            /* signal is caught */
406 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
407 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
408
409         /* indicates specified signal received */
410         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
411         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
412         char *trap[NSIG];
413         char **trap_ptr;        /* used only by "trap hack" */
414
415         /* Rarely referenced stuff */
416 #if ENABLE_ASH_RANDOM_SUPPORT
417         random_t random_gen;
418 #endif
419         pid_t backgndpid;        /* pid of last background process */
420 };
421 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
422 #define G_misc (*ash_ptr_to_globals_misc)
423 #define exitstatus        (G_misc.exitstatus )
424 #define back_exitstatus   (G_misc.back_exitstatus )
425 #define job_warning       (G_misc.job_warning)
426 #define rootpid     (G_misc.rootpid    )
427 #define shlvl       (G_misc.shlvl      )
428 #define errlinno    (G_misc.errlinno   )
429 #define minusc      (G_misc.minusc     )
430 #define curdir      (G_misc.curdir     )
431 #define physdir     (G_misc.physdir    )
432 #define arg0        (G_misc.arg0       )
433 #define exception_handler (G_misc.exception_handler)
434 #define exception_type    (G_misc.exception_type   )
435 #define suppress_int      (G_misc.suppress_int     )
436 #define pending_int       (G_misc.pending_int      )
437 #define got_sigchld       (G_misc.got_sigchld      )
438 #define pending_sig       (G_misc.pending_sig      )
439 #define nullstr     (G_misc.nullstr    )
440 #define optlist     (G_misc.optlist    )
441 #define sigmode     (G_misc.sigmode    )
442 #define gotsig      (G_misc.gotsig     )
443 #define may_have_traps    (G_misc.may_have_traps   )
444 #define trap        (G_misc.trap       )
445 #define trap_ptr    (G_misc.trap_ptr   )
446 #define random_gen  (G_misc.random_gen )
447 #define backgndpid  (G_misc.backgndpid )
448 #define INIT_G_misc() do { \
449         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
450         barrier(); \
451         curdir = nullstr; \
452         physdir = nullstr; \
453         trap_ptr = trap; \
454 } while (0)
455
456
457 /* ============ DEBUG */
458 #if DEBUG
459 static void trace_printf(const char *fmt, ...);
460 static void trace_vprintf(const char *fmt, va_list va);
461 # define TRACE(param)    trace_printf param
462 # define TRACEV(param)   trace_vprintf param
463 # define close(fd) do { \
464         int dfd = (fd); \
465         if (close(dfd) < 0) \
466                 bb_error_msg("bug on %d: closing %d(0x%x)", \
467                         __LINE__, dfd, dfd); \
468 } while (0)
469 #else
470 # define TRACE(param)
471 # define TRACEV(param)
472 #endif
473
474
475 /* ============ Utility functions */
476 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
477 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
478
479 static int
480 isdigit_str9(const char *str)
481 {
482         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
483         while (--maxlen && isdigit(*str))
484                 str++;
485         return (*str == '\0');
486 }
487
488 static const char *
489 var_end(const char *var)
490 {
491         while (*var)
492                 if (*var++ == '=')
493                         break;
494         return var;
495 }
496
497
498 /* ============ Interrupts / exceptions */
499
500 static void exitshell(void) NORETURN;
501
502 /*
503  * These macros allow the user to suspend the handling of interrupt signals
504  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
505  * much more efficient and portable.  (But hacking the kernel is so much
506  * more fun than worrying about efficiency and portability. :-))
507  */
508 #if DEBUG_INTONOFF
509 # define INT_OFF do { \
510         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
511         suppress_int++; \
512         barrier(); \
513 } while (0)
514 #else
515 # define INT_OFF do { \
516         suppress_int++; \
517         barrier(); \
518 } while (0)
519 #endif
520
521 /*
522  * Called to raise an exception.  Since C doesn't include exceptions, we
523  * just do a longjmp to the exception handler.  The type of exception is
524  * stored in the global variable "exception_type".
525  */
526 static void raise_exception(int) NORETURN;
527 static void
528 raise_exception(int e)
529 {
530 #if DEBUG
531         if (exception_handler == NULL)
532                 abort();
533 #endif
534         INT_OFF;
535         exception_type = e;
536         longjmp(exception_handler->loc, 1);
537 }
538 #if DEBUG
539 #define raise_exception(e) do { \
540         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
541         raise_exception(e); \
542 } while (0)
543 #endif
544
545 /*
546  * Called when a SIGINT is received.  (If the user specifies
547  * that SIGINT is to be trapped or ignored using the trap builtin, then
548  * this routine is not called.)  Suppressint is nonzero when interrupts
549  * are held using the INT_OFF macro.  (The test for iflag is just
550  * defensive programming.)
551  */
552 static void raise_interrupt(void) NORETURN;
553 static void
554 raise_interrupt(void)
555 {
556         pending_int = 0;
557         /* Signal is not automatically unmasked after it is raised,
558          * do it ourself - unmask all signals */
559         sigprocmask_allsigs(SIG_UNBLOCK);
560         /* pending_sig = 0; - now done in signal_handler() */
561
562         if (!(rootshell && iflag)) {
563                 /* Kill ourself with SIGINT */
564                 signal(SIGINT, SIG_DFL);
565                 raise(SIGINT);
566         }
567         /* bash: ^C even on empty command line sets $? */
568         exitstatus = SIGINT + 128;
569         raise_exception(EXINT);
570         /* NOTREACHED */
571 }
572 #if DEBUG
573 #define raise_interrupt() do { \
574         TRACE(("raising interrupt on line %d\n", __LINE__)); \
575         raise_interrupt(); \
576 } while (0)
577 #endif
578
579 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
580 int_on(void)
581 {
582         barrier();
583         if (--suppress_int == 0 && pending_int) {
584                 raise_interrupt();
585         }
586 }
587 #if DEBUG_INTONOFF
588 # define INT_ON do { \
589         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
590         int_on(); \
591 } while (0)
592 #else
593 # define INT_ON int_on()
594 #endif
595 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
596 force_int_on(void)
597 {
598         barrier();
599         suppress_int = 0;
600         if (pending_int)
601                 raise_interrupt();
602 }
603 #define FORCE_INT_ON force_int_on()
604
605 #define SAVE_INT(v) ((v) = suppress_int)
606
607 #define RESTORE_INT(v) do { \
608         barrier(); \
609         suppress_int = (v); \
610         if (suppress_int == 0 && pending_int) \
611                 raise_interrupt(); \
612 } while (0)
613
614
615 /* ============ Stdout/stderr output */
616
617 static void
618 outstr(const char *p, FILE *file)
619 {
620         INT_OFF;
621         fputs(p, file);
622         INT_ON;
623 }
624
625 static void
626 flush_stdout_stderr(void)
627 {
628         INT_OFF;
629         fflush_all();
630         INT_ON;
631 }
632
633 /* Was called outcslow(c,FILE*), but c was always '\n' */
634 static void
635 newline_and_flush(FILE *dest)
636 {
637         INT_OFF;
638         putc('\n', dest);
639         fflush(dest);
640         INT_ON;
641 }
642
643 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
644 static int
645 out1fmt(const char *fmt, ...)
646 {
647         va_list ap;
648         int r;
649
650         INT_OFF;
651         va_start(ap, fmt);
652         r = vprintf(fmt, ap);
653         va_end(ap);
654         INT_ON;
655         return r;
656 }
657
658 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
659 static int
660 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
661 {
662         va_list ap;
663         int ret;
664
665         INT_OFF;
666         va_start(ap, fmt);
667         ret = vsnprintf(outbuf, length, fmt, ap);
668         va_end(ap);
669         INT_ON;
670         return ret;
671 }
672
673 static void
674 out1str(const char *p)
675 {
676         outstr(p, stdout);
677 }
678
679 static void
680 out2str(const char *p)
681 {
682         outstr(p, stderr);
683         flush_stdout_stderr();
684 }
685
686
687 /* ============ Parser structures */
688
689 /* control characters in argument strings */
690 #define CTL_FIRST CTLESC
691 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
692 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
693 #define CTLENDVAR    ((unsigned char)'\203')
694 #define CTLBACKQ     ((unsigned char)'\204')
695 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
696 #define CTLENDARI    ((unsigned char)'\207')
697 #define CTLQUOTEMARK ((unsigned char)'\210')
698 #define CTL_LAST CTLQUOTEMARK
699
700 /* variable substitution byte (follows CTLVAR) */
701 #define VSTYPE  0x0f            /* type of variable substitution */
702 #define VSNUL   0x10            /* colon--treat the empty string as unset */
703
704 /* values of VSTYPE field */
705 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
706 #define VSMINUS         0x2     /* ${var-text} */
707 #define VSPLUS          0x3     /* ${var+text} */
708 #define VSQUESTION      0x4     /* ${var?message} */
709 #define VSASSIGN        0x5     /* ${var=text} */
710 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
711 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
712 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
713 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
714 #define VSLENGTH        0xa     /* ${#var} */
715 #if BASH_SUBSTR
716 #define VSSUBSTR        0xc     /* ${var:position:length} */
717 #endif
718 #if BASH_PATTERN_SUBST
719 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
720 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
721 #endif
722
723 static const char dolatstr[] ALIGN1 = {
724         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
725 };
726 #define DOLATSTRLEN 6
727
728 #define NCMD      0
729 #define NPIPE     1
730 #define NREDIR    2
731 #define NBACKGND  3
732 #define NSUBSHELL 4
733 #define NAND      5
734 #define NOR       6
735 #define NSEMI     7
736 #define NIF       8
737 #define NWHILE    9
738 #define NUNTIL   10
739 #define NFOR     11
740 #define NCASE    12
741 #define NCLIST   13
742 #define NDEFUN   14
743 #define NARG     15
744 #define NTO      16
745 #if BASH_REDIR_OUTPUT
746 #define NTO2     17
747 #endif
748 #define NCLOBBER 18
749 #define NFROM    19
750 #define NFROMTO  20
751 #define NAPPEND  21
752 #define NTOFD    22
753 #define NFROMFD  23
754 #define NHERE    24
755 #define NXHERE   25
756 #define NNOT     26
757 #define N_NUMBER 27
758
759 union node;
760
761 struct ncmd {
762         smallint type; /* Nxxxx */
763         int linno;
764         union node *assign;
765         union node *args;
766         union node *redirect;
767 };
768
769 struct npipe {
770         smallint type;
771         smallint pipe_backgnd;
772         struct nodelist *cmdlist;
773 };
774
775 struct nredir {
776         smallint type;
777         int linno;
778         union node *n;
779         union node *redirect;
780 };
781
782 struct nbinary {
783         smallint type;
784         union node *ch1;
785         union node *ch2;
786 };
787
788 struct nif {
789         smallint type;
790         union node *test;
791         union node *ifpart;
792         union node *elsepart;
793 };
794
795 struct nfor {
796         smallint type;
797         int linno;
798         union node *args;
799         union node *body;
800         char *var;
801 };
802
803 struct ncase {
804         smallint type;
805         int linno;
806         union node *expr;
807         union node *cases;
808 };
809
810 struct nclist {
811         smallint type;
812         union node *next;
813         union node *pattern;
814         union node *body;
815 };
816
817 struct ndefun {
818         smallint type;
819         int linno;
820         char *text;
821         union node *body;
822 };
823
824 struct narg {
825         smallint type;
826         union node *next;
827         char *text;
828         struct nodelist *backquote;
829 };
830
831 /* nfile and ndup layout must match!
832  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
833  * that it is actually NTO2 (>&file), and change its type.
834  */
835 struct nfile {
836         smallint type;
837         union node *next;
838         int fd;
839         int _unused_dupfd;
840         union node *fname;
841         char *expfname;
842 };
843
844 struct ndup {
845         smallint type;
846         union node *next;
847         int fd;
848         int dupfd;
849         union node *vname;
850         char *_unused_expfname;
851 };
852
853 struct nhere {
854         smallint type;
855         union node *next;
856         int fd;
857         union node *doc;
858 };
859
860 struct nnot {
861         smallint type;
862         union node *com;
863 };
864
865 union node {
866         smallint type;
867         struct ncmd ncmd;
868         struct npipe npipe;
869         struct nredir nredir;
870         struct nbinary nbinary;
871         struct nif nif;
872         struct nfor nfor;
873         struct ncase ncase;
874         struct nclist nclist;
875         struct ndefun ndefun;
876         struct narg narg;
877         struct nfile nfile;
878         struct ndup ndup;
879         struct nhere nhere;
880         struct nnot nnot;
881 };
882
883 /*
884  * NODE_EOF is returned by parsecmd when it encounters an end of file.
885  * It must be distinct from NULL.
886  */
887 #define NODE_EOF ((union node *) -1L)
888
889 struct nodelist {
890         struct nodelist *next;
891         union node *n;
892 };
893
894 struct funcnode {
895         int count;
896         union node n;
897 };
898
899 /*
900  * Free a parse tree.
901  */
902 static void
903 freefunc(struct funcnode *f)
904 {
905         if (f && --f->count < 0)
906                 free(f);
907 }
908
909
910 /* ============ Debugging output */
911
912 #if DEBUG
913
914 static FILE *tracefile;
915
916 static void
917 trace_printf(const char *fmt, ...)
918 {
919         va_list va;
920
921         if (debug != 1)
922                 return;
923         if (DEBUG_TIME)
924                 fprintf(tracefile, "%u ", (int) time(NULL));
925         if (DEBUG_PID)
926                 fprintf(tracefile, "[%u] ", (int) getpid());
927         if (DEBUG_SIG)
928                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
929         va_start(va, fmt);
930         vfprintf(tracefile, fmt, va);
931         va_end(va);
932 }
933
934 static void
935 trace_vprintf(const char *fmt, va_list va)
936 {
937         if (debug != 1)
938                 return;
939         vfprintf(tracefile, fmt, va);
940         fprintf(tracefile, "\n");
941 }
942
943 static void
944 trace_puts(const char *s)
945 {
946         if (debug != 1)
947                 return;
948         fputs(s, tracefile);
949 }
950
951 static void
952 trace_puts_quoted(char *s)
953 {
954         char *p;
955         char c;
956
957         if (debug != 1)
958                 return;
959         putc('"', tracefile);
960         for (p = s; *p; p++) {
961                 switch ((unsigned char)*p) {
962                 case '\n': c = 'n'; goto backslash;
963                 case '\t': c = 't'; goto backslash;
964                 case '\r': c = 'r'; goto backslash;
965                 case '\"': c = '\"'; goto backslash;
966                 case '\\': c = '\\'; goto backslash;
967                 case CTLESC: c = 'e'; goto backslash;
968                 case CTLVAR: c = 'v'; goto backslash;
969                 case CTLBACKQ: c = 'q'; goto backslash;
970  backslash:
971                         putc('\\', tracefile);
972                         putc(c, tracefile);
973                         break;
974                 default:
975                         if (*p >= ' ' && *p <= '~')
976                                 putc(*p, tracefile);
977                         else {
978                                 putc('\\', tracefile);
979                                 putc((*p >> 6) & 03, tracefile);
980                                 putc((*p >> 3) & 07, tracefile);
981                                 putc(*p & 07, tracefile);
982                         }
983                         break;
984                 }
985         }
986         putc('"', tracefile);
987 }
988
989 static void
990 trace_puts_args(char **ap)
991 {
992         if (debug != 1)
993                 return;
994         if (!*ap)
995                 return;
996         while (1) {
997                 trace_puts_quoted(*ap);
998                 if (!*++ap) {
999                         putc('\n', tracefile);
1000                         break;
1001                 }
1002                 putc(' ', tracefile);
1003         }
1004 }
1005
1006 static void
1007 opentrace(void)
1008 {
1009         char s[100];
1010 #ifdef O_APPEND
1011         int flags;
1012 #endif
1013
1014         if (debug != 1) {
1015                 if (tracefile)
1016                         fflush(tracefile);
1017                 /* leave open because libedit might be using it */
1018                 return;
1019         }
1020         strcpy(s, "./trace");
1021         if (tracefile) {
1022                 if (!freopen(s, "a", tracefile)) {
1023                         fprintf(stderr, "Can't re-open %s\n", s);
1024                         debug = 0;
1025                         return;
1026                 }
1027         } else {
1028                 tracefile = fopen(s, "a");
1029                 if (tracefile == NULL) {
1030                         fprintf(stderr, "Can't open %s\n", s);
1031                         debug = 0;
1032                         return;
1033                 }
1034         }
1035 #ifdef O_APPEND
1036         flags = fcntl(fileno(tracefile), F_GETFL);
1037         if (flags >= 0)
1038                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1039 #endif
1040         setlinebuf(tracefile);
1041         fputs("\nTracing started.\n", tracefile);
1042 }
1043
1044 static void
1045 indent(int amount, char *pfx, FILE *fp)
1046 {
1047         int i;
1048
1049         for (i = 0; i < amount; i++) {
1050                 if (pfx && i == amount - 1)
1051                         fputs(pfx, fp);
1052                 putc('\t', fp);
1053         }
1054 }
1055
1056 /* little circular references here... */
1057 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1058
1059 static void
1060 sharg(union node *arg, FILE *fp)
1061 {
1062         char *p;
1063         struct nodelist *bqlist;
1064         unsigned char subtype;
1065
1066         if (arg->type != NARG) {
1067                 out1fmt("<node type %d>\n", arg->type);
1068                 abort();
1069         }
1070         bqlist = arg->narg.backquote;
1071         for (p = arg->narg.text; *p; p++) {
1072                 switch ((unsigned char)*p) {
1073                 case CTLESC:
1074                         p++;
1075                         putc(*p, fp);
1076                         break;
1077                 case CTLVAR:
1078                         putc('$', fp);
1079                         putc('{', fp);
1080                         subtype = *++p;
1081                         if (subtype == VSLENGTH)
1082                                 putc('#', fp);
1083
1084                         while (*p != '=') {
1085                                 putc(*p, fp);
1086                                 p++;
1087                         }
1088
1089                         if (subtype & VSNUL)
1090                                 putc(':', fp);
1091
1092                         switch (subtype & VSTYPE) {
1093                         case VSNORMAL:
1094                                 putc('}', fp);
1095                                 break;
1096                         case VSMINUS:
1097                                 putc('-', fp);
1098                                 break;
1099                         case VSPLUS:
1100                                 putc('+', fp);
1101                                 break;
1102                         case VSQUESTION:
1103                                 putc('?', fp);
1104                                 break;
1105                         case VSASSIGN:
1106                                 putc('=', fp);
1107                                 break;
1108                         case VSTRIMLEFT:
1109                                 putc('#', fp);
1110                                 break;
1111                         case VSTRIMLEFTMAX:
1112                                 putc('#', fp);
1113                                 putc('#', fp);
1114                                 break;
1115                         case VSTRIMRIGHT:
1116                                 putc('%', fp);
1117                                 break;
1118                         case VSTRIMRIGHTMAX:
1119                                 putc('%', fp);
1120                                 putc('%', fp);
1121                                 break;
1122                         case VSLENGTH:
1123                                 break;
1124                         default:
1125                                 out1fmt("<subtype %d>", subtype);
1126                         }
1127                         break;
1128                 case CTLENDVAR:
1129                         putc('}', fp);
1130                         break;
1131                 case CTLBACKQ:
1132                         putc('$', fp);
1133                         putc('(', fp);
1134                         shtree(bqlist->n, -1, NULL, fp);
1135                         putc(')', fp);
1136                         break;
1137                 default:
1138                         putc(*p, fp);
1139                         break;
1140                 }
1141         }
1142 }
1143
1144 static void
1145 shcmd(union node *cmd, FILE *fp)
1146 {
1147         union node *np;
1148         int first;
1149         const char *s;
1150         int dftfd;
1151
1152         first = 1;
1153         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1154                 if (!first)
1155                         putc(' ', fp);
1156                 sharg(np, fp);
1157                 first = 0;
1158         }
1159         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1160                 if (!first)
1161                         putc(' ', fp);
1162                 dftfd = 0;
1163                 switch (np->nfile.type) {
1164                 case NTO:      s = ">>"+1; dftfd = 1; break;
1165                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1166                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1167 #if BASH_REDIR_OUTPUT
1168                 case NTO2:
1169 #endif
1170                 case NTOFD:    s = ">&"; dftfd = 1; break;
1171                 case NFROM:    s = "<"; break;
1172                 case NFROMFD:  s = "<&"; break;
1173                 case NFROMTO:  s = "<>"; break;
1174                 default:       s = "*error*"; break;
1175                 }
1176                 if (np->nfile.fd != dftfd)
1177                         fprintf(fp, "%d", np->nfile.fd);
1178                 fputs(s, fp);
1179                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1180                         fprintf(fp, "%d", np->ndup.dupfd);
1181                 } else {
1182                         sharg(np->nfile.fname, fp);
1183                 }
1184                 first = 0;
1185         }
1186 }
1187
1188 static void
1189 shtree(union node *n, int ind, char *pfx, FILE *fp)
1190 {
1191         struct nodelist *lp;
1192         const char *s;
1193
1194         if (n == NULL)
1195                 return;
1196
1197         indent(ind, pfx, fp);
1198
1199         if (n == NODE_EOF) {
1200                 fputs("<EOF>", fp);
1201                 return;
1202         }
1203
1204         switch (n->type) {
1205         case NSEMI:
1206                 s = "; ";
1207                 goto binop;
1208         case NAND:
1209                 s = " && ";
1210                 goto binop;
1211         case NOR:
1212                 s = " || ";
1213  binop:
1214                 shtree(n->nbinary.ch1, ind, NULL, fp);
1215                 /* if (ind < 0) */
1216                         fputs(s, fp);
1217                 shtree(n->nbinary.ch2, ind, NULL, fp);
1218                 break;
1219         case NCMD:
1220                 shcmd(n, fp);
1221                 if (ind >= 0)
1222                         putc('\n', fp);
1223                 break;
1224         case NPIPE:
1225                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1226                         shtree(lp->n, 0, NULL, fp);
1227                         if (lp->next)
1228                                 fputs(" | ", fp);
1229                 }
1230                 if (n->npipe.pipe_backgnd)
1231                         fputs(" &", fp);
1232                 if (ind >= 0)
1233                         putc('\n', fp);
1234                 break;
1235         default:
1236                 fprintf(fp, "<node type %d>", n->type);
1237                 if (ind >= 0)
1238                         putc('\n', fp);
1239                 break;
1240         }
1241 }
1242
1243 static void
1244 showtree(union node *n)
1245 {
1246         trace_puts("showtree called\n");
1247         shtree(n, 1, NULL, stderr);
1248 }
1249
1250 #endif /* DEBUG */
1251
1252
1253 /* ============ Parser data */
1254
1255 /*
1256  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1257  */
1258 struct strlist {
1259         struct strlist *next;
1260         char *text;
1261 };
1262
1263 struct alias;
1264
1265 struct strpush {
1266         struct strpush *prev;   /* preceding string on stack */
1267         char *prev_string;
1268         int prev_left_in_line;
1269 #if ENABLE_ASH_ALIAS
1270         struct alias *ap;       /* if push was associated with an alias */
1271 #endif
1272         char *string;           /* remember the string since it may change */
1273
1274         /* Remember last two characters for pungetc. */
1275         int lastc[2];
1276
1277         /* Number of outstanding calls to pungetc. */
1278         int unget;
1279 };
1280
1281 /*
1282  * The parsefile structure pointed to by the global variable parsefile
1283  * contains information about the current file being read.
1284  */
1285 struct parsefile {
1286         struct parsefile *prev; /* preceding file on stack */
1287         int linno;              /* current line */
1288         int pf_fd;              /* file descriptor (or -1 if string) */
1289         int left_in_line;       /* number of chars left in this line */
1290         int left_in_buffer;     /* number of chars left in this buffer past the line */
1291         char *next_to_pgetc;    /* next char in buffer */
1292         char *buf;              /* input buffer */
1293         struct strpush *strpush; /* for pushing strings at this level */
1294         struct strpush basestrpush; /* so pushing one is fast */
1295
1296         /* Remember last two characters for pungetc. */
1297         int lastc[2];
1298
1299         /* Number of outstanding calls to pungetc. */
1300         int unget;
1301 };
1302
1303 static struct parsefile basepf;        /* top level input file */
1304 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1305 static char *commandname;              /* currently executing command */
1306
1307
1308 /* ============ Message printing */
1309
1310 static void
1311 ash_vmsg(const char *msg, va_list ap)
1312 {
1313         fprintf(stderr, "%s: ", arg0);
1314         if (commandname) {
1315                 if (strcmp(arg0, commandname))
1316                         fprintf(stderr, "%s: ", commandname);
1317                 if (!iflag || g_parsefile->pf_fd > 0)
1318                         fprintf(stderr, "line %d: ", errlinno);
1319         }
1320         vfprintf(stderr, msg, ap);
1321         newline_and_flush(stderr);
1322 }
1323
1324 /*
1325  * Exverror is called to raise the error exception.  If the second argument
1326  * is not NULL then error prints an error message using printf style
1327  * formatting.  It then raises the error exception.
1328  */
1329 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1330 static void
1331 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1332 {
1333 #if DEBUG
1334         if (msg) {
1335                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1336                 TRACEV((msg, ap));
1337         } else
1338                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1339         if (msg)
1340 #endif
1341                 ash_vmsg(msg, ap);
1342
1343         flush_stdout_stderr();
1344         raise_exception(cond);
1345         /* NOTREACHED */
1346 }
1347
1348 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1349 static void
1350 ash_msg_and_raise_error(const char *msg, ...)
1351 {
1352         va_list ap;
1353
1354         exitstatus = 2;
1355
1356         va_start(ap, msg);
1357         ash_vmsg_and_raise(EXERROR, msg, ap);
1358         /* NOTREACHED */
1359         va_end(ap);
1360 }
1361
1362 /*
1363  * 'fmt' must be a string literal.
1364  */
1365 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1366
1367 static void raise_error_syntax(const char *) NORETURN;
1368 static void
1369 raise_error_syntax(const char *msg)
1370 {
1371         errlinno = g_parsefile->linno;
1372         ash_msg_and_raise_error("syntax error: %s", msg);
1373         /* NOTREACHED */
1374 }
1375
1376 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1377 static void
1378 ash_msg_and_raise(int cond, const char *msg, ...)
1379 {
1380         va_list ap;
1381
1382         va_start(ap, msg);
1383         ash_vmsg_and_raise(cond, msg, ap);
1384         /* NOTREACHED */
1385         va_end(ap);
1386 }
1387
1388 /*
1389  * error/warning routines for external builtins
1390  */
1391 static void
1392 ash_msg(const char *fmt, ...)
1393 {
1394         va_list ap;
1395
1396         va_start(ap, fmt);
1397         ash_vmsg(fmt, ap);
1398         va_end(ap);
1399 }
1400
1401 /*
1402  * Return a string describing an error.  The returned string may be a
1403  * pointer to a static buffer that will be overwritten on the next call.
1404  * Action describes the operation that got the error.
1405  */
1406 static const char *
1407 errmsg(int e, const char *em)
1408 {
1409         if (e == ENOENT || e == ENOTDIR) {
1410                 return em;
1411         }
1412         return strerror(e);
1413 }
1414
1415
1416 /* ============ Memory allocation */
1417
1418 #if 0
1419 /* I consider these wrappers nearly useless:
1420  * ok, they return you to nearest exception handler, but
1421  * how much memory do you leak in the process, making
1422  * memory starvation worse?
1423  */
1424 static void *
1425 ckrealloc(void * p, size_t nbytes)
1426 {
1427         p = realloc(p, nbytes);
1428         if (!p)
1429                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1430         return p;
1431 }
1432
1433 static void *
1434 ckmalloc(size_t nbytes)
1435 {
1436         return ckrealloc(NULL, nbytes);
1437 }
1438
1439 static void *
1440 ckzalloc(size_t nbytes)
1441 {
1442         return memset(ckmalloc(nbytes), 0, nbytes);
1443 }
1444
1445 static char *
1446 ckstrdup(const char *s)
1447 {
1448         char *p = strdup(s);
1449         if (!p)
1450                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1451         return p;
1452 }
1453 #else
1454 /* Using bbox equivalents. They exit if out of memory */
1455 # define ckrealloc xrealloc
1456 # define ckmalloc  xmalloc
1457 # define ckzalloc  xzalloc
1458 # define ckstrdup  xstrdup
1459 #endif
1460
1461 /*
1462  * It appears that grabstackstr() will barf with such alignments
1463  * because stalloc() will return a string allocated in a new stackblock.
1464  */
1465 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1466 enum {
1467         /* Most machines require the value returned from malloc to be aligned
1468          * in some way.  The following macro will get this right
1469          * on many machines.  */
1470         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1471         /* Minimum size of a block */
1472         MINSIZE = SHELL_ALIGN(504),
1473 };
1474
1475 struct stack_block {
1476         struct stack_block *prev;
1477         char space[MINSIZE];
1478 };
1479
1480 struct stackmark {
1481         struct stack_block *stackp;
1482         char *stacknxt;
1483         size_t stacknleft;
1484 };
1485
1486
1487 struct globals_memstack {
1488         struct stack_block *g_stackp; // = &stackbase;
1489         char *g_stacknxt; // = stackbase.space;
1490         char *sstrend; // = stackbase.space + MINSIZE;
1491         size_t g_stacknleft; // = MINSIZE;
1492         struct stack_block stackbase;
1493 };
1494 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1495 #define G_memstack (*ash_ptr_to_globals_memstack)
1496 #define g_stackp     (G_memstack.g_stackp    )
1497 #define g_stacknxt   (G_memstack.g_stacknxt  )
1498 #define sstrend      (G_memstack.sstrend     )
1499 #define g_stacknleft (G_memstack.g_stacknleft)
1500 #define stackbase    (G_memstack.stackbase   )
1501 #define INIT_G_memstack() do { \
1502         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1503         barrier(); \
1504         g_stackp = &stackbase; \
1505         g_stacknxt = stackbase.space; \
1506         g_stacknleft = MINSIZE; \
1507         sstrend = stackbase.space + MINSIZE; \
1508 } while (0)
1509
1510
1511 #define stackblock()     ((void *)g_stacknxt)
1512 #define stackblocksize() g_stacknleft
1513
1514 /*
1515  * Parse trees for commands are allocated in lifo order, so we use a stack
1516  * to make this more efficient, and also to avoid all sorts of exception
1517  * handling code to handle interrupts in the middle of a parse.
1518  *
1519  * The size 504 was chosen because the Ultrix malloc handles that size
1520  * well.
1521  */
1522 static void *
1523 stalloc(size_t nbytes)
1524 {
1525         char *p;
1526         size_t aligned;
1527
1528         aligned = SHELL_ALIGN(nbytes);
1529         if (aligned > g_stacknleft) {
1530                 size_t len;
1531                 size_t blocksize;
1532                 struct stack_block *sp;
1533
1534                 blocksize = aligned;
1535                 if (blocksize < MINSIZE)
1536                         blocksize = MINSIZE;
1537                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1538                 if (len < blocksize)
1539                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1540                 INT_OFF;
1541                 sp = ckmalloc(len);
1542                 sp->prev = g_stackp;
1543                 g_stacknxt = sp->space;
1544                 g_stacknleft = blocksize;
1545                 sstrend = g_stacknxt + blocksize;
1546                 g_stackp = sp;
1547                 INT_ON;
1548         }
1549         p = g_stacknxt;
1550         g_stacknxt += aligned;
1551         g_stacknleft -= aligned;
1552         return p;
1553 }
1554
1555 static void *
1556 stzalloc(size_t nbytes)
1557 {
1558         return memset(stalloc(nbytes), 0, nbytes);
1559 }
1560
1561 static void
1562 stunalloc(void *p)
1563 {
1564 #if DEBUG
1565         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1566                 write(STDERR_FILENO, "stunalloc\n", 10);
1567                 abort();
1568         }
1569 #endif
1570         g_stacknleft += g_stacknxt - (char *)p;
1571         g_stacknxt = p;
1572 }
1573
1574 /*
1575  * Like strdup but works with the ash stack.
1576  */
1577 static char *
1578 sstrdup(const char *p)
1579 {
1580         size_t len = strlen(p) + 1;
1581         return memcpy(stalloc(len), p, len);
1582 }
1583
1584 static ALWAYS_INLINE void
1585 grabstackblock(size_t len)
1586 {
1587         stalloc(len);
1588 }
1589
1590 static void
1591 pushstackmark(struct stackmark *mark, size_t len)
1592 {
1593         mark->stackp = g_stackp;
1594         mark->stacknxt = g_stacknxt;
1595         mark->stacknleft = g_stacknleft;
1596         grabstackblock(len);
1597 }
1598
1599 static void
1600 setstackmark(struct stackmark *mark)
1601 {
1602         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1603 }
1604
1605 static void
1606 popstackmark(struct stackmark *mark)
1607 {
1608         struct stack_block *sp;
1609
1610         if (!mark->stackp)
1611                 return;
1612
1613         INT_OFF;
1614         while (g_stackp != mark->stackp) {
1615                 sp = g_stackp;
1616                 g_stackp = sp->prev;
1617                 free(sp);
1618         }
1619         g_stacknxt = mark->stacknxt;
1620         g_stacknleft = mark->stacknleft;
1621         sstrend = mark->stacknxt + mark->stacknleft;
1622         INT_ON;
1623 }
1624
1625 /*
1626  * When the parser reads in a string, it wants to stick the string on the
1627  * stack and only adjust the stack pointer when it knows how big the
1628  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1629  * of space on top of the stack and stackblocklen returns the length of
1630  * this block.  Growstackblock will grow this space by at least one byte,
1631  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1632  * part of the block that has been used.
1633  */
1634 static void
1635 growstackblock(void)
1636 {
1637         size_t newlen;
1638
1639         newlen = g_stacknleft * 2;
1640         if (newlen < g_stacknleft)
1641                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1642         if (newlen < 128)
1643                 newlen += 128;
1644
1645         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1646                 struct stack_block *sp;
1647                 struct stack_block *prevstackp;
1648                 size_t grosslen;
1649
1650                 INT_OFF;
1651                 sp = g_stackp;
1652                 prevstackp = sp->prev;
1653                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1654                 sp = ckrealloc(sp, grosslen);
1655                 sp->prev = prevstackp;
1656                 g_stackp = sp;
1657                 g_stacknxt = sp->space;
1658                 g_stacknleft = newlen;
1659                 sstrend = sp->space + newlen;
1660                 INT_ON;
1661         } else {
1662                 char *oldspace = g_stacknxt;
1663                 size_t oldlen = g_stacknleft;
1664                 char *p = stalloc(newlen);
1665
1666                 /* free the space we just allocated */
1667                 g_stacknxt = memcpy(p, oldspace, oldlen);
1668                 g_stacknleft += newlen;
1669         }
1670 }
1671
1672 /*
1673  * The following routines are somewhat easier to use than the above.
1674  * The user declares a variable of type STACKSTR, which may be declared
1675  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1676  * the user uses the macro STPUTC to add characters to the string.  In
1677  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1678  * grown as necessary.  When the user is done, she can just leave the
1679  * string there and refer to it using stackblock().  Or she can allocate
1680  * the space for it using grabstackstr().  If it is necessary to allow
1681  * someone else to use the stack temporarily and then continue to grow
1682  * the string, the user should use grabstack to allocate the space, and
1683  * then call ungrabstr(p) to return to the previous mode of operation.
1684  *
1685  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1686  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1687  * is space for at least one character.
1688  */
1689 static void *
1690 growstackstr(void)
1691 {
1692         size_t len = stackblocksize();
1693         growstackblock();
1694         return (char *)stackblock() + len;
1695 }
1696
1697 /*
1698  * Called from CHECKSTRSPACE.
1699  */
1700 static char *
1701 makestrspace(size_t newlen, char *p)
1702 {
1703         size_t len = p - g_stacknxt;
1704         size_t size;
1705
1706         for (;;) {
1707                 size_t nleft;
1708
1709                 size = stackblocksize();
1710                 nleft = size - len;
1711                 if (nleft >= newlen)
1712                         break;
1713                 growstackblock();
1714         }
1715         return (char *)stackblock() + len;
1716 }
1717
1718 static char *
1719 stack_nputstr(const char *s, size_t n, char *p)
1720 {
1721         p = makestrspace(n, p);
1722         p = (char *)mempcpy(p, s, n);
1723         return p;
1724 }
1725
1726 static char *
1727 stack_putstr(const char *s, char *p)
1728 {
1729         return stack_nputstr(s, strlen(s), p);
1730 }
1731
1732 static char *
1733 _STPUTC(int c, char *p)
1734 {
1735         if (p == sstrend)
1736                 p = growstackstr();
1737         *p++ = c;
1738         return p;
1739 }
1740
1741 #define STARTSTACKSTR(p)        ((p) = stackblock())
1742 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1743 #define CHECKSTRSPACE(n, p) do { \
1744         char *q = (p); \
1745         size_t l = (n); \
1746         size_t m = sstrend - q; \
1747         if (l > m) \
1748                 (p) = makestrspace(l, q); \
1749 } while (0)
1750 #define USTPUTC(c, p)           (*(p)++ = (c))
1751 #define STACKSTRNUL(p) do { \
1752         if ((p) == sstrend) \
1753                 (p) = growstackstr(); \
1754         *(p) = '\0'; \
1755 } while (0)
1756 #define STUNPUTC(p)             (--(p))
1757 #define STTOPC(p)               ((p)[-1])
1758 #define STADJUST(amount, p)     ((p) += (amount))
1759
1760 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1761 #define ungrabstackstr(s, p)    stunalloc(s)
1762 #define stackstrend()           ((void *)sstrend)
1763
1764
1765 /* ============ String helpers */
1766
1767 /*
1768  * prefix -- see if pfx is a prefix of string.
1769  */
1770 static char *
1771 prefix(const char *string, const char *pfx)
1772 {
1773         while (*pfx) {
1774                 if (*pfx++ != *string++)
1775                         return NULL;
1776         }
1777         return (char *) string;
1778 }
1779
1780 /*
1781  * Check for a valid number.  This should be elsewhere.
1782  */
1783 static int
1784 is_number(const char *p)
1785 {
1786         do {
1787                 if (!isdigit(*p))
1788                         return 0;
1789         } while (*++p != '\0');
1790         return 1;
1791 }
1792
1793 /*
1794  * Convert a string of digits to an integer, printing an error message on
1795  * failure.
1796  */
1797 static int
1798 number(const char *s)
1799 {
1800         if (!is_number(s))
1801                 ash_msg_and_raise_error(msg_illnum, s);
1802         return atoi(s);
1803 }
1804
1805 /*
1806  * Produce a single quoted string suitable as input to the shell.
1807  * The return string is allocated on the stack.
1808  */
1809 static char *
1810 single_quote(const char *s)
1811 {
1812         char *p;
1813
1814         STARTSTACKSTR(p);
1815
1816         do {
1817                 char *q;
1818                 size_t len;
1819
1820                 len = strchrnul(s, '\'') - s;
1821
1822                 q = p = makestrspace(len + 3, p);
1823
1824                 *q++ = '\'';
1825                 q = (char *)mempcpy(q, s, len);
1826                 *q++ = '\'';
1827                 s += len;
1828
1829                 STADJUST(q - p, p);
1830
1831                 if (*s != '\'')
1832                         break;
1833                 len = 0;
1834                 do len++; while (*++s == '\'');
1835
1836                 q = p = makestrspace(len + 3, p);
1837
1838                 *q++ = '"';
1839                 q = (char *)mempcpy(q, s - len, len);
1840                 *q++ = '"';
1841
1842                 STADJUST(q - p, p);
1843         } while (*s);
1844
1845         USTPUTC('\0', p);
1846
1847         return stackblock();
1848 }
1849
1850 /*
1851  * Produce a possibly single quoted string suitable as input to the shell.
1852  * If quoting was done, the return string is allocated on the stack,
1853  * otherwise a pointer to the original string is returned.
1854  */
1855 static const char *
1856 maybe_single_quote(const char *s)
1857 {
1858         const char *p = s;
1859
1860         while (*p) {
1861                 /* Assuming ACSII */
1862                 /* quote ctrl_chars space !"#$%&'()* */
1863                 if (*p < '+')
1864                         goto need_quoting;
1865                 /* quote ;<=>? */
1866                 if (*p >= ';' && *p <= '?')
1867                         goto need_quoting;
1868                 /* quote `[\ */
1869                 if (*p == '`')
1870                         goto need_quoting;
1871                 if (*p == '[')
1872                         goto need_quoting;
1873                 if (*p == '\\')
1874                         goto need_quoting;
1875                 /* quote {|}~ DEL and high bytes */
1876                 if (*p > 'z')
1877                         goto need_quoting;
1878                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1879                 /* TODO: maybe avoid quoting % */
1880                 p++;
1881         }
1882         return s;
1883
1884  need_quoting:
1885         return single_quote(s);
1886 }
1887
1888
1889 /* ============ nextopt */
1890
1891 static char **argptr;                  /* argument list for builtin commands */
1892 static char *optionarg;                /* set by nextopt (like getopt) */
1893 static char *optptr;                   /* used by nextopt */
1894
1895 /*
1896  * XXX - should get rid of. Have all builtins use getopt(3).
1897  * The library getopt must have the BSD extension static variable
1898  * "optreset", otherwise it can't be used within the shell safely.
1899  *
1900  * Standard option processing (a la getopt) for builtin routines.
1901  * The only argument that is passed to nextopt is the option string;
1902  * the other arguments are unnecessary. It returns the character,
1903  * or '\0' on end of input.
1904  */
1905 static int
1906 nextopt(const char *optstring)
1907 {
1908         char *p;
1909         const char *q;
1910         char c;
1911
1912         p = optptr;
1913         if (p == NULL || *p == '\0') {
1914                 /* We ate entire "-param", take next one */
1915                 p = *argptr;
1916                 if (p == NULL)
1917                         return '\0';
1918                 if (*p != '-')
1919                         return '\0';
1920                 if (*++p == '\0') /* just "-" ? */
1921                         return '\0';
1922                 argptr++;
1923                 if (LONE_DASH(p)) /* "--" ? */
1924                         return '\0';
1925                 /* p => next "-param" */
1926         }
1927         /* p => some option char in the middle of a "-param" */
1928         c = *p++;
1929         for (q = optstring; *q != c;) {
1930                 if (*q == '\0')
1931                         ash_msg_and_raise_error("illegal option -%c", c);
1932                 if (*++q == ':')
1933                         q++;
1934         }
1935         if (*++q == ':') {
1936                 if (*p == '\0') {
1937                         p = *argptr++;
1938                         if (p == NULL)
1939                                 ash_msg_and_raise_error("no arg for -%c option", c);
1940                 }
1941                 optionarg = p;
1942                 p = NULL;
1943         }
1944         optptr = p;
1945         return c;
1946 }
1947
1948
1949 /* ============ Shell variables */
1950
1951 struct shparam {
1952         int nparam;             /* # of positional parameters (without $0) */
1953 #if ENABLE_ASH_GETOPTS
1954         int optind;             /* next parameter to be processed by getopts */
1955         int optoff;             /* used by getopts */
1956 #endif
1957         unsigned char malloced; /* if parameter list dynamically allocated */
1958         char **p;               /* parameter list */
1959 };
1960
1961 /*
1962  * Free the list of positional parameters.
1963  */
1964 static void
1965 freeparam(volatile struct shparam *param)
1966 {
1967         if (param->malloced) {
1968                 char **ap, **ap1;
1969                 ap = ap1 = param->p;
1970                 while (*ap)
1971                         free(*ap++);
1972                 free(ap1);
1973         }
1974 }
1975
1976 #if ENABLE_ASH_GETOPTS
1977 static void FAST_FUNC getoptsreset(const char *value);
1978 #endif
1979
1980 struct var {
1981         struct var *next;               /* next entry in hash list */
1982         int flags;                      /* flags are defined above */
1983         const char *var_text;           /* name=value */
1984         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1985                                         /* the variable gets set/unset */
1986 };
1987
1988 struct localvar {
1989         struct localvar *next;          /* next local variable in list */
1990         struct var *vp;                 /* the variable that was made local */
1991         int flags;                      /* saved flags */
1992         const char *text;               /* saved text */
1993 };
1994
1995 /* flags */
1996 #define VEXPORT         0x01    /* variable is exported */
1997 #define VREADONLY       0x02    /* variable cannot be modified */
1998 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1999 #define VTEXTFIXED      0x08    /* text is statically allocated */
2000 #define VSTACK          0x10    /* text is allocated on the stack */
2001 #define VUNSET          0x20    /* the variable is not set */
2002 #define VNOFUNC         0x40    /* don't call the callback function */
2003 #define VNOSET          0x80    /* do not set variable - just readonly test */
2004 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2005 #if ENABLE_ASH_RANDOM_SUPPORT
2006 # define VDYNAMIC       0x200   /* dynamic variable */
2007 #else
2008 # define VDYNAMIC       0
2009 #endif
2010
2011
2012 /* Need to be before varinit_data[] */
2013 #if ENABLE_LOCALE_SUPPORT
2014 static void FAST_FUNC
2015 change_lc_all(const char *value)
2016 {
2017         if (value && *value != '\0')
2018                 setlocale(LC_ALL, value);
2019 }
2020 static void FAST_FUNC
2021 change_lc_ctype(const char *value)
2022 {
2023         if (value && *value != '\0')
2024                 setlocale(LC_CTYPE, value);
2025 }
2026 #endif
2027 #if ENABLE_ASH_MAIL
2028 static void chkmail(void);
2029 static void changemail(const char *var_value) FAST_FUNC;
2030 #else
2031 # define chkmail()  ((void)0)
2032 #endif
2033 static void changepath(const char *) FAST_FUNC;
2034 #if ENABLE_ASH_RANDOM_SUPPORT
2035 static void change_random(const char *) FAST_FUNC;
2036 #endif
2037
2038 static const struct {
2039         int flags;
2040         const char *var_text;
2041         void (*var_func)(const char *) FAST_FUNC;
2042 } varinit_data[] = {
2043         /*
2044          * Note: VEXPORT would not work correctly here for NOFORK applets:
2045          * some environment strings may be constant.
2046          */
2047         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2048 #if ENABLE_ASH_MAIL
2049         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2050         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2051 #endif
2052         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2053         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2054         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2055         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2056 #if ENABLE_ASH_GETOPTS
2057         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2058 #endif
2059         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2060 #if ENABLE_ASH_RANDOM_SUPPORT
2061         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2062 #endif
2063 #if ENABLE_LOCALE_SUPPORT
2064         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2065         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2066 #endif
2067 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2068         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2069 #endif
2070 };
2071
2072 struct redirtab;
2073
2074 struct globals_var {
2075         struct shparam shellparam;      /* $@ current positional parameters */
2076         struct redirtab *redirlist;
2077         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2078         struct var *vartab[VTABSIZE];
2079         struct var varinit[ARRAY_SIZE(varinit_data)];
2080         int lineno;
2081         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2082 };
2083 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2084 #define G_var (*ash_ptr_to_globals_var)
2085 #define shellparam    (G_var.shellparam   )
2086 //#define redirlist     (G_var.redirlist    )
2087 #define preverrout_fd (G_var.preverrout_fd)
2088 #define vartab        (G_var.vartab       )
2089 #define varinit       (G_var.varinit      )
2090 #define lineno        (G_var.lineno       )
2091 #define linenovar     (G_var.linenovar    )
2092 #define vifs      varinit[0]
2093 #if ENABLE_ASH_MAIL
2094 # define vmail    (&vifs)[1]
2095 # define vmpath   (&vmail)[1]
2096 # define vpath    (&vmpath)[1]
2097 #else
2098 # define vpath    (&vifs)[1]
2099 #endif
2100 #define vps1      (&vpath)[1]
2101 #define vps2      (&vps1)[1]
2102 #define vps4      (&vps2)[1]
2103 #if ENABLE_ASH_GETOPTS
2104 # define voptind  (&vps4)[1]
2105 # define vlineno  (&voptind)[1]
2106 # if ENABLE_ASH_RANDOM_SUPPORT
2107 #  define vrandom (&vlineno)[1]
2108 # endif
2109 #else
2110 # define vlineno  (&vps4)[1]
2111 # if ENABLE_ASH_RANDOM_SUPPORT
2112 #  define vrandom (&vlineno)[1]
2113 # endif
2114 #endif
2115 #define INIT_G_var() do { \
2116         unsigned i; \
2117         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2118         barrier(); \
2119         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2120                 varinit[i].flags    = varinit_data[i].flags; \
2121                 varinit[i].var_text = varinit_data[i].var_text; \
2122                 varinit[i].var_func = varinit_data[i].var_func; \
2123         } \
2124         strcpy(linenovar, "LINENO="); \
2125         vlineno.var_text = linenovar; \
2126 } while (0)
2127
2128 /*
2129  * The following macros access the values of the above variables.
2130  * They have to skip over the name.  They return the null string
2131  * for unset variables.
2132  */
2133 #define ifsval()        (vifs.var_text + 4)
2134 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2135 #if ENABLE_ASH_MAIL
2136 # define mailval()      (vmail.var_text + 5)
2137 # define mpathval()     (vmpath.var_text + 9)
2138 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2139 #endif
2140 #define pathval()       (vpath.var_text + 5)
2141 #define ps1val()        (vps1.var_text + 4)
2142 #define ps2val()        (vps2.var_text + 4)
2143 #define ps4val()        (vps4.var_text + 4)
2144 #if ENABLE_ASH_GETOPTS
2145 # define optindval()    (voptind.var_text + 7)
2146 #endif
2147
2148 #if ENABLE_ASH_GETOPTS
2149 static void FAST_FUNC
2150 getoptsreset(const char *value)
2151 {
2152         shellparam.optind = 1;
2153         if (is_number(value))
2154                 shellparam.optind = number(value) ?: 1;
2155         shellparam.optoff = -1;
2156 }
2157 #endif
2158
2159 /*
2160  * Compares two strings up to the first = or '\0'.  The first
2161  * string must be terminated by '='; the second may be terminated by
2162  * either '=' or '\0'.
2163  */
2164 static int
2165 varcmp(const char *p, const char *q)
2166 {
2167         int c, d;
2168
2169         while ((c = *p) == (d = *q)) {
2170                 if (c == '\0' || c == '=')
2171                         goto out;
2172                 p++;
2173                 q++;
2174         }
2175         if (c == '=')
2176                 c = '\0';
2177         if (d == '=')
2178                 d = '\0';
2179  out:
2180         return c - d;
2181 }
2182
2183 /*
2184  * Find the appropriate entry in the hash table from the name.
2185  */
2186 static struct var **
2187 hashvar(const char *p)
2188 {
2189         unsigned hashval;
2190
2191         hashval = ((unsigned char) *p) << 4;
2192         while (*p && *p != '=')
2193                 hashval += (unsigned char) *p++;
2194         return &vartab[hashval % VTABSIZE];
2195 }
2196
2197 static int
2198 vpcmp(const void *a, const void *b)
2199 {
2200         return varcmp(*(const char **)a, *(const char **)b);
2201 }
2202
2203 /*
2204  * This routine initializes the builtin variables.
2205  */
2206 static void
2207 initvar(void)
2208 {
2209         struct var *vp;
2210         struct var *end;
2211         struct var **vpp;
2212
2213         /*
2214          * PS1 depends on uid
2215          */
2216 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2217         vps1.var_text = "PS1=\\w \\$ ";
2218 #else
2219         if (!geteuid())
2220                 vps1.var_text = "PS1=# ";
2221 #endif
2222         vp = varinit;
2223         end = vp + ARRAY_SIZE(varinit);
2224         do {
2225                 vpp = hashvar(vp->var_text);
2226                 vp->next = *vpp;
2227                 *vpp = vp;
2228         } while (++vp < end);
2229 }
2230
2231 static struct var **
2232 findvar(struct var **vpp, const char *name)
2233 {
2234         for (; *vpp; vpp = &(*vpp)->next) {
2235                 if (varcmp((*vpp)->var_text, name) == 0) {
2236                         break;
2237                 }
2238         }
2239         return vpp;
2240 }
2241
2242 /*
2243  * Find the value of a variable.  Returns NULL if not set.
2244  */
2245 static const char* FAST_FUNC
2246 lookupvar(const char *name)
2247 {
2248         struct var *v;
2249
2250         v = *findvar(hashvar(name), name);
2251         if (v) {
2252 #if ENABLE_ASH_RANDOM_SUPPORT
2253         /*
2254          * Dynamic variables are implemented roughly the same way they are
2255          * in bash. Namely, they're "special" so long as they aren't unset.
2256          * As soon as they're unset, they're no longer dynamic, and dynamic
2257          * lookup will no longer happen at that point. -- PFM.
2258          */
2259                 if (v->flags & VDYNAMIC)
2260                         v->var_func(NULL);
2261 #endif
2262                 if (!(v->flags & VUNSET)) {
2263                         if (v == &vlineno && v->var_text == linenovar) {
2264                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2265                         }
2266                         return var_end(v->var_text);
2267                 }
2268         }
2269         return NULL;
2270 }
2271
2272 #if ENABLE_UNICODE_SUPPORT
2273 static void
2274 reinit_unicode_for_ash(void)
2275 {
2276         /* Unicode support should be activated even if LANG is set
2277          * _during_ shell execution, not only if it was set when
2278          * shell was started. Therefore, re-check LANG every time:
2279          */
2280         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2281          || ENABLE_UNICODE_USING_LOCALE
2282         ) {
2283                 const char *s = lookupvar("LC_ALL");
2284                 if (!s) s = lookupvar("LC_CTYPE");
2285                 if (!s) s = lookupvar("LANG");
2286                 reinit_unicode(s);
2287         }
2288 }
2289 #else
2290 # define reinit_unicode_for_ash() ((void)0)
2291 #endif
2292
2293 /*
2294  * Search the environment of a builtin command.
2295  */
2296 static ALWAYS_INLINE const char *
2297 bltinlookup(const char *name)
2298 {
2299         return lookupvar(name);
2300 }
2301
2302 /*
2303  * Same as setvar except that the variable and value are passed in
2304  * the first argument as name=value.  Since the first argument will
2305  * be actually stored in the table, it should not be a string that
2306  * will go away.
2307  * Called with interrupts off.
2308  */
2309 static struct var *
2310 setvareq(char *s, int flags)
2311 {
2312         struct var *vp, **vpp;
2313
2314         vpp = hashvar(s);
2315         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2316         vpp = findvar(vpp, s);
2317         vp = *vpp;
2318         if (vp) {
2319                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2320                         const char *n;
2321
2322                         if (flags & VNOSAVE)
2323                                 free(s);
2324                         n = vp->var_text;
2325                         exitstatus = 1;
2326                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2327                 }
2328
2329                 if (flags & VNOSET)
2330                         goto out;
2331
2332                 if (vp->var_func && !(flags & VNOFUNC))
2333                         vp->var_func(var_end(s));
2334
2335                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2336                         free((char*)vp->var_text);
2337
2338                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2339                         *vpp = vp->next;
2340                         free(vp);
2341  out_free:
2342                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2343                                 free(s);
2344                         goto out;
2345                 }
2346
2347                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2348         } else {
2349                 /* variable s is not found */
2350                 if (flags & VNOSET)
2351                         goto out;
2352                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2353                         goto out_free;
2354                 vp = ckzalloc(sizeof(*vp));
2355                 vp->next = *vpp;
2356                 /*vp->func = NULL; - ckzalloc did it */
2357                 *vpp = vp;
2358         }
2359         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2360                 s = ckstrdup(s);
2361         vp->var_text = s;
2362         vp->flags = flags;
2363
2364  out:
2365         return vp;
2366 }
2367
2368 /*
2369  * Set the value of a variable.  The flags argument is ored with the
2370  * flags of the variable.  If val is NULL, the variable is unset.
2371  */
2372 static struct var *
2373 setvar(const char *name, const char *val, int flags)
2374 {
2375         const char *q;
2376         char *p;
2377         char *nameeq;
2378         size_t namelen;
2379         size_t vallen;
2380         struct var *vp;
2381
2382         q = endofname(name);
2383         p = strchrnul(q, '=');
2384         namelen = p - name;
2385         if (!namelen || p != q)
2386                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2387         vallen = 0;
2388         if (val == NULL) {
2389                 flags |= VUNSET;
2390         } else {
2391                 vallen = strlen(val);
2392         }
2393
2394         INT_OFF;
2395         nameeq = ckmalloc(namelen + vallen + 2);
2396         p = mempcpy(nameeq, name, namelen);
2397         if (val) {
2398                 *p++ = '=';
2399                 p = mempcpy(p, val, vallen);
2400         }
2401         *p = '\0';
2402         vp = setvareq(nameeq, flags | VNOSAVE);
2403         INT_ON;
2404
2405         return vp;
2406 }
2407
2408 static void FAST_FUNC
2409 setvar0(const char *name, const char *val)
2410 {
2411         setvar(name, val, 0);
2412 }
2413
2414 /*
2415  * Unset the specified variable.
2416  */
2417 static void
2418 unsetvar(const char *s)
2419 {
2420         setvar(s, NULL, 0);
2421 }
2422
2423 /*
2424  * Process a linked list of variable assignments.
2425  */
2426 static void
2427 listsetvar(struct strlist *list_set_var, int flags)
2428 {
2429         struct strlist *lp = list_set_var;
2430
2431         if (!lp)
2432                 return;
2433         INT_OFF;
2434         do {
2435                 setvareq(lp->text, flags);
2436                 lp = lp->next;
2437         } while (lp);
2438         INT_ON;
2439 }
2440
2441 /*
2442  * Generate a list of variables satisfying the given conditions.
2443  */
2444 #if !ENABLE_FEATURE_SH_NOFORK
2445 # define listvars(on, off, lp, end) listvars(on, off, end)
2446 #endif
2447 static char **
2448 listvars(int on, int off, struct strlist *lp, char ***end)
2449 {
2450         struct var **vpp;
2451         struct var *vp;
2452         char **ep;
2453         int mask;
2454
2455         STARTSTACKSTR(ep);
2456         vpp = vartab;
2457         mask = on | off;
2458         do {
2459                 for (vp = *vpp; vp; vp = vp->next) {
2460                         if ((vp->flags & mask) == on) {
2461 #if ENABLE_FEATURE_SH_NOFORK
2462                                 /* If variable with the same name is both
2463                                  * exported and temporarily set for a command:
2464                                  *  export ZVAR=5
2465                                  *  ZVAR=6 printenv
2466                                  * then "ZVAR=6" will be both in vartab and
2467                                  * lp lists. Do not pass it twice to printenv.
2468                                  */
2469                                 struct strlist *lp1 = lp;
2470                                 while (lp1) {
2471                                         if (strcmp(lp1->text, vp->var_text) == 0)
2472                                                 goto skip;
2473                                         lp1 = lp1->next;
2474                                 }
2475 #endif
2476                                 if (ep == stackstrend())
2477                                         ep = growstackstr();
2478                                 *ep++ = (char*)vp->var_text;
2479 #if ENABLE_FEATURE_SH_NOFORK
2480  skip: ;
2481 #endif
2482                         }
2483                 }
2484         } while (++vpp < vartab + VTABSIZE);
2485
2486 #if ENABLE_FEATURE_SH_NOFORK
2487         while (lp) {
2488                 if (ep == stackstrend())
2489                         ep = growstackstr();
2490                 *ep++ = lp->text;
2491                 lp = lp->next;
2492         }
2493 #endif
2494
2495         if (ep == stackstrend())
2496                 ep = growstackstr();
2497         if (end)
2498                 *end = ep;
2499         *ep++ = NULL;
2500         return grabstackstr(ep);
2501 }
2502
2503
2504 /* ============ Path search helper
2505  *
2506  * The variable path (passed by reference) should be set to the start
2507  * of the path before the first call; path_advance will update
2508  * this value as it proceeds.  Successive calls to path_advance will return
2509  * the possible path expansions in sequence.  If an option (indicated by
2510  * a percent sign) appears in the path entry then the global variable
2511  * pathopt will be set to point to it; otherwise pathopt will be set to
2512  * NULL.
2513  */
2514 static const char *pathopt;     /* set by path_advance */
2515
2516 static char *
2517 path_advance(const char **path, const char *name)
2518 {
2519         const char *p;
2520         char *q;
2521         const char *start;
2522         size_t len;
2523
2524         if (*path == NULL)
2525                 return NULL;
2526         start = *path;
2527         for (p = start; *p && *p != ':' && *p != '%'; p++)
2528                 continue;
2529         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2530         while (stackblocksize() < len)
2531                 growstackblock();
2532         q = stackblock();
2533         if (p != start) {
2534                 q = mempcpy(q, start, p - start);
2535                 *q++ = '/';
2536         }
2537         strcpy(q, name);
2538         pathopt = NULL;
2539         if (*p == '%') {
2540                 pathopt = ++p;
2541                 while (*p && *p != ':')
2542                         p++;
2543         }
2544         if (*p == ':')
2545                 *path = p + 1;
2546         else
2547                 *path = NULL;
2548         return stalloc(len);
2549 }
2550
2551
2552 /* ============ Prompt */
2553
2554 static smallint doprompt;                   /* if set, prompt the user */
2555 static smallint needprompt;                 /* true if interactive and at start of line */
2556
2557 #if ENABLE_FEATURE_EDITING
2558 static line_input_t *line_input_state;
2559 static const char *cmdedit_prompt;
2560 static void
2561 putprompt(const char *s)
2562 {
2563         if (ENABLE_ASH_EXPAND_PRMT) {
2564                 free((char*)cmdedit_prompt);
2565                 cmdedit_prompt = ckstrdup(s);
2566                 return;
2567         }
2568         cmdedit_prompt = s;
2569 }
2570 #else
2571 static void
2572 putprompt(const char *s)
2573 {
2574         out2str(s);
2575 }
2576 #endif
2577
2578 /* expandstr() needs parsing machinery, so it is far away ahead... */
2579 static const char *expandstr(const char *ps, int syntax_type);
2580 /* Values for syntax param */
2581 #define BASESYNTAX 0    /* not in quotes */
2582 #define DQSYNTAX   1    /* in double quotes */
2583 #define SQSYNTAX   2    /* in single quotes */
2584 #define ARISYNTAX  3    /* in arithmetic */
2585 #if ENABLE_ASH_EXPAND_PRMT
2586 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2587 #endif
2588 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2589
2590 /*
2591  * called by editline -- any expansions to the prompt should be added here.
2592  */
2593 static void
2594 setprompt_if(smallint do_set, int whichprompt)
2595 {
2596         const char *prompt;
2597         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2598
2599         if (!do_set)
2600                 return;
2601
2602         needprompt = 0;
2603
2604         switch (whichprompt) {
2605         case 1:
2606                 prompt = ps1val();
2607                 break;
2608         case 2:
2609                 prompt = ps2val();
2610                 break;
2611         default:                        /* 0 */
2612                 prompt = nullstr;
2613         }
2614 #if ENABLE_ASH_EXPAND_PRMT
2615         pushstackmark(&smark, stackblocksize());
2616         putprompt(expandstr(prompt, PSSYNTAX));
2617         popstackmark(&smark);
2618 #else
2619         putprompt(prompt);
2620 #endif
2621 }
2622
2623
2624 /* ============ The cd and pwd commands */
2625
2626 #define CD_PHYSICAL 1
2627 #define CD_PRINT 2
2628
2629 static int
2630 cdopt(void)
2631 {
2632         int flags = 0;
2633         int i, j;
2634
2635         j = 'L';
2636         while ((i = nextopt("LP")) != '\0') {
2637                 if (i != j) {
2638                         flags ^= CD_PHYSICAL;
2639                         j = i;
2640                 }
2641         }
2642
2643         return flags;
2644 }
2645
2646 /*
2647  * Update curdir (the name of the current directory) in response to a
2648  * cd command.
2649  */
2650 static const char *
2651 updatepwd(const char *dir)
2652 {
2653         char *new;
2654         char *p;
2655         char *cdcomppath;
2656         const char *lim;
2657
2658         cdcomppath = sstrdup(dir);
2659         STARTSTACKSTR(new);
2660         if (*dir != '/') {
2661                 if (curdir == nullstr)
2662                         return 0;
2663                 new = stack_putstr(curdir, new);
2664         }
2665         new = makestrspace(strlen(dir) + 2, new);
2666         lim = (char *)stackblock() + 1;
2667         if (*dir != '/') {
2668                 if (new[-1] != '/')
2669                         USTPUTC('/', new);
2670                 if (new > lim && *lim == '/')
2671                         lim++;
2672         } else {
2673                 USTPUTC('/', new);
2674                 cdcomppath++;
2675                 if (dir[1] == '/' && dir[2] != '/') {
2676                         USTPUTC('/', new);
2677                         cdcomppath++;
2678                         lim++;
2679                 }
2680         }
2681         p = strtok(cdcomppath, "/");
2682         while (p) {
2683                 switch (*p) {
2684                 case '.':
2685                         if (p[1] == '.' && p[2] == '\0') {
2686                                 while (new > lim) {
2687                                         STUNPUTC(new);
2688                                         if (new[-1] == '/')
2689                                                 break;
2690                                 }
2691                                 break;
2692                         }
2693                         if (p[1] == '\0')
2694                                 break;
2695                         /* fall through */
2696                 default:
2697                         new = stack_putstr(p, new);
2698                         USTPUTC('/', new);
2699                 }
2700                 p = strtok(NULL, "/");
2701         }
2702         if (new > lim)
2703                 STUNPUTC(new);
2704         *new = 0;
2705         return stackblock();
2706 }
2707
2708 /*
2709  * Find out what the current directory is. If we already know the current
2710  * directory, this routine returns immediately.
2711  */
2712 static char *
2713 getpwd(void)
2714 {
2715         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2716         return dir ? dir : nullstr;
2717 }
2718
2719 static void
2720 setpwd(const char *val, int setold)
2721 {
2722         char *oldcur, *dir;
2723
2724         oldcur = dir = curdir;
2725
2726         if (setold) {
2727                 setvar("OLDPWD", oldcur, VEXPORT);
2728         }
2729         INT_OFF;
2730         if (physdir != nullstr) {
2731                 if (physdir != oldcur)
2732                         free(physdir);
2733                 physdir = nullstr;
2734         }
2735         if (oldcur == val || !val) {
2736                 char *s = getpwd();
2737                 physdir = s;
2738                 if (!val)
2739                         dir = s;
2740         } else
2741                 dir = ckstrdup(val);
2742         if (oldcur != dir && oldcur != nullstr) {
2743                 free(oldcur);
2744         }
2745         curdir = dir;
2746         INT_ON;
2747         setvar("PWD", dir, VEXPORT);
2748 }
2749
2750 static void hashcd(void);
2751
2752 /*
2753  * Actually do the chdir.  We also call hashcd to let other routines
2754  * know that the current directory has changed.
2755  */
2756 static int
2757 docd(const char *dest, int flags)
2758 {
2759         const char *dir = NULL;
2760         int err;
2761
2762         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2763
2764         INT_OFF;
2765         if (!(flags & CD_PHYSICAL)) {
2766                 dir = updatepwd(dest);
2767                 if (dir)
2768                         dest = dir;
2769         }
2770         err = chdir(dest);
2771         if (err)
2772                 goto out;
2773         setpwd(dir, 1);
2774         hashcd();
2775  out:
2776         INT_ON;
2777         return err;
2778 }
2779
2780 static int FAST_FUNC
2781 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2782 {
2783         const char *dest;
2784         const char *path;
2785         const char *p;
2786         char c;
2787         struct stat statb;
2788         int flags;
2789
2790         flags = cdopt();
2791         dest = *argptr;
2792         if (!dest)
2793                 dest = bltinlookup("HOME");
2794         else if (LONE_DASH(dest)) {
2795                 dest = bltinlookup("OLDPWD");
2796                 flags |= CD_PRINT;
2797         }
2798         if (!dest)
2799                 dest = nullstr;
2800         if (*dest == '/')
2801                 goto step6;
2802         if (*dest == '.') {
2803                 c = dest[1];
2804  dotdot:
2805                 switch (c) {
2806                 case '\0':
2807                 case '/':
2808                         goto step6;
2809                 case '.':
2810                         c = dest[2];
2811                         if (c != '.')
2812                                 goto dotdot;
2813                 }
2814         }
2815         if (!*dest)
2816                 dest = ".";
2817         path = bltinlookup("CDPATH");
2818         while (path) {
2819                 c = *path;
2820                 p = path_advance(&path, dest);
2821                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2822                         if (c && c != ':')
2823                                 flags |= CD_PRINT;
2824  docd:
2825                         if (!docd(p, flags))
2826                                 goto out;
2827                         goto err;
2828                 }
2829         }
2830
2831  step6:
2832         p = dest;
2833         goto docd;
2834
2835  err:
2836         ash_msg_and_raise_perror("can't cd to %s", dest);
2837         /* NOTREACHED */
2838  out:
2839         if (flags & CD_PRINT)
2840                 out1fmt("%s\n", curdir);
2841         return 0;
2842 }
2843
2844 static int FAST_FUNC
2845 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2846 {
2847         int flags;
2848         const char *dir = curdir;
2849
2850         flags = cdopt();
2851         if (flags) {
2852                 if (physdir == nullstr)
2853                         setpwd(dir, 0);
2854                 dir = physdir;
2855         }
2856         out1fmt("%s\n", dir);
2857         return 0;
2858 }
2859
2860
2861 /* ============ ... */
2862
2863
2864 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2865
2866 /* Syntax classes */
2867 #define CWORD     0             /* character is nothing special */
2868 #define CNL       1             /* newline character */
2869 #define CBACK     2             /* a backslash character */
2870 #define CSQUOTE   3             /* single quote */
2871 #define CDQUOTE   4             /* double quote */
2872 #define CENDQUOTE 5             /* a terminating quote */
2873 #define CBQUOTE   6             /* backwards single quote */
2874 #define CVAR      7             /* a dollar sign */
2875 #define CENDVAR   8             /* a '}' character */
2876 #define CLP       9             /* a left paren in arithmetic */
2877 #define CRP      10             /* a right paren in arithmetic */
2878 #define CENDFILE 11             /* end of file */
2879 #define CCTL     12             /* like CWORD, except it must be escaped */
2880 #define CSPCL    13             /* these terminate a word */
2881 #define CIGN     14             /* character should be ignored */
2882
2883 #define PEOF     256
2884 #if ENABLE_ASH_ALIAS
2885 # define PEOA    257
2886 #endif
2887
2888 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2889
2890 #if ENABLE_FEATURE_SH_MATH
2891 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2892 #else
2893 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2894 #endif
2895 static const uint16_t S_I_T[] ALIGN2 = {
2896 #if ENABLE_ASH_ALIAS
2897         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2898 #endif
2899         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2900         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2901         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2902         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2903         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2904         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2905         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2906         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2907         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2908         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2909         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2910 #if !USE_SIT_FUNCTION
2911         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2912         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2913         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2914 #endif
2915 #undef SIT_ITEM
2916 };
2917 /* Constants below must match table above */
2918 enum {
2919 #if ENABLE_ASH_ALIAS
2920         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2921 #endif
2922         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2923         CNL_CNL_CNL_CNL                    , /*  2 */
2924         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2925         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2926         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2927         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2928         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2929         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2930         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2931         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2932         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2933         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2934         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2935         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2936 };
2937
2938 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2939  * caller must ensure proper cast on it if c is *char_ptr!
2940  */
2941 #if USE_SIT_FUNCTION
2942
2943 static int
2944 SIT(int c, int syntax)
2945 {
2946         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2947         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2948         /*
2949          * This causes '/' to be prepended with CTLESC in dquoted string,
2950          * making "./file"* treated incorrectly because we feed
2951          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2952          * The "homegrown" glob implementation is okay with that,
2953          * but glibc one isn't. With '/' always treated as CWORD,
2954          * both work fine.
2955          */
2956 # if ENABLE_ASH_ALIAS
2957         static const uint8_t syntax_index_table[] ALIGN1 = {
2958                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2959                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2960                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2961                 11, 3                           /* "}~" */
2962         };
2963 # else
2964         static const uint8_t syntax_index_table[] ALIGN1 = {
2965                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2966                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2967                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2968                 10, 2                           /* "}~" */
2969         };
2970 # endif
2971         const char *s;
2972         int indx;
2973
2974         if (c == PEOF)
2975                 return CENDFILE;
2976 # if ENABLE_ASH_ALIAS
2977         if (c == PEOA)
2978                 indx = 0;
2979         else
2980 # endif
2981         {
2982                 /* Cast is purely for paranoia here,
2983                  * just in case someone passed signed char to us */
2984                 if ((unsigned char)c >= CTL_FIRST
2985                  && (unsigned char)c <= CTL_LAST
2986                 ) {
2987                         return CCTL;
2988                 }
2989                 s = strchrnul(spec_symbls, c);
2990                 if (*s == '\0')
2991                         return CWORD;
2992                 indx = syntax_index_table[s - spec_symbls];
2993         }
2994         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2995 }
2996
2997 #else   /* !USE_SIT_FUNCTION */
2998
2999 static const uint8_t syntax_index_table[] ALIGN1 = {
3000         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3001         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3002         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3003         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3004         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3005         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3006         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3007         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3008         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3009         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3010         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3011         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3012         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3013         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3014         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3015         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3016         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3017         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3018         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3019         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3020         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3021         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3022         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3023         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3024         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3025         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3026         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3027         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3028         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3029         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3030         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3031         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3032         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3033         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3034         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3035         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3036         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3037         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3038         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3039         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3040         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3041         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3042         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3043         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3044         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3045         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3046         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3047         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3048 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3049         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3050         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3051         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3052         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3053         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3054         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3055         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3056         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3057         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3058         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3059         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3060         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3061         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3062         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3063         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3064         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3065         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3066         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3067         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3068         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3069         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3070         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3071         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3072         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3073         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3074         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3075         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3076         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3077         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3078         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3079         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3080         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3081         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3082         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3083         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3084         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3085         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3086         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3087         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3088         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3089         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3090         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3091         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3092         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3093         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3094         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3095         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3096         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3097         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3098         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3099         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3100         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3101         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3102         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3103         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3104         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3105         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3106         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3107         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3108         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3109         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3110         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3111         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3112         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3113         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3114         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3115         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3116         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3117         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3118         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3119         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3120         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3121         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3122         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3123         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3124         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3125         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3126         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3127         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3128         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3129         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3130         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3131         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3132         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3133         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3134         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3135         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3136         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3137         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3138         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3139         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3258         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3259 # if ENABLE_ASH_ALIAS
3260         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3261 # endif
3262 };
3263
3264 #if 1
3265 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3266 #else /* debug version, caught one signed char bug */
3267 # define SIT(c, syntax) \
3268         ({ \
3269                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3270                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3271                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3272                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3273                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3274         })
3275 #endif
3276
3277 #endif  /* !USE_SIT_FUNCTION */
3278
3279
3280 /* ============ Alias handling */
3281
3282 #if ENABLE_ASH_ALIAS
3283
3284 #define ALIASINUSE 1
3285 #define ALIASDEAD  2
3286
3287 struct alias {
3288         struct alias *next;
3289         char *name;
3290         char *val;
3291         int flag;
3292 };
3293
3294
3295 static struct alias **atab; // [ATABSIZE];
3296 #define INIT_G_alias() do { \
3297         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3298 } while (0)
3299
3300
3301 static struct alias **
3302 __lookupalias(const char *name)
3303 {
3304         unsigned int hashval;
3305         struct alias **app;
3306         const char *p;
3307         unsigned int ch;
3308
3309         p = name;
3310
3311         ch = (unsigned char)*p;
3312         hashval = ch << 4;
3313         while (ch) {
3314                 hashval += ch;
3315                 ch = (unsigned char)*++p;
3316         }
3317         app = &atab[hashval % ATABSIZE];
3318
3319         for (; *app; app = &(*app)->next) {
3320                 if (strcmp(name, (*app)->name) == 0) {
3321                         break;
3322                 }
3323         }
3324
3325         return app;
3326 }
3327
3328 static struct alias *
3329 lookupalias(const char *name, int check)
3330 {
3331         struct alias *ap = *__lookupalias(name);
3332
3333         if (check && ap && (ap->flag & ALIASINUSE))
3334                 return NULL;
3335         return ap;
3336 }
3337
3338 static struct alias *
3339 freealias(struct alias *ap)
3340 {
3341         struct alias *next;
3342
3343         if (ap->flag & ALIASINUSE) {
3344                 ap->flag |= ALIASDEAD;
3345                 return ap;
3346         }
3347
3348         next = ap->next;
3349         free(ap->name);
3350         free(ap->val);
3351         free(ap);
3352         return next;
3353 }
3354
3355 static void
3356 setalias(const char *name, const char *val)
3357 {
3358         struct alias *ap, **app;
3359
3360         app = __lookupalias(name);
3361         ap = *app;
3362         INT_OFF;
3363         if (ap) {
3364                 if (!(ap->flag & ALIASINUSE)) {
3365                         free(ap->val);
3366                 }
3367                 ap->val = ckstrdup(val);
3368                 ap->flag &= ~ALIASDEAD;
3369         } else {
3370                 /* not found */
3371                 ap = ckzalloc(sizeof(struct alias));
3372                 ap->name = ckstrdup(name);
3373                 ap->val = ckstrdup(val);
3374                 /*ap->flag = 0; - ckzalloc did it */
3375                 /*ap->next = NULL;*/
3376                 *app = ap;
3377         }
3378         INT_ON;
3379 }
3380
3381 static int
3382 unalias(const char *name)
3383 {
3384         struct alias **app;
3385
3386         app = __lookupalias(name);
3387
3388         if (*app) {
3389                 INT_OFF;
3390                 *app = freealias(*app);
3391                 INT_ON;
3392                 return 0;
3393         }
3394
3395         return 1;
3396 }
3397
3398 static void
3399 rmaliases(void)
3400 {
3401         struct alias *ap, **app;
3402         int i;
3403
3404         INT_OFF;
3405         for (i = 0; i < ATABSIZE; i++) {
3406                 app = &atab[i];
3407                 for (ap = *app; ap; ap = *app) {
3408                         *app = freealias(*app);
3409                         if (ap == *app) {
3410                                 app = &ap->next;
3411                         }
3412                 }
3413         }
3414         INT_ON;
3415 }
3416
3417 static void
3418 printalias(const struct alias *ap)
3419 {
3420         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3421 }
3422
3423 /*
3424  * TODO - sort output
3425  */
3426 static int FAST_FUNC
3427 aliascmd(int argc UNUSED_PARAM, char **argv)
3428 {
3429         char *n, *v;
3430         int ret = 0;
3431         struct alias *ap;
3432
3433         if (!argv[1]) {
3434                 int i;
3435
3436                 for (i = 0; i < ATABSIZE; i++) {
3437                         for (ap = atab[i]; ap; ap = ap->next) {
3438                                 printalias(ap);
3439                         }
3440                 }
3441                 return 0;
3442         }
3443         while ((n = *++argv) != NULL) {
3444                 v = strchr(n+1, '=');
3445                 if (v == NULL) { /* n+1: funny ksh stuff */
3446                         ap = *__lookupalias(n);
3447                         if (ap == NULL) {
3448                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3449                                 ret = 1;
3450                         } else
3451                                 printalias(ap);
3452                 } else {
3453                         *v++ = '\0';
3454                         setalias(n, v);
3455                 }
3456         }
3457
3458         return ret;
3459 }
3460
3461 static int FAST_FUNC
3462 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3463 {
3464         int i;
3465
3466         while (nextopt("a") != '\0') {
3467                 rmaliases();
3468                 return 0;
3469         }
3470         for (i = 0; *argptr; argptr++) {
3471                 if (unalias(*argptr)) {
3472                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3473                         i = 1;
3474                 }
3475         }
3476
3477         return i;
3478 }
3479
3480 #endif /* ASH_ALIAS */
3481
3482
3483 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3484 #define FORK_FG    0
3485 #define FORK_BG    1
3486 #define FORK_NOJOB 2
3487
3488 /* mode flags for showjob(s) */
3489 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3490 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3491 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3492 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3493
3494 /*
3495  * A job structure contains information about a job.  A job is either a
3496  * single process or a set of processes contained in a pipeline.  In the
3497  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3498  * array of pids.
3499  */
3500 struct procstat {
3501         pid_t   ps_pid;         /* process id */
3502         int     ps_status;      /* last process status from wait() */
3503         char    *ps_cmd;        /* text of command being run */
3504 };
3505
3506 struct job {
3507         struct procstat ps0;    /* status of process */
3508         struct procstat *ps;    /* status or processes when more than one */
3509 #if JOBS
3510         int stopstatus;         /* status of a stopped job */
3511 #endif
3512         unsigned nprocs;        /* number of processes */
3513
3514 #define JOBRUNNING      0       /* at least one proc running */
3515 #define JOBSTOPPED      1       /* all procs are stopped */
3516 #define JOBDONE         2       /* all procs are completed */
3517         unsigned
3518                 state: 8,
3519 #if JOBS
3520                 sigint: 1,      /* job was killed by SIGINT */
3521                 jobctl: 1,      /* job running under job control */
3522 #endif
3523                 waited: 1,      /* true if this entry has been waited for */
3524                 used: 1,        /* true if this entry is in used */
3525                 changed: 1;     /* true if status has changed */
3526         struct job *prev_job;   /* previous job */
3527 };
3528
3529 static struct job *makejob(/*union node *,*/ int);
3530 static int forkshell(struct job *, union node *, int);
3531 static int waitforjob(struct job *);
3532
3533 #if !JOBS
3534 enum { doing_jobctl = 0 };
3535 #define setjobctl(on) do {} while (0)
3536 #else
3537 static smallint doing_jobctl; //references:8
3538 static void setjobctl(int);
3539 #endif
3540
3541 /*
3542  * Ignore a signal.
3543  */
3544 static void
3545 ignoresig(int signo)
3546 {
3547         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3548         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3549                 /* No, need to do it */
3550                 signal(signo, SIG_IGN);
3551         }
3552         sigmode[signo - 1] = S_HARD_IGN;
3553 }
3554
3555 /*
3556  * Only one usage site - in setsignal()
3557  */
3558 static void
3559 signal_handler(int signo)
3560 {
3561         if (signo == SIGCHLD) {
3562                 got_sigchld = 1;
3563                 if (!trap[SIGCHLD])
3564                         return;
3565         }
3566
3567         gotsig[signo - 1] = 1;
3568         pending_sig = signo;
3569
3570         if (signo == SIGINT && !trap[SIGINT]) {
3571                 if (!suppress_int) {
3572                         pending_sig = 0;
3573                         raise_interrupt(); /* does not return */
3574                 }
3575                 pending_int = 1;
3576         }
3577 }
3578
3579 /*
3580  * Set the signal handler for the specified signal.  The routine figures
3581  * out what it should be set to.
3582  */
3583 static void
3584 setsignal(int signo)
3585 {
3586         char *t;
3587         char cur_act, new_act;
3588         struct sigaction act;
3589
3590         t = trap[signo];
3591         new_act = S_DFL;
3592         if (t != NULL) { /* trap for this sig is set */
3593                 new_act = S_CATCH;
3594                 if (t[0] == '\0') /* trap is "": ignore this sig */
3595                         new_act = S_IGN;
3596         }
3597
3598         if (rootshell && new_act == S_DFL) {
3599                 switch (signo) {
3600                 case SIGINT:
3601                         if (iflag || minusc || sflag == 0)
3602                                 new_act = S_CATCH;
3603                         break;
3604                 case SIGQUIT:
3605 #if DEBUG
3606                         if (debug)
3607                                 break;
3608 #endif
3609                         /* man bash:
3610                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3611                          * commands run by bash have signal handlers
3612                          * set to the values inherited by the shell
3613                          * from its parent". */
3614                         new_act = S_IGN;
3615                         break;
3616                 case SIGTERM:
3617                         if (iflag)
3618                                 new_act = S_IGN;
3619                         break;
3620 #if JOBS
3621                 case SIGTSTP:
3622                 case SIGTTOU:
3623                         if (mflag)
3624                                 new_act = S_IGN;
3625                         break;
3626 #endif
3627                 }
3628         }
3629         /* if !rootshell, we reset SIGQUIT to DFL,
3630          * whereas we have to restore it to what shell got on entry.
3631          * This is handled by the fact that if signal was IGNored on entry,
3632          * then cur_act is S_HARD_IGN and we never change its sigaction
3633          * (see code below).
3634          */
3635
3636         if (signo == SIGCHLD)
3637                 new_act = S_CATCH;
3638
3639         t = &sigmode[signo - 1];
3640         cur_act = *t;
3641         if (cur_act == 0) {
3642                 /* current setting is not yet known */
3643                 if (sigaction(signo, NULL, &act)) {
3644                         /* pretend it worked; maybe we should give a warning,
3645                          * but other shells don't. We don't alter sigmode,
3646                          * so we retry every time.
3647                          * btw, in Linux it never fails. --vda */
3648                         return;
3649                 }
3650                 if (act.sa_handler == SIG_IGN) {
3651                         cur_act = S_HARD_IGN;
3652                         if (mflag
3653                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3654                         ) {
3655                                 cur_act = S_IGN;   /* don't hard ignore these */
3656                         }
3657                 }
3658                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3659                         /* installing SIG_DFL over SIG_DFL is a no-op */
3660                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3661                         *t = S_DFL;
3662                         return;
3663                 }
3664         }
3665         if (cur_act == S_HARD_IGN || cur_act == new_act)
3666                 return;
3667
3668         *t = new_act;
3669
3670         act.sa_handler = SIG_DFL;
3671         switch (new_act) {
3672         case S_CATCH:
3673                 act.sa_handler = signal_handler;
3674                 break;
3675         case S_IGN:
3676                 act.sa_handler = SIG_IGN;
3677                 break;
3678         }
3679         /* flags and mask matter only if !DFL and !IGN, but we do it
3680          * for all cases for more deterministic behavior:
3681          */
3682         act.sa_flags = 0; //TODO: why not SA_RESTART?
3683         sigfillset(&act.sa_mask);
3684
3685         sigaction_set(signo, &act);
3686 }
3687
3688 /* mode flags for set_curjob */
3689 #define CUR_DELETE 2
3690 #define CUR_RUNNING 1
3691 #define CUR_STOPPED 0
3692
3693 #if JOBS
3694 /* pgrp of shell on invocation */
3695 static int initialpgrp; //references:2
3696 static int ttyfd = -1; //5
3697 #endif
3698 /* array of jobs */
3699 static struct job *jobtab; //5
3700 /* size of array */
3701 static unsigned njobs; //4
3702 /* current job */
3703 static struct job *curjob; //lots
3704 /* number of presumed living untracked jobs */
3705 static int jobless; //4
3706
3707 #if 0
3708 /* Bash has a feature: it restores termios after a successful wait for
3709  * a foreground job which had at least one stopped or sigkilled member.
3710  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3711  * properly restoring tty state. Should we do this too?
3712  * A reproducer: ^Z an interactive python:
3713  *
3714  * # python
3715  * Python 2.7.12 (...)
3716  * >>> ^Z
3717  *      { python leaves tty in -icanon -echo state. We do survive that... }
3718  *  [1]+  Stopped                    python
3719  *      { ...however, next program (python #2) does not survive it well: }
3720  * # python
3721  * Python 2.7.12 (...)
3722  * >>> Traceback (most recent call last):
3723  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3724  *   File "<stdin>", line 1, in <module>
3725  * NameError: name 'qwerty' is not defined
3726  *
3727  * The implementation below is modeled on bash code and seems to work.
3728  * However, I'm not sure we should do this. For one: what if I'd fg
3729  * the stopped python instead? It'll be confused by "restored" tty state.
3730  */
3731 static struct termios shell_tty_info;
3732 static void
3733 get_tty_state(void)
3734 {
3735         if (rootshell && ttyfd >= 0)
3736                 tcgetattr(ttyfd, &shell_tty_info);
3737 }
3738 static void
3739 set_tty_state(void)
3740 {
3741         /* if (rootshell) - caller ensures this */
3742         if (ttyfd >= 0)
3743                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3744 }
3745 static int
3746 job_signal_status(struct job *jp)
3747 {
3748         int status;
3749         unsigned i;
3750         struct procstat *ps = jp->ps;
3751         for (i = 0; i < jp->nprocs; i++) {
3752                 status = ps[i].ps_status;
3753                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3754                         return status;
3755         }
3756         return 0;
3757 }
3758 static void
3759 restore_tty_if_stopped_or_signaled(struct job *jp)
3760 {
3761 //TODO: check what happens if we come from waitforjob() in expbackq()
3762         if (rootshell) {
3763                 int s = job_signal_status(jp);
3764                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3765                         set_tty_state();
3766         }
3767 }
3768 #else
3769 # define get_tty_state() ((void)0)
3770 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3771 #endif
3772
3773 static void
3774 set_curjob(struct job *jp, unsigned mode)
3775 {
3776         struct job *jp1;
3777         struct job **jpp, **curp;
3778
3779         /* first remove from list */
3780         jpp = curp = &curjob;
3781         while (1) {
3782                 jp1 = *jpp;
3783                 if (jp1 == jp)
3784                         break;
3785                 jpp = &jp1->prev_job;
3786         }
3787         *jpp = jp1->prev_job;
3788
3789         /* Then re-insert in correct position */
3790         jpp = curp;
3791         switch (mode) {
3792         default:
3793 #if DEBUG
3794                 abort();
3795 #endif
3796         case CUR_DELETE:
3797                 /* job being deleted */
3798                 break;
3799         case CUR_RUNNING:
3800                 /* newly created job or backgrounded job,
3801                  * put after all stopped jobs.
3802                  */
3803                 while (1) {
3804                         jp1 = *jpp;
3805 #if JOBS
3806                         if (!jp1 || jp1->state != JOBSTOPPED)
3807 #endif
3808                                 break;
3809                         jpp = &jp1->prev_job;
3810                 }
3811                 /* FALLTHROUGH */
3812 #if JOBS
3813         case CUR_STOPPED:
3814 #endif
3815                 /* newly stopped job - becomes curjob */
3816                 jp->prev_job = *jpp;
3817                 *jpp = jp;
3818                 break;
3819         }
3820 }
3821
3822 #if JOBS || DEBUG
3823 static int
3824 jobno(const struct job *jp)
3825 {
3826         return jp - jobtab + 1;
3827 }
3828 #endif
3829
3830 /*
3831  * Convert a job name to a job structure.
3832  */
3833 #if !JOBS
3834 #define getjob(name, getctl) getjob(name)
3835 #endif
3836 static struct job *
3837 getjob(const char *name, int getctl)
3838 {
3839         struct job *jp;
3840         struct job *found;
3841         const char *err_msg = "%s: no such job";
3842         unsigned num;
3843         int c;
3844         const char *p;
3845         char *(*match)(const char *, const char *);
3846
3847         jp = curjob;
3848         p = name;
3849         if (!p)
3850                 goto currentjob;
3851
3852         if (*p != '%')
3853                 goto err;
3854
3855         c = *++p;
3856         if (!c)
3857                 goto currentjob;
3858
3859         if (!p[1]) {
3860                 if (c == '+' || c == '%') {
3861  currentjob:
3862                         err_msg = "No current job";
3863                         goto check;
3864                 }
3865                 if (c == '-') {
3866                         if (jp)
3867                                 jp = jp->prev_job;
3868                         err_msg = "No previous job";
3869  check:
3870                         if (!jp)
3871                                 goto err;
3872                         goto gotit;
3873                 }
3874         }
3875
3876         if (is_number(p)) {
3877                 num = atoi(p);
3878                 if (num > 0 && num <= njobs) {
3879                         jp = jobtab + num - 1;
3880                         if (jp->used)
3881                                 goto gotit;
3882                         goto err;
3883                 }
3884         }
3885
3886         match = prefix;
3887         if (*p == '?') {
3888                 match = strstr;
3889                 p++;
3890         }
3891
3892         found = NULL;
3893         while (jp) {
3894                 if (match(jp->ps[0].ps_cmd, p)) {
3895                         if (found)
3896                                 goto err;
3897                         found = jp;
3898                         err_msg = "%s: ambiguous";
3899                 }
3900                 jp = jp->prev_job;
3901         }
3902         if (!found)
3903                 goto err;
3904         jp = found;
3905
3906  gotit:
3907 #if JOBS
3908         err_msg = "job %s not created under job control";
3909         if (getctl && jp->jobctl == 0)
3910                 goto err;
3911 #endif
3912         return jp;
3913  err:
3914         ash_msg_and_raise_error(err_msg, name);
3915 }
3916
3917 /*
3918  * Mark a job structure as unused.
3919  */
3920 static void
3921 freejob(struct job *jp)
3922 {
3923         struct procstat *ps;
3924         int i;
3925
3926         INT_OFF;
3927         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3928                 if (ps->ps_cmd != nullstr)
3929                         free(ps->ps_cmd);
3930         }
3931         if (jp->ps != &jp->ps0)
3932                 free(jp->ps);
3933         jp->used = 0;
3934         set_curjob(jp, CUR_DELETE);
3935         INT_ON;
3936 }
3937
3938 #if JOBS
3939 static void
3940 xtcsetpgrp(int fd, pid_t pgrp)
3941 {
3942         if (tcsetpgrp(fd, pgrp))
3943                 ash_msg_and_raise_perror("can't set tty process group");
3944 }
3945
3946 /*
3947  * Turn job control on and off.
3948  *
3949  * Note:  This code assumes that the third arg to ioctl is a character
3950  * pointer, which is true on Berkeley systems but not System V.  Since
3951  * System V doesn't have job control yet, this isn't a problem now.
3952  *
3953  * Called with interrupts off.
3954  */
3955 static void
3956 setjobctl(int on)
3957 {
3958         int fd;
3959         int pgrp;
3960
3961         if (on == doing_jobctl || rootshell == 0)
3962                 return;
3963         if (on) {
3964                 int ofd;
3965                 ofd = fd = open(_PATH_TTY, O_RDWR);
3966                 if (fd < 0) {
3967         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3968          * That sometimes helps to acquire controlling tty.
3969          * Obviously, a workaround for bugs when someone
3970          * failed to provide a controlling tty to bash! :) */
3971                         fd = 2;
3972                         while (!isatty(fd))
3973                                 if (--fd < 0)
3974                                         goto out;
3975                 }
3976                 /* fd is a tty at this point */
3977                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
3978                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3979                         close(ofd);
3980                 if (fd < 0)
3981                         goto out; /* F_DUPFD failed */
3982                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
3983                         close_on_exec_on(fd);
3984                 while (1) { /* while we are in the background */
3985                         pgrp = tcgetpgrp(fd);
3986                         if (pgrp < 0) {
3987  out:
3988                                 ash_msg("can't access tty; job control turned off");
3989                                 mflag = on = 0;
3990                                 goto close;
3991                         }
3992                         if (pgrp == getpgrp())
3993                                 break;
3994                         killpg(0, SIGTTIN);
3995                 }
3996                 initialpgrp = pgrp;
3997
3998                 setsignal(SIGTSTP);
3999                 setsignal(SIGTTOU);
4000                 setsignal(SIGTTIN);
4001                 pgrp = rootpid;
4002                 setpgid(0, pgrp);
4003                 xtcsetpgrp(fd, pgrp);
4004         } else {
4005                 /* turning job control off */
4006                 fd = ttyfd;
4007                 pgrp = initialpgrp;
4008                 /* was xtcsetpgrp, but this can make exiting ash
4009                  * loop forever if pty is already deleted */
4010                 tcsetpgrp(fd, pgrp);
4011                 setpgid(0, pgrp);
4012                 setsignal(SIGTSTP);
4013                 setsignal(SIGTTOU);
4014                 setsignal(SIGTTIN);
4015  close:
4016                 if (fd >= 0)
4017                         close(fd);
4018                 fd = -1;
4019         }
4020         ttyfd = fd;
4021         doing_jobctl = on;
4022 }
4023
4024 static int FAST_FUNC
4025 killcmd(int argc, char **argv)
4026 {
4027         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4028                 int i = 1;
4029                 do {
4030                         if (argv[i][0] == '%') {
4031                                 /*
4032                                  * "kill %N" - job kill
4033                                  * Converting to pgrp / pid kill
4034                                  */
4035                                 struct job *jp;
4036                                 char *dst;
4037                                 int j, n;
4038
4039                                 jp = getjob(argv[i], 0);
4040                                 /*
4041                                  * In jobs started under job control, we signal
4042                                  * entire process group by kill -PGRP_ID.
4043                                  * This happens, f.e., in interactive shell.
4044                                  *
4045                                  * Otherwise, we signal each child via
4046                                  * kill PID1 PID2 PID3.
4047                                  * Testcases:
4048                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4049                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4050                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4051                                  */
4052                                 n = jp->nprocs; /* can't be 0 (I hope) */
4053                                 if (jp->jobctl)
4054                                         n = 1;
4055                                 dst = alloca(n * sizeof(int)*4);
4056                                 argv[i] = dst;
4057                                 for (j = 0; j < n; j++) {
4058                                         struct procstat *ps = &jp->ps[j];
4059                                         /* Skip non-running and not-stopped members
4060                                          * (i.e. dead members) of the job
4061                                          */
4062                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4063                                                 continue;
4064                                         /*
4065                                          * kill_main has matching code to expect
4066                                          * leading space. Needed to not confuse
4067                                          * negative pids with "kill -SIGNAL_NO" syntax
4068                                          */
4069                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4070                                 }
4071                                 *dst = '\0';
4072                         }
4073                 } while (argv[++i]);
4074         }
4075         return kill_main(argc, argv);
4076 }
4077
4078 static void
4079 showpipe(struct job *jp /*, FILE *out*/)
4080 {
4081         struct procstat *ps;
4082         struct procstat *psend;
4083
4084         psend = jp->ps + jp->nprocs;
4085         for (ps = jp->ps + 1; ps < psend; ps++)
4086                 printf(" | %s", ps->ps_cmd);
4087         newline_and_flush(stdout);
4088         flush_stdout_stderr();
4089 }
4090
4091
4092 static int
4093 restartjob(struct job *jp, int mode)
4094 {
4095         struct procstat *ps;
4096         int i;
4097         int status;
4098         pid_t pgid;
4099
4100         INT_OFF;
4101         if (jp->state == JOBDONE)
4102                 goto out;
4103         jp->state = JOBRUNNING;
4104         pgid = jp->ps[0].ps_pid;
4105         if (mode == FORK_FG) {
4106                 get_tty_state();
4107                 xtcsetpgrp(ttyfd, pgid);
4108         }
4109         killpg(pgid, SIGCONT);
4110         ps = jp->ps;
4111         i = jp->nprocs;
4112         do {
4113                 if (WIFSTOPPED(ps->ps_status)) {
4114                         ps->ps_status = -1;
4115                 }
4116                 ps++;
4117         } while (--i);
4118  out:
4119         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4120         INT_ON;
4121         return status;
4122 }
4123
4124 static int FAST_FUNC
4125 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4126 {
4127         struct job *jp;
4128         int mode;
4129         int retval;
4130
4131         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4132         nextopt(nullstr);
4133         argv = argptr;
4134         do {
4135                 jp = getjob(*argv, 1);
4136                 if (mode == FORK_BG) {
4137                         set_curjob(jp, CUR_RUNNING);
4138                         printf("[%d] ", jobno(jp));
4139                 }
4140                 out1str(jp->ps[0].ps_cmd);
4141                 showpipe(jp /*, stdout*/);
4142                 retval = restartjob(jp, mode);
4143         } while (*argv && *++argv);
4144         return retval;
4145 }
4146 #endif
4147
4148 static int
4149 sprint_status48(char *s, int status, int sigonly)
4150 {
4151         int col;
4152         int st;
4153
4154         col = 0;
4155         if (!WIFEXITED(status)) {
4156 #if JOBS
4157                 if (WIFSTOPPED(status))
4158                         st = WSTOPSIG(status);
4159                 else
4160 #endif
4161                         st = WTERMSIG(status);
4162                 if (sigonly) {
4163                         if (st == SIGINT || st == SIGPIPE)
4164                                 goto out;
4165 #if JOBS
4166                         if (WIFSTOPPED(status))
4167                                 goto out;
4168 #endif
4169                 }
4170                 st &= 0x7f;
4171 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4172                 col = fmtstr(s, 32, strsignal(st));
4173                 if (WCOREDUMP(status)) {
4174                         strcpy(s + col, " (core dumped)");
4175                         col += sizeof(" (core dumped)")-1;
4176                 }
4177         } else if (!sigonly) {
4178                 st = WEXITSTATUS(status);
4179                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4180         }
4181  out:
4182         return col;
4183 }
4184
4185 static int
4186 wait_block_or_sig(int *status)
4187 {
4188         int pid;
4189
4190         do {
4191                 sigset_t mask;
4192
4193                 /* Poll all children for changes in their state */
4194                 got_sigchld = 0;
4195                 /* if job control is active, accept stopped processes too */
4196                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4197                 if (pid != 0)
4198                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4199
4200                 /* Children exist, but none are ready. Sleep until interesting signal */
4201 #if 1
4202                 sigfillset(&mask);
4203                 sigprocmask(SIG_SETMASK, &mask, &mask);
4204                 while (!got_sigchld && !pending_sig)
4205                         sigsuspend(&mask);
4206                 sigprocmask(SIG_SETMASK, &mask, NULL);
4207 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4208                 while (!got_sigchld && !pending_sig)
4209                         pause();
4210 #endif
4211
4212                 /* If it was SIGCHLD, poll children again */
4213         } while (got_sigchld);
4214
4215         return pid;
4216 }
4217
4218 #define DOWAIT_NONBLOCK 0
4219 #define DOWAIT_BLOCK    1
4220 #define DOWAIT_BLOCK_OR_SIG 2
4221
4222 static int
4223 dowait(int block, struct job *job)
4224 {
4225         int pid;
4226         int status;
4227         struct job *jp;
4228         struct job *thisjob = NULL;
4229
4230         TRACE(("dowait(0x%x) called\n", block));
4231
4232         /* It's wrong to call waitpid() outside of INT_OFF region:
4233          * signal can arrive just after syscall return and handler can
4234          * longjmp away, losing stop/exit notification processing.
4235          * Thus, for "jobs" builtin, and for waiting for a fg job,
4236          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4237          *
4238          * However, for "wait" builtin it is wrong to simply call waitpid()
4239          * in INT_OFF region: "wait" needs to wait for any running job
4240          * to change state, but should exit on any trap too.
4241          * In INT_OFF region, a signal just before syscall entry can set
4242          * pending_sig variables, but we can't check them, and we would
4243          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4244          *
4245          * Because of this, we run inside INT_OFF, but use a special routine
4246          * which combines waitpid() and sigsuspend().
4247          * This is the reason why we need to have a handler for SIGCHLD:
4248          * SIG_DFL handler does not wake sigsuspend().
4249          */
4250         INT_OFF;
4251         if (block == DOWAIT_BLOCK_OR_SIG) {
4252                 pid = wait_block_or_sig(&status);
4253         } else {
4254                 int wait_flags = 0;
4255                 if (block == DOWAIT_NONBLOCK)
4256                         wait_flags = WNOHANG;
4257                 /* if job control is active, accept stopped processes too */
4258                 if (doing_jobctl)
4259                         wait_flags |= WUNTRACED;
4260                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4261                 pid = waitpid(-1, &status, wait_flags);
4262         }
4263         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4264                                 pid, status, errno, strerror(errno)));
4265         if (pid <= 0)
4266                 goto out;
4267
4268         thisjob = NULL;
4269         for (jp = curjob; jp; jp = jp->prev_job) {
4270                 int jobstate;
4271                 struct procstat *ps;
4272                 struct procstat *psend;
4273                 if (jp->state == JOBDONE)
4274                         continue;
4275                 jobstate = JOBDONE;
4276                 ps = jp->ps;
4277                 psend = ps + jp->nprocs;
4278                 do {
4279                         if (ps->ps_pid == pid) {
4280                                 TRACE(("Job %d: changing status of proc %d "
4281                                         "from 0x%x to 0x%x\n",
4282                                         jobno(jp), pid, ps->ps_status, status));
4283                                 ps->ps_status = status;
4284                                 thisjob = jp;
4285                         }
4286                         if (ps->ps_status == -1)
4287                                 jobstate = JOBRUNNING;
4288 #if JOBS
4289                         if (jobstate == JOBRUNNING)
4290                                 continue;
4291                         if (WIFSTOPPED(ps->ps_status)) {
4292                                 jp->stopstatus = ps->ps_status;
4293                                 jobstate = JOBSTOPPED;
4294                         }
4295 #endif
4296                 } while (++ps < psend);
4297                 if (!thisjob)
4298                         continue;
4299
4300                 /* Found the job where one of its processes changed its state.
4301                  * Is there at least one live and running process in this job? */
4302                 if (jobstate != JOBRUNNING) {
4303                         /* No. All live processes in the job are stopped
4304                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4305                          */
4306                         thisjob->changed = 1;
4307                         if (thisjob->state != jobstate) {
4308                                 TRACE(("Job %d: changing state from %d to %d\n",
4309                                         jobno(thisjob), thisjob->state, jobstate));
4310                                 thisjob->state = jobstate;
4311 #if JOBS
4312                                 if (jobstate == JOBSTOPPED)
4313                                         set_curjob(thisjob, CUR_STOPPED);
4314 #endif
4315                         }
4316                 }
4317                 goto out;
4318         }
4319         /* The process wasn't found in job list */
4320 #if JOBS
4321         if (!WIFSTOPPED(status))
4322                 jobless--;
4323 #endif
4324  out:
4325         INT_ON;
4326
4327         if (thisjob && thisjob == job) {
4328                 char s[48 + 1];
4329                 int len;
4330
4331                 len = sprint_status48(s, status, 1);
4332                 if (len) {
4333                         s[len] = '\n';
4334                         s[len + 1] = '\0';
4335                         out2str(s);
4336                 }
4337         }
4338         return pid;
4339 }
4340
4341 #if JOBS
4342 static void
4343 showjob(struct job *jp, int mode)
4344 {
4345         struct procstat *ps;
4346         struct procstat *psend;
4347         int col;
4348         int indent_col;
4349         char s[16 + 16 + 48];
4350         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4351
4352         ps = jp->ps;
4353
4354         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4355                 /* just output process (group) id of pipeline */
4356                 fprintf(out, "%d\n", ps->ps_pid);
4357                 return;
4358         }
4359
4360         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4361         indent_col = col;
4362
4363         if (jp == curjob)
4364                 s[col - 3] = '+';
4365         else if (curjob && jp == curjob->prev_job)
4366                 s[col - 3] = '-';
4367
4368         if (mode & SHOW_PIDS)
4369                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4370
4371         psend = ps + jp->nprocs;
4372
4373         if (jp->state == JOBRUNNING) {
4374                 strcpy(s + col, "Running");
4375                 col += sizeof("Running") - 1;
4376         } else {
4377                 int status = psend[-1].ps_status;
4378                 if (jp->state == JOBSTOPPED)
4379                         status = jp->stopstatus;
4380                 col += sprint_status48(s + col, status, 0);
4381         }
4382         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4383
4384         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4385          * or prints several "PID             | <cmdN>" lines,
4386          * depending on SHOW_PIDS bit.
4387          * We do not print status of individual processes
4388          * between PID and <cmdN>. bash does it, but not very well:
4389          * first line shows overall job status, not process status,
4390          * making it impossible to know 1st process status.
4391          */
4392         goto start;
4393         do {
4394                 /* for each process */
4395                 s[0] = '\0';
4396                 col = 33;
4397                 if (mode & SHOW_PIDS)
4398                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4399  start:
4400                 fprintf(out, "%s%*c%s%s",
4401                                 s,
4402                                 33 - col >= 0 ? 33 - col : 0, ' ',
4403                                 ps == jp->ps ? "" : "| ",
4404                                 ps->ps_cmd
4405                 );
4406         } while (++ps != psend);
4407         newline_and_flush(out);
4408
4409         jp->changed = 0;
4410
4411         if (jp->state == JOBDONE) {
4412                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4413                 freejob(jp);
4414         }
4415 }
4416
4417 /*
4418  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4419  * statuses have changed since the last call to showjobs.
4420  */
4421 static void
4422 showjobs(int mode)
4423 {
4424         struct job *jp;
4425
4426         TRACE(("showjobs(0x%x) called\n", mode));
4427
4428         /* Handle all finished jobs */
4429         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4430                 continue;
4431
4432         for (jp = curjob; jp; jp = jp->prev_job) {
4433                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4434                         showjob(jp, mode);
4435                 }
4436         }
4437 }
4438
4439 static int FAST_FUNC
4440 jobscmd(int argc UNUSED_PARAM, char **argv)
4441 {
4442         int mode, m;
4443
4444         mode = 0;
4445         while ((m = nextopt("lp")) != '\0') {
4446                 if (m == 'l')
4447                         mode |= SHOW_PIDS;
4448                 else
4449                         mode |= SHOW_ONLY_PGID;
4450         }
4451
4452         argv = argptr;
4453         if (*argv) {
4454                 do
4455                         showjob(getjob(*argv, 0), mode);
4456                 while (*++argv);
4457         } else {
4458                 showjobs(mode);
4459         }
4460
4461         return 0;
4462 }
4463 #endif /* JOBS */
4464
4465 /* Called only on finished or stopped jobs (no members are running) */
4466 static int
4467 getstatus(struct job *job)
4468 {
4469         int status;
4470         int retval;
4471         struct procstat *ps;
4472
4473         /* Fetch last member's status */
4474         ps = job->ps + job->nprocs - 1;
4475         status = ps->ps_status;
4476         if (pipefail) {
4477                 /* "set -o pipefail" mode: use last _nonzero_ status */
4478                 while (status == 0 && --ps >= job->ps)
4479                         status = ps->ps_status;
4480         }
4481
4482         retval = WEXITSTATUS(status);
4483         if (!WIFEXITED(status)) {
4484 #if JOBS
4485                 retval = WSTOPSIG(status);
4486                 if (!WIFSTOPPED(status))
4487 #endif
4488                 {
4489                         /* XXX: limits number of signals */
4490                         retval = WTERMSIG(status);
4491 #if JOBS
4492                         if (retval == SIGINT)
4493                                 job->sigint = 1;
4494 #endif
4495                 }
4496                 retval += 128;
4497         }
4498         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4499                 jobno(job), job->nprocs, status, retval));
4500         return retval;
4501 }
4502
4503 static int FAST_FUNC
4504 waitcmd(int argc UNUSED_PARAM, char **argv)
4505 {
4506         struct job *job;
4507         int retval;
4508         struct job *jp;
4509
4510         nextopt(nullstr);
4511         retval = 0;
4512
4513         argv = argptr;
4514         if (!*argv) {
4515                 /* wait for all jobs */
4516                 for (;;) {
4517                         jp = curjob;
4518                         while (1) {
4519                                 if (!jp) /* no running procs */
4520                                         goto ret;
4521                                 if (jp->state == JOBRUNNING)
4522                                         break;
4523                                 jp->waited = 1;
4524                                 jp = jp->prev_job;
4525                         }
4526         /* man bash:
4527          * "When bash is waiting for an asynchronous command via
4528          * the wait builtin, the reception of a signal for which a trap
4529          * has been set will cause the wait builtin to return immediately
4530          * with an exit status greater than 128, immediately after which
4531          * the trap is executed."
4532          */
4533                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4534         /* if child sends us a signal *and immediately exits*,
4535          * dowait() returns pid > 0. Check this case,
4536          * not "if (dowait() < 0)"!
4537          */
4538                         if (pending_sig)
4539                                 goto sigout;
4540                 }
4541         }
4542
4543         retval = 127;
4544         do {
4545                 if (**argv != '%') {
4546                         pid_t pid = number(*argv);
4547                         job = curjob;
4548                         while (1) {
4549                                 if (!job)
4550                                         goto repeat;
4551                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4552                                         break;
4553                                 job = job->prev_job;
4554                         }
4555                 } else {
4556                         job = getjob(*argv, 0);
4557                 }
4558                 /* loop until process terminated or stopped */
4559                 while (job->state == JOBRUNNING) {
4560                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4561                         if (pending_sig)
4562                                 goto sigout;
4563                 }
4564                 job->waited = 1;
4565                 retval = getstatus(job);
4566  repeat: ;
4567         } while (*++argv);
4568
4569  ret:
4570         return retval;
4571  sigout:
4572         retval = 128 + pending_sig;
4573         return retval;
4574 }
4575
4576 static struct job *
4577 growjobtab(void)
4578 {
4579         size_t len;
4580         ptrdiff_t offset;
4581         struct job *jp, *jq;
4582
4583         len = njobs * sizeof(*jp);
4584         jq = jobtab;
4585         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4586
4587         offset = (char *)jp - (char *)jq;
4588         if (offset) {
4589                 /* Relocate pointers */
4590                 size_t l = len;
4591
4592                 jq = (struct job *)((char *)jq + l);
4593                 while (l) {
4594                         l -= sizeof(*jp);
4595                         jq--;
4596 #define joff(p) ((struct job *)((char *)(p) + l))
4597 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4598                         if (joff(jp)->ps == &jq->ps0)
4599                                 jmove(joff(jp)->ps);
4600                         if (joff(jp)->prev_job)
4601                                 jmove(joff(jp)->prev_job);
4602                 }
4603                 if (curjob)
4604                         jmove(curjob);
4605 #undef joff
4606 #undef jmove
4607         }
4608
4609         njobs += 4;
4610         jobtab = jp;
4611         jp = (struct job *)((char *)jp + len);
4612         jq = jp + 3;
4613         do {
4614                 jq->used = 0;
4615         } while (--jq >= jp);
4616         return jp;
4617 }
4618
4619 /*
4620  * Return a new job structure.
4621  * Called with interrupts off.
4622  */
4623 static struct job *
4624 makejob(/*union node *node,*/ int nprocs)
4625 {
4626         int i;
4627         struct job *jp;
4628
4629         for (i = njobs, jp = jobtab; ; jp++) {
4630                 if (--i < 0) {
4631                         jp = growjobtab();
4632                         break;
4633                 }
4634                 if (jp->used == 0)
4635                         break;
4636                 if (jp->state != JOBDONE || !jp->waited)
4637                         continue;
4638 #if JOBS
4639                 if (doing_jobctl)
4640                         continue;
4641 #endif
4642                 freejob(jp);
4643                 break;
4644         }
4645         memset(jp, 0, sizeof(*jp));
4646 #if JOBS
4647         /* jp->jobctl is a bitfield.
4648          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4649         if (doing_jobctl)
4650                 jp->jobctl = 1;
4651 #endif
4652         jp->prev_job = curjob;
4653         curjob = jp;
4654         jp->used = 1;
4655         jp->ps = &jp->ps0;
4656         if (nprocs > 1) {
4657                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4658         }
4659         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4660                                 jobno(jp)));
4661         return jp;
4662 }
4663
4664 #if JOBS
4665 /*
4666  * Return a string identifying a command (to be printed by the
4667  * jobs command).
4668  */
4669 static char *cmdnextc;
4670
4671 static void
4672 cmdputs(const char *s)
4673 {
4674         static const char vstype[VSTYPE + 1][3] = {
4675                 "", "}", "-", "+", "?", "=",
4676                 "%", "%%", "#", "##"
4677                 IF_BASH_SUBSTR(, ":")
4678                 IF_BASH_PATTERN_SUBST(, "/", "//")
4679         };
4680
4681         const char *p, *str;
4682         char cc[2];
4683         char *nextc;
4684         unsigned char c;
4685         unsigned char subtype = 0;
4686         int quoted = 0;
4687
4688         cc[1] = '\0';
4689         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4690         p = s;
4691         while ((c = *p++) != '\0') {
4692                 str = NULL;
4693                 switch (c) {
4694                 case CTLESC:
4695                         c = *p++;
4696                         break;
4697                 case CTLVAR:
4698                         subtype = *p++;
4699                         if ((subtype & VSTYPE) == VSLENGTH)
4700                                 str = "${#";
4701                         else
4702                                 str = "${";
4703                         goto dostr;
4704                 case CTLENDVAR:
4705                         str = "\"}" + !(quoted & 1);
4706                         quoted >>= 1;
4707                         subtype = 0;
4708                         goto dostr;
4709                 case CTLBACKQ:
4710                         str = "$(...)";
4711                         goto dostr;
4712 #if ENABLE_FEATURE_SH_MATH
4713                 case CTLARI:
4714                         str = "$((";
4715                         goto dostr;
4716                 case CTLENDARI:
4717                         str = "))";
4718                         goto dostr;
4719 #endif
4720                 case CTLQUOTEMARK:
4721                         quoted ^= 1;
4722                         c = '"';
4723                         break;
4724                 case '=':
4725                         if (subtype == 0)
4726                                 break;
4727                         if ((subtype & VSTYPE) != VSNORMAL)
4728                                 quoted <<= 1;
4729                         str = vstype[subtype & VSTYPE];
4730                         if (subtype & VSNUL)
4731                                 c = ':';
4732                         else
4733                                 goto checkstr;
4734                         break;
4735                 case '\'':
4736                 case '\\':
4737                 case '"':
4738                 case '$':
4739                         /* These can only happen inside quotes */
4740                         cc[0] = c;
4741                         str = cc;
4742 //FIXME:
4743 // $ true $$ &
4744 // $ <cr>
4745 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4746                         c = '\\';
4747                         break;
4748                 default:
4749                         break;
4750                 }
4751                 USTPUTC(c, nextc);
4752  checkstr:
4753                 if (!str)
4754                         continue;
4755  dostr:
4756                 while ((c = *str++) != '\0') {
4757                         USTPUTC(c, nextc);
4758                 }
4759         } /* while *p++ not NUL */
4760
4761         if (quoted & 1) {
4762                 USTPUTC('"', nextc);
4763         }
4764         *nextc = 0;
4765         cmdnextc = nextc;
4766 }
4767
4768 /* cmdtxt() and cmdlist() call each other */
4769 static void cmdtxt(union node *n);
4770
4771 static void
4772 cmdlist(union node *np, int sep)
4773 {
4774         for (; np; np = np->narg.next) {
4775                 if (!sep)
4776                         cmdputs(" ");
4777                 cmdtxt(np);
4778                 if (sep && np->narg.next)
4779                         cmdputs(" ");
4780         }
4781 }
4782
4783 static void
4784 cmdtxt(union node *n)
4785 {
4786         union node *np;
4787         struct nodelist *lp;
4788         const char *p;
4789
4790         if (!n)
4791                 return;
4792         switch (n->type) {
4793         default:
4794 #if DEBUG
4795                 abort();
4796 #endif
4797         case NPIPE:
4798                 lp = n->npipe.cmdlist;
4799                 for (;;) {
4800                         cmdtxt(lp->n);
4801                         lp = lp->next;
4802                         if (!lp)
4803                                 break;
4804                         cmdputs(" | ");
4805                 }
4806                 break;
4807         case NSEMI:
4808                 p = "; ";
4809                 goto binop;
4810         case NAND:
4811                 p = " && ";
4812                 goto binop;
4813         case NOR:
4814                 p = " || ";
4815  binop:
4816                 cmdtxt(n->nbinary.ch1);
4817                 cmdputs(p);
4818                 n = n->nbinary.ch2;
4819                 goto donode;
4820         case NREDIR:
4821         case NBACKGND:
4822                 n = n->nredir.n;
4823                 goto donode;
4824         case NNOT:
4825                 cmdputs("!");
4826                 n = n->nnot.com;
4827  donode:
4828                 cmdtxt(n);
4829                 break;
4830         case NIF:
4831                 cmdputs("if ");
4832                 cmdtxt(n->nif.test);
4833                 cmdputs("; then ");
4834                 if (n->nif.elsepart) {
4835                         cmdtxt(n->nif.ifpart);
4836                         cmdputs("; else ");
4837                         n = n->nif.elsepart;
4838                 } else {
4839                         n = n->nif.ifpart;
4840                 }
4841                 p = "; fi";
4842                 goto dotail;
4843         case NSUBSHELL:
4844                 cmdputs("(");
4845                 n = n->nredir.n;
4846                 p = ")";
4847                 goto dotail;
4848         case NWHILE:
4849                 p = "while ";
4850                 goto until;
4851         case NUNTIL:
4852                 p = "until ";
4853  until:
4854                 cmdputs(p);
4855                 cmdtxt(n->nbinary.ch1);
4856                 n = n->nbinary.ch2;
4857                 p = "; done";
4858  dodo:
4859                 cmdputs("; do ");
4860  dotail:
4861                 cmdtxt(n);
4862                 goto dotail2;
4863         case NFOR:
4864                 cmdputs("for ");
4865                 cmdputs(n->nfor.var);
4866                 cmdputs(" in ");
4867                 cmdlist(n->nfor.args, 1);
4868                 n = n->nfor.body;
4869                 p = "; done";
4870                 goto dodo;
4871         case NDEFUN:
4872                 cmdputs(n->ndefun.text);
4873                 p = "() { ... }";
4874                 goto dotail2;
4875         case NCMD:
4876                 cmdlist(n->ncmd.args, 1);
4877                 cmdlist(n->ncmd.redirect, 0);
4878                 break;
4879         case NARG:
4880                 p = n->narg.text;
4881  dotail2:
4882                 cmdputs(p);
4883                 break;
4884         case NHERE:
4885         case NXHERE:
4886                 p = "<<...";
4887                 goto dotail2;
4888         case NCASE:
4889                 cmdputs("case ");
4890                 cmdputs(n->ncase.expr->narg.text);
4891                 cmdputs(" in ");
4892                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4893                         cmdtxt(np->nclist.pattern);
4894                         cmdputs(") ");
4895                         cmdtxt(np->nclist.body);
4896                         cmdputs(";; ");
4897                 }
4898                 p = "esac";
4899                 goto dotail2;
4900         case NTO:
4901                 p = ">";
4902                 goto redir;
4903         case NCLOBBER:
4904                 p = ">|";
4905                 goto redir;
4906         case NAPPEND:
4907                 p = ">>";
4908                 goto redir;
4909 #if BASH_REDIR_OUTPUT
4910         case NTO2:
4911 #endif
4912         case NTOFD:
4913                 p = ">&";
4914                 goto redir;
4915         case NFROM:
4916                 p = "<";
4917                 goto redir;
4918         case NFROMFD:
4919                 p = "<&";
4920                 goto redir;
4921         case NFROMTO:
4922                 p = "<>";
4923  redir:
4924                 cmdputs(utoa(n->nfile.fd));
4925                 cmdputs(p);
4926                 if (n->type == NTOFD || n->type == NFROMFD) {
4927                         if (n->ndup.dupfd >= 0)
4928                                 cmdputs(utoa(n->ndup.dupfd));
4929                         else
4930                                 cmdputs("-");
4931                         break;
4932                 }
4933                 n = n->nfile.fname;
4934                 goto donode;
4935         }
4936 }
4937
4938 static char *
4939 commandtext(union node *n)
4940 {
4941         char *name;
4942
4943         STARTSTACKSTR(cmdnextc);
4944         cmdtxt(n);
4945         name = stackblock();
4946         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4947         return ckstrdup(name);
4948 }
4949 #endif /* JOBS */
4950
4951 /*
4952  * Fork off a subshell.  If we are doing job control, give the subshell its
4953  * own process group.  Jp is a job structure that the job is to be added to.
4954  * N is the command that will be evaluated by the child.  Both jp and n may
4955  * be NULL.  The mode parameter can be one of the following:
4956  *      FORK_FG - Fork off a foreground process.
4957  *      FORK_BG - Fork off a background process.
4958  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4959  *                   process group even if job control is on.
4960  *
4961  * When job control is turned off, background processes have their standard
4962  * input redirected to /dev/null (except for the second and later processes
4963  * in a pipeline).
4964  *
4965  * Called with interrupts off.
4966  */
4967 /*
4968  * Clear traps on a fork.
4969  */
4970 static void
4971 clear_traps(void)
4972 {
4973         char **tp;
4974
4975         INT_OFF;
4976         for (tp = trap; tp < &trap[NSIG]; tp++) {
4977                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4978                         if (trap_ptr == trap)
4979                                 free(*tp);
4980                         /* else: it "belongs" to trap_ptr vector, don't free */
4981                         *tp = NULL;
4982                         if ((tp - trap) != 0)
4983                                 setsignal(tp - trap);
4984                 }
4985         }
4986         may_have_traps = 0;
4987         INT_ON;
4988 }
4989
4990 /* Lives far away from here, needed for forkchild */
4991 static void closescript(void);
4992
4993 /* Called after fork(), in child */
4994 /* jp and n are NULL when called by openhere() for heredoc support */
4995 static NOINLINE void
4996 forkchild(struct job *jp, union node *n, int mode)
4997 {
4998         int oldlvl;
4999
5000         TRACE(("Child shell %d\n", getpid()));
5001         oldlvl = shlvl;
5002         shlvl++;
5003
5004         /* man bash: "Non-builtin commands run by bash have signal handlers
5005          * set to the values inherited by the shell from its parent".
5006          * Do we do it correctly? */
5007
5008         closescript();
5009
5010         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5011          && n && n->type == NCMD        /* is it single cmd? */
5012         /* && n->ncmd.args->type == NARG - always true? */
5013          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5014          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5015         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5016         ) {
5017                 TRACE(("Trap hack\n"));
5018                 /* Awful hack for `trap` or $(trap).
5019                  *
5020                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5021                  * contains an example where "trap" is executed in a subshell:
5022                  *
5023                  * save_traps=$(trap)
5024                  * ...
5025                  * eval "$save_traps"
5026                  *
5027                  * Standard does not say that "trap" in subshell shall print
5028                  * parent shell's traps. It only says that its output
5029                  * must have suitable form, but then, in the above example
5030                  * (which is not supposed to be normative), it implies that.
5031                  *
5032                  * bash (and probably other shell) does implement it
5033                  * (traps are reset to defaults, but "trap" still shows them),
5034                  * but as a result, "trap" logic is hopelessly messed up:
5035                  *
5036                  * # trap
5037                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5038                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5039                  * # true | trap   <--- trap is in subshell - no output (ditto)
5040                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5041                  * trap -- 'echo Ho' SIGWINCH
5042                  * # echo `(trap)`         <--- in subshell in subshell - output
5043                  * trap -- 'echo Ho' SIGWINCH
5044                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5045                  * trap -- 'echo Ho' SIGWINCH
5046                  *
5047                  * The rules when to forget and when to not forget traps
5048                  * get really complex and nonsensical.
5049                  *
5050                  * Our solution: ONLY bare $(trap) or `trap` is special.
5051                  */
5052                 /* Save trap handler strings for trap builtin to print */
5053                 trap_ptr = xmemdup(trap, sizeof(trap));
5054                 /* Fall through into clearing traps */
5055         }
5056         clear_traps();
5057 #if JOBS
5058         /* do job control only in root shell */
5059         doing_jobctl = 0;
5060         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5061                 pid_t pgrp;
5062
5063                 if (jp->nprocs == 0)
5064                         pgrp = getpid();
5065                 else
5066                         pgrp = jp->ps[0].ps_pid;
5067                 /* this can fail because we are doing it in the parent also */
5068                 setpgid(0, pgrp);
5069                 if (mode == FORK_FG)
5070                         xtcsetpgrp(ttyfd, pgrp);
5071                 setsignal(SIGTSTP);
5072                 setsignal(SIGTTOU);
5073         } else
5074 #endif
5075         if (mode == FORK_BG) {
5076                 /* man bash: "When job control is not in effect,
5077                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5078                 ignoresig(SIGINT);
5079                 ignoresig(SIGQUIT);
5080                 if (jp->nprocs == 0) {
5081                         close(0);
5082                         if (open(bb_dev_null, O_RDONLY) != 0)
5083                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5084                 }
5085         }
5086         if (oldlvl == 0) {
5087                 if (iflag) { /* why if iflag only? */
5088                         setsignal(SIGINT);
5089                         setsignal(SIGTERM);
5090                 }
5091                 /* man bash:
5092                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5093                  * commands run by bash have signal handlers
5094                  * set to the values inherited by the shell
5095                  * from its parent".
5096                  * Take care of the second rule: */
5097                 setsignal(SIGQUIT);
5098         }
5099 #if JOBS
5100         if (n && n->type == NCMD
5101          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5102         ) {
5103                 TRACE(("Job hack\n"));
5104                 /* "jobs": we do not want to clear job list for it,
5105                  * instead we remove only _its_ own_ job from job list.
5106                  * This makes "jobs .... | cat" more useful.
5107                  */
5108                 freejob(curjob);
5109                 return;
5110         }
5111 #endif
5112         for (jp = curjob; jp; jp = jp->prev_job)
5113                 freejob(jp);
5114         jobless = 0;
5115 }
5116
5117 /* Called after fork(), in parent */
5118 #if !JOBS
5119 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5120 #endif
5121 static void
5122 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5123 {
5124         TRACE(("In parent shell: child = %d\n", pid));
5125         if (!jp) {
5126                 /* jp is NULL when called by openhere() for heredoc support */
5127                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5128                         continue;
5129                 jobless++;
5130                 return;
5131         }
5132 #if JOBS
5133         if (mode != FORK_NOJOB && jp->jobctl) {
5134                 int pgrp;
5135
5136                 if (jp->nprocs == 0)
5137                         pgrp = pid;
5138                 else
5139                         pgrp = jp->ps[0].ps_pid;
5140                 /* This can fail because we are doing it in the child also */
5141                 setpgid(pid, pgrp);
5142         }
5143 #endif
5144         if (mode == FORK_BG) {
5145                 backgndpid = pid;               /* set $! */
5146                 set_curjob(jp, CUR_RUNNING);
5147         }
5148         if (jp) {
5149                 struct procstat *ps = &jp->ps[jp->nprocs++];
5150                 ps->ps_pid = pid;
5151                 ps->ps_status = -1;
5152                 ps->ps_cmd = nullstr;
5153 #if JOBS
5154                 if (doing_jobctl && n)
5155                         ps->ps_cmd = commandtext(n);
5156 #endif
5157         }
5158 }
5159
5160 /* jp and n are NULL when called by openhere() for heredoc support */
5161 static int
5162 forkshell(struct job *jp, union node *n, int mode)
5163 {
5164         int pid;
5165
5166         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5167         pid = fork();
5168         if (pid < 0) {
5169                 TRACE(("Fork failed, errno=%d", errno));
5170                 if (jp)
5171                         freejob(jp);
5172                 ash_msg_and_raise_perror("can't fork");
5173         }
5174         if (pid == 0) {
5175                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5176                 forkchild(jp, n, mode);
5177         } else {
5178                 forkparent(jp, n, mode, pid);
5179         }
5180         return pid;
5181 }
5182
5183 /*
5184  * Wait for job to finish.
5185  *
5186  * Under job control we have the problem that while a child process
5187  * is running interrupts generated by the user are sent to the child
5188  * but not to the shell.  This means that an infinite loop started by
5189  * an interactive user may be hard to kill.  With job control turned off,
5190  * an interactive user may place an interactive program inside a loop.
5191  * If the interactive program catches interrupts, the user doesn't want
5192  * these interrupts to also abort the loop.  The approach we take here
5193  * is to have the shell ignore interrupt signals while waiting for a
5194  * foreground process to terminate, and then send itself an interrupt
5195  * signal if the child process was terminated by an interrupt signal.
5196  * Unfortunately, some programs want to do a bit of cleanup and then
5197  * exit on interrupt; unless these processes terminate themselves by
5198  * sending a signal to themselves (instead of calling exit) they will
5199  * confuse this approach.
5200  *
5201  * Called with interrupts off.
5202  */
5203 static int
5204 waitforjob(struct job *jp)
5205 {
5206         int st;
5207
5208         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5209
5210         INT_OFF;
5211         while (jp->state == JOBRUNNING) {
5212                 /* In non-interactive shells, we _can_ get
5213                  * a keyboard signal here and be EINTRed,
5214                  * but we just loop back, waiting for command to complete.
5215                  *
5216                  * man bash:
5217                  * "If bash is waiting for a command to complete and receives
5218                  * a signal for which a trap has been set, the trap
5219                  * will not be executed until the command completes."
5220                  *
5221                  * Reality is that even if trap is not set, bash
5222                  * will not act on the signal until command completes.
5223                  * Try this. sleep5intoff.c:
5224                  * #include <signal.h>
5225                  * #include <unistd.h>
5226                  * int main() {
5227                  *         sigset_t set;
5228                  *         sigemptyset(&set);
5229                  *         sigaddset(&set, SIGINT);
5230                  *         sigaddset(&set, SIGQUIT);
5231                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5232                  *         sleep(5);
5233                  *         return 0;
5234                  * }
5235                  * $ bash -c './sleep5intoff; echo hi'
5236                  * ^C^C^C^C <--- pressing ^C once a second
5237                  * $ _
5238                  * $ bash -c './sleep5intoff; echo hi'
5239                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5240                  * $ _
5241                  */
5242                 dowait(DOWAIT_BLOCK, jp);
5243         }
5244         INT_ON;
5245
5246         st = getstatus(jp);
5247 #if JOBS
5248         if (jp->jobctl) {
5249                 xtcsetpgrp(ttyfd, rootpid);
5250                 restore_tty_if_stopped_or_signaled(jp);
5251
5252                 /*
5253                  * This is truly gross.
5254                  * If we're doing job control, then we did a TIOCSPGRP which
5255                  * caused us (the shell) to no longer be in the controlling
5256                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5257                  * intuit from the subprocess exit status whether a SIGINT
5258                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5259                  */
5260                 if (jp->sigint) /* TODO: do the same with all signals */
5261                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5262         }
5263         if (jp->state == JOBDONE)
5264 #endif
5265                 freejob(jp);
5266         return st;
5267 }
5268
5269 /*
5270  * return 1 if there are stopped jobs, otherwise 0
5271  */
5272 static int
5273 stoppedjobs(void)
5274 {
5275         struct job *jp;
5276         int retval;
5277
5278         retval = 0;
5279         if (job_warning)
5280                 goto out;
5281         jp = curjob;
5282         if (jp && jp->state == JOBSTOPPED) {
5283                 out2str("You have stopped jobs.\n");
5284                 job_warning = 2;
5285                 retval++;
5286         }
5287  out:
5288         return retval;
5289 }
5290
5291
5292 /*
5293  * Code for dealing with input/output redirection.
5294  */
5295
5296 #undef EMPTY
5297 #undef CLOSED
5298 #define EMPTY -2                /* marks an unused slot in redirtab */
5299 #define CLOSED -1               /* marks a slot of previously-closed fd */
5300
5301 /*
5302  * Handle here documents.  Normally we fork off a process to write the
5303  * data to a pipe.  If the document is short, we can stuff the data in
5304  * the pipe without forking.
5305  */
5306 /* openhere needs this forward reference */
5307 static void expandhere(union node *arg, int fd);
5308 static int
5309 openhere(union node *redir)
5310 {
5311         int pip[2];
5312         size_t len = 0;
5313
5314         if (pipe(pip) < 0)
5315                 ash_msg_and_raise_perror("can't create pipe");
5316         if (redir->type == NHERE) {
5317                 len = strlen(redir->nhere.doc->narg.text);
5318                 if (len <= PIPE_BUF) {
5319                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5320                         goto out;
5321                 }
5322         }
5323         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5324                 /* child */
5325                 close(pip[0]);
5326                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5327                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5328                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5329                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5330                 signal(SIGPIPE, SIG_DFL);
5331                 if (redir->type == NHERE)
5332                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5333                 else /* NXHERE */
5334                         expandhere(redir->nhere.doc, pip[1]);
5335                 _exit(EXIT_SUCCESS);
5336         }
5337  out:
5338         close(pip[1]);
5339         return pip[0];
5340 }
5341
5342 static int
5343 openredirect(union node *redir)
5344 {
5345         struct stat sb;
5346         char *fname;
5347         int f;
5348
5349         switch (redir->nfile.type) {
5350 /* Can't happen, our single caller does this itself */
5351 //      case NTOFD:
5352 //      case NFROMFD:
5353 //              return -1;
5354         case NHERE:
5355         case NXHERE:
5356                 return openhere(redir);
5357         }
5358
5359         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5360          * allocated space. Do it only when we know it is safe.
5361          */
5362         fname = redir->nfile.expfname;
5363
5364         switch (redir->nfile.type) {
5365         default:
5366 #if DEBUG
5367                 abort();
5368 #endif
5369         case NFROM:
5370                 f = open(fname, O_RDONLY);
5371                 if (f < 0)
5372                         goto eopen;
5373                 break;
5374         case NFROMTO:
5375                 f = open(fname, O_RDWR|O_CREAT, 0666);
5376                 if (f < 0)
5377                         goto ecreate;
5378                 break;
5379         case NTO:
5380 #if BASH_REDIR_OUTPUT
5381         case NTO2:
5382 #endif
5383                 /* Take care of noclobber mode. */
5384                 if (Cflag) {
5385                         if (stat(fname, &sb) < 0) {
5386                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5387                                 if (f < 0)
5388                                         goto ecreate;
5389                         } else if (!S_ISREG(sb.st_mode)) {
5390                                 f = open(fname, O_WRONLY, 0666);
5391                                 if (f < 0)
5392                                         goto ecreate;
5393                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5394                                         close(f);
5395                                         errno = EEXIST;
5396                                         goto ecreate;
5397                                 }
5398                         } else {
5399                                 errno = EEXIST;
5400                                 goto ecreate;
5401                         }
5402                         break;
5403                 }
5404                 /* FALLTHROUGH */
5405         case NCLOBBER:
5406                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5407                 if (f < 0)
5408                         goto ecreate;
5409                 break;
5410         case NAPPEND:
5411                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5412                 if (f < 0)
5413                         goto ecreate;
5414                 break;
5415         }
5416
5417         return f;
5418  ecreate:
5419         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5420  eopen:
5421         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5422 }
5423
5424 /*
5425  * Copy a file descriptor to be >= 10. Throws exception on error.
5426  */
5427 static int
5428 savefd(int from)
5429 {
5430         int newfd;
5431         int err;
5432
5433         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5434         err = newfd < 0 ? errno : 0;
5435         if (err != EBADF) {
5436                 if (err)
5437                         ash_msg_and_raise_perror("%d", from);
5438                 close(from);
5439                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5440                         close_on_exec_on(newfd);
5441         }
5442
5443         return newfd;
5444 }
5445 static int
5446 dup2_or_raise(int from, int to)
5447 {
5448         int newfd;
5449
5450         newfd = (from != to) ? dup2(from, to) : to;
5451         if (newfd < 0) {
5452                 /* Happens when source fd is not open: try "echo >&99" */
5453                 ash_msg_and_raise_perror("%d", from);
5454         }
5455         return newfd;
5456 }
5457 static int
5458 dup_CLOEXEC(int fd, int avoid_fd)
5459 {
5460         int newfd;
5461  repeat:
5462         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5463         if (newfd >= 0) {
5464                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5465                         close_on_exec_on(newfd);
5466         } else { /* newfd < 0 */
5467                 if (errno == EBUSY)
5468                         goto repeat;
5469                 if (errno == EINTR)
5470                         goto repeat;
5471         }
5472         return newfd;
5473 }
5474 static int
5475 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5476 {
5477         int newfd;
5478  repeat:
5479         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5480         if (newfd < 0) {
5481                 if (errno == EBUSY)
5482                         goto repeat;
5483                 if (errno == EINTR)
5484                         goto repeat;
5485                 /* fd was not open? */
5486                 if (errno == EBADF)
5487                         return fd;
5488                 ash_msg_and_raise_perror("%d", newfd);
5489         }
5490         if (F_DUPFD_CLOEXEC == F_DUPFD)
5491                 close_on_exec_on(newfd);
5492         close(fd);
5493         return newfd;
5494 }
5495
5496 /* Struct def and variable are moved down to the first usage site */
5497 struct squirrel {
5498         int orig_fd;
5499         int moved_to;
5500 };
5501 struct redirtab {
5502         struct redirtab *next;
5503         int pair_count;
5504         struct squirrel two_fd[];
5505 };
5506 #define redirlist (G_var.redirlist)
5507
5508 static void
5509 add_squirrel_closed(struct redirtab *sq, int fd)
5510 {
5511         int i;
5512
5513         if (!sq)
5514                 return;
5515
5516         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5517                 /* If we collide with an already moved fd... */
5518                 if (fd == sq->two_fd[i].orig_fd) {
5519                         /* Examples:
5520                          * "echo 3>FILE 3>&- 3>FILE"
5521                          * "echo 3>&- 3>FILE"
5522                          * No need for last redirect to insert
5523                          * another "need to close 3" indicator.
5524                          */
5525                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5526                         return;
5527                 }
5528         }
5529         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5530         sq->two_fd[i].orig_fd = fd;
5531         sq->two_fd[i].moved_to = CLOSED;
5532 }
5533
5534 static int
5535 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5536 {
5537         int i, new_fd;
5538
5539         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5540                 avoid_fd = 9;
5541
5542 #if JOBS
5543         if (fd == ttyfd) {
5544                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5545                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5546                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5547                 return 1; /* "we closed fd" */
5548         }
5549 #endif
5550         /* Are we called from redirect(0)? E.g. redirect
5551          * in a forked child. No need to save fds,
5552          * we aren't going to use them anymore, ok to trash.
5553          */
5554         if (!sq)
5555                 return 0;
5556
5557         /* If this one of script's fds? */
5558         if (fd != 0) {
5559                 struct parsefile *pf = g_parsefile;
5560                 while (pf) {
5561                         /* We skip fd == 0 case because of the following:
5562                          * $ ash  # running ash interactively
5563                          * $ . ./script.sh
5564                          * and in script.sh: "exec 9>&0".
5565                          * Even though top-level pf_fd _is_ 0,
5566                          * it's still ok to use it: "read" builtin uses it,
5567                          * why should we cripple "exec" builtin?
5568                          */
5569                         if (fd == pf->pf_fd) {
5570                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5571                                 return 1; /* "we closed fd" */
5572                         }
5573                         pf = pf->prev;
5574                 }
5575         }
5576
5577         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5578
5579         /* First: do we collide with some already moved fds? */
5580         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5581                 /* If we collide with an already moved fd... */
5582                 if (fd == sq->two_fd[i].moved_to) {
5583                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5584                         sq->two_fd[i].moved_to = new_fd;
5585                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5586                         if (new_fd < 0) /* what? */
5587                                 xfunc_die();
5588                         return 0; /* "we did not close fd" */
5589                 }
5590                 if (fd == sq->two_fd[i].orig_fd) {
5591                         /* Example: echo Hello >/dev/null 1>&2 */
5592                         TRACE(("redirect_fd %d: already moved\n", fd));
5593                         return 0; /* "we did not close fd" */
5594                 }
5595         }
5596
5597         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5598         new_fd = dup_CLOEXEC(fd, avoid_fd);
5599         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5600         if (new_fd < 0) {
5601                 if (errno != EBADF)
5602                         xfunc_die();
5603                 /* new_fd = CLOSED; - already is -1 */
5604         }
5605         sq->two_fd[i].moved_to = new_fd;
5606         sq->two_fd[i].orig_fd = fd;
5607
5608         /* if we move stderr, let "set -x" code know */
5609         if (fd == preverrout_fd)
5610                 preverrout_fd = new_fd;
5611
5612         return 0; /* "we did not close fd" */
5613 }
5614
5615 static int
5616 internally_opened_fd(int fd, struct redirtab *sq)
5617 {
5618         int i;
5619 #if JOBS
5620         if (fd == ttyfd)
5621                 return 1;
5622 #endif
5623         /* If this one of script's fds? */
5624         if (fd != 0) {
5625                 struct parsefile *pf = g_parsefile;
5626                 while (pf) {
5627                         if (fd == pf->pf_fd)
5628                                 return 1;
5629                         pf = pf->prev;
5630                 }
5631         }
5632
5633         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5634                 if (fd == sq->two_fd[i].moved_to)
5635                         return 1;
5636         }
5637         return 0;
5638 }
5639
5640 /*
5641  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5642  * old file descriptors are stashed away so that the redirection can be
5643  * undone by calling popredir.
5644  */
5645 /* flags passed to redirect */
5646 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5647 static void
5648 redirect(union node *redir, int flags)
5649 {
5650         struct redirtab *sv;
5651
5652         if (!redir)
5653                 return;
5654
5655         sv = NULL;
5656         INT_OFF;
5657         if (flags & REDIR_PUSH)
5658                 sv = redirlist;
5659         do {
5660                 int fd;
5661                 int newfd;
5662                 int close_fd;
5663                 int closed;
5664
5665                 fd = redir->nfile.fd;
5666                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5667                         //bb_error_msg("doing %d > %d", fd, newfd);
5668                         newfd = redir->ndup.dupfd;
5669                         close_fd = -1;
5670                 } else {
5671                         newfd = openredirect(redir); /* always >= 0 */
5672                         if (fd == newfd) {
5673                                 /* open() gave us precisely the fd we wanted.
5674                                  * This means that this fd was not busy
5675                                  * (not opened to anywhere).
5676                                  * Remember to close it on restore:
5677                                  */
5678                                 add_squirrel_closed(sv, fd);
5679                                 continue;
5680                         }
5681                         close_fd = newfd;
5682                 }
5683
5684                 if (fd == newfd)
5685                         continue;
5686
5687                 /* if "N>FILE": move newfd to fd */
5688                 /* if "N>&M": dup newfd to fd */
5689                 /* if "N>&-": close fd (newfd is -1) */
5690
5691  IF_BASH_REDIR_OUTPUT(redirect_more:)
5692
5693                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5694                 if (newfd == -1) {
5695                         /* "N>&-" means "close me" */
5696                         if (!closed) {
5697                                 /* ^^^ optimization: saving may already
5698                                  * have closed it. If not... */
5699                                 close(fd);
5700                         }
5701                 } else {
5702                         /* if newfd is a script fd or saved fd, simulate EBADF */
5703                         if (internally_opened_fd(newfd, sv)) {
5704                                 errno = EBADF;
5705                                 ash_msg_and_raise_perror("%d", newfd);
5706                         }
5707                         dup2_or_raise(newfd, fd);
5708                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5709                                 close(close_fd);
5710 #if BASH_REDIR_OUTPUT
5711                         if (redir->nfile.type == NTO2 && fd == 1) {
5712                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5713                                 fd = 2;
5714                                 newfd = 1;
5715                                 close_fd = -1;
5716                                 goto redirect_more;
5717                         }
5718 #endif
5719                 }
5720         } while ((redir = redir->nfile.next) != NULL);
5721         INT_ON;
5722
5723 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5724 #define REDIR_SAVEFD2 0
5725         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5726         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5727         // not only for calls with flags containing REDIR_SAVEFD2.
5728         // We do this unconditionally (see save_fd_on_redirect()).
5729         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5730         //      preverrout_fd = copied_fd2;
5731 }
5732
5733 static int
5734 redirectsafe(union node *redir, int flags)
5735 {
5736         int err;
5737         volatile int saveint;
5738         struct jmploc *volatile savehandler = exception_handler;
5739         struct jmploc jmploc;
5740
5741         SAVE_INT(saveint);
5742         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5743         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5744         if (!err) {
5745                 exception_handler = &jmploc;
5746                 redirect(redir, flags);
5747         }
5748         exception_handler = savehandler;
5749         if (err && exception_type != EXERROR)
5750                 longjmp(exception_handler->loc, 1);
5751         RESTORE_INT(saveint);
5752         return err;
5753 }
5754
5755 static struct redirtab*
5756 pushredir(union node *redir)
5757 {
5758         struct redirtab *sv;
5759         int i;
5760
5761         if (!redir)
5762                 return redirlist;
5763
5764         i = 0;
5765         do {
5766                 i++;
5767 #if BASH_REDIR_OUTPUT
5768                 if (redir->nfile.type == NTO2)
5769                         i++;
5770 #endif
5771                 redir = redir->nfile.next;
5772         } while (redir);
5773
5774         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5775         sv->pair_count = i;
5776         while (--i >= 0)
5777                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5778         sv->next = redirlist;
5779         redirlist = sv;
5780         return sv->next;
5781 }
5782
5783 /*
5784  * Undo the effects of the last redirection.
5785  */
5786 static void
5787 popredir(int drop)
5788 {
5789         struct redirtab *rp;
5790         int i;
5791
5792         if (redirlist == NULL)
5793                 return;
5794         INT_OFF;
5795         rp = redirlist;
5796         for (i = 0; i < rp->pair_count; i++) {
5797                 int fd = rp->two_fd[i].orig_fd;
5798                 int copy = rp->two_fd[i].moved_to;
5799                 if (copy == CLOSED) {
5800                         if (!drop)
5801                                 close(fd);
5802                         continue;
5803                 }
5804                 if (copy != EMPTY) {
5805                         if (!drop) {
5806                                 /*close(fd);*/
5807                                 dup2_or_raise(copy, fd);
5808                         }
5809                         close(copy);
5810                 }
5811         }
5812         redirlist = rp->next;
5813         free(rp);
5814         INT_ON;
5815 }
5816
5817 static void
5818 unwindredir(struct redirtab *stop)
5819 {
5820         while (redirlist != stop)
5821                 popredir(/*drop:*/ 0);
5822 }
5823
5824
5825 /* ============ Routines to expand arguments to commands
5826  *
5827  * We have to deal with backquotes, shell variables, and file metacharacters.
5828  */
5829
5830 #if ENABLE_FEATURE_SH_MATH
5831 static arith_t
5832 ash_arith(const char *s)
5833 {
5834         arith_state_t math_state;
5835         arith_t result;
5836
5837         math_state.lookupvar = lookupvar;
5838         math_state.setvar    = setvar0;
5839         //math_state.endofname = endofname;
5840
5841         INT_OFF;
5842         result = arith(&math_state, s);
5843         if (math_state.errmsg)
5844                 ash_msg_and_raise_error(math_state.errmsg);
5845         INT_ON;
5846
5847         return result;
5848 }
5849 #endif
5850 #if BASH_SUBSTR
5851 # if ENABLE_FEATURE_SH_MATH
5852 static int substr_atoi(const char *s)
5853 {
5854         arith_t t = ash_arith(s);
5855         if (sizeof(t) > sizeof(int)) {
5856                 /* clamp very large or very large negative nums for ${v:N:M}:
5857                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5858                  */
5859                 if (t > INT_MAX)
5860                         t = INT_MAX;
5861                 if (t < INT_MIN)
5862                         t = INT_MIN;
5863         }
5864         return t;
5865 }
5866 # else
5867 #  define substr_atoi(s) number(s)
5868 # endif
5869 #endif
5870
5871 /*
5872  * expandarg flags
5873  */
5874 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5875 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5876 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5877 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5878 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5879  * POSIX says for this case:
5880  *  Pathname expansion shall not be performed on the word by a
5881  *  non-interactive shell; an interactive shell may perform it, but shall
5882  *  do so only when the expansion would result in one word.
5883  * Currently, our code complies to the above rule by never globbing
5884  * redirection filenames.
5885  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5886  * (this means that on a typical Linux distro, bash almost always
5887  * performs globbing, and thus diverges from what we do).
5888  */
5889 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5890 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
5891 #define EXP_WORD        0x40    /* expand word in parameter expansion */
5892 #define EXP_QUOTED      0x80    /* expand word in double quotes */
5893 /*
5894  * rmescape() flags
5895  */
5896 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5897 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5898 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5899 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5900
5901 /* Add CTLESC when necessary. */
5902 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
5903 /* Do not skip NUL characters. */
5904 #define QUOTES_KEEPNUL EXP_TILDE
5905
5906 /*
5907  * Structure specifying which parts of the string should be searched
5908  * for IFS characters.
5909  */
5910 struct ifsregion {
5911         struct ifsregion *next; /* next region in list */
5912         int begoff;             /* offset of start of region */
5913         int endoff;             /* offset of end of region */
5914         int nulonly;            /* search for nul bytes only */
5915 };
5916
5917 struct arglist {
5918         struct strlist *list;
5919         struct strlist **lastp;
5920 };
5921
5922 /* output of current string */
5923 static char *expdest;
5924 /* list of back quote expressions */
5925 static struct nodelist *argbackq;
5926 /* first struct in list of ifs regions */
5927 static struct ifsregion ifsfirst;
5928 /* last struct in list */
5929 static struct ifsregion *ifslastp;
5930 /* holds expanded arg list */
5931 static struct arglist exparg;
5932
5933 /*
5934  * Our own itoa().
5935  * cvtnum() is used even if math support is off (to prepare $? values and such).
5936  */
5937 static int
5938 cvtnum(arith_t num)
5939 {
5940         int len;
5941
5942         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5943         len = sizeof(arith_t) * 3;
5944         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5945         if (sizeof(arith_t) < 4) len += 2;
5946
5947         expdest = makestrspace(len, expdest);
5948         len = fmtstr(expdest, len, ARITH_FMT, num);
5949         STADJUST(len, expdest);
5950         return len;
5951 }
5952
5953 /*
5954  * Break the argument string into pieces based upon IFS and add the
5955  * strings to the argument list.  The regions of the string to be
5956  * searched for IFS characters have been stored by recordregion.
5957  */
5958 static void
5959 ifsbreakup(char *string, struct arglist *arglist)
5960 {
5961         struct ifsregion *ifsp;
5962         struct strlist *sp;
5963         char *start;
5964         char *p;
5965         char *q;
5966         const char *ifs, *realifs;
5967         int ifsspc;
5968         int nulonly;
5969
5970         start = string;
5971         if (ifslastp != NULL) {
5972                 ifsspc = 0;
5973                 nulonly = 0;
5974                 realifs = ifsset() ? ifsval() : defifs;
5975                 ifsp = &ifsfirst;
5976                 do {
5977                         int afternul;
5978
5979                         p = string + ifsp->begoff;
5980                         afternul = nulonly;
5981                         nulonly = ifsp->nulonly;
5982                         ifs = nulonly ? nullstr : realifs;
5983                         ifsspc = 0;
5984                         while (p < string + ifsp->endoff) {
5985                                 q = p;
5986                                 if ((unsigned char)*p == CTLESC)
5987                                         p++;
5988                                 if (!strchr(ifs, *p)) {
5989                                         p++;
5990                                         continue;
5991                                 }
5992                                 if (!(afternul || nulonly))
5993                                         ifsspc = (strchr(defifs, *p) != NULL);
5994                                 /* Ignore IFS whitespace at start */
5995                                 if (q == start && ifsspc) {
5996                                         p++;
5997                                         start = p;
5998                                         continue;
5999                                 }
6000                                 *q = '\0';
6001                                 sp = stzalloc(sizeof(*sp));
6002                                 sp->text = start;
6003                                 *arglist->lastp = sp;
6004                                 arglist->lastp = &sp->next;
6005                                 p++;
6006                                 if (!nulonly) {
6007                                         for (;;) {
6008                                                 if (p >= string + ifsp->endoff) {
6009                                                         break;
6010                                                 }
6011                                                 q = p;
6012                                                 if ((unsigned char)*p == CTLESC)
6013                                                         p++;
6014                                                 if (strchr(ifs, *p) == NULL) {
6015                                                         p = q;
6016                                                         break;
6017                                                 }
6018                                                 if (strchr(defifs, *p) == NULL) {
6019                                                         if (ifsspc) {
6020                                                                 p++;
6021                                                                 ifsspc = 0;
6022                                                         } else {
6023                                                                 p = q;
6024                                                                 break;
6025                                                         }
6026                                                 } else
6027                                                         p++;
6028                                         }
6029                                 }
6030                                 start = p;
6031                         } /* while */
6032                         ifsp = ifsp->next;
6033                 } while (ifsp != NULL);
6034                 if (nulonly)
6035                         goto add;
6036         }
6037
6038         if (!*start)
6039                 return;
6040
6041  add:
6042         sp = stzalloc(sizeof(*sp));
6043         sp->text = start;
6044         *arglist->lastp = sp;
6045         arglist->lastp = &sp->next;
6046 }
6047
6048 static void
6049 ifsfree(void)
6050 {
6051         struct ifsregion *p = ifsfirst.next;
6052
6053         if (!p)
6054                 goto out;
6055
6056         INT_OFF;
6057         do {
6058                 struct ifsregion *ifsp;
6059                 ifsp = p->next;
6060                 free(p);
6061                 p = ifsp;
6062         } while (p);
6063         ifsfirst.next = NULL;
6064         INT_ON;
6065  out:
6066         ifslastp = NULL;
6067 }
6068
6069 static size_t
6070 esclen(const char *start, const char *p)
6071 {
6072         size_t esc = 0;
6073
6074         while (p > start && (unsigned char)*--p == CTLESC) {
6075                 esc++;
6076         }
6077         return esc;
6078 }
6079
6080 /*
6081  * Remove any CTLESC characters from a string.
6082  */
6083 #if !BASH_PATTERN_SUBST
6084 #define rmescapes(str, flag, slash_position) \
6085         rmescapes(str, flag)
6086 #endif
6087 static char *
6088 rmescapes(char *str, int flag, int *slash_position)
6089 {
6090         static const char qchars[] ALIGN1 = {
6091                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6092
6093         char *p, *q, *r;
6094         unsigned protect_against_glob;
6095         unsigned globbing;
6096
6097         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6098         if (!p)
6099                 return str;
6100
6101         q = p;
6102         r = str;
6103         if (flag & RMESCAPE_ALLOC) {
6104                 size_t len = p - str;
6105                 size_t fulllen = len + strlen(p) + 1;
6106
6107                 if (flag & RMESCAPE_GROW) {
6108                         int strloc = str - (char *)stackblock();
6109                         r = makestrspace(fulllen, expdest);
6110                         /* p and str may be invalidated by makestrspace */
6111                         str = (char *)stackblock() + strloc;
6112                         p = str + len;
6113                 } else if (flag & RMESCAPE_HEAP) {
6114                         r = ckmalloc(fulllen);
6115                 } else {
6116                         r = stalloc(fulllen);
6117                 }
6118                 q = r;
6119                 if (len > 0) {
6120                         q = (char *)mempcpy(q, str, len);
6121                 }
6122         }
6123
6124         globbing = flag & RMESCAPE_GLOB;
6125         protect_against_glob = globbing;
6126         while (*p) {
6127                 if ((unsigned char)*p == CTLQUOTEMARK) {
6128 // Note: protect_against_glob only affect whether
6129 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6130                         p++;
6131                         protect_against_glob = globbing;
6132                         continue;
6133                 }
6134                 if (*p == '\\') {
6135                         /* naked back slash */
6136                         protect_against_glob = 0;
6137                         goto copy;
6138                 }
6139                 if ((unsigned char)*p == CTLESC) {
6140                         p++;
6141 #if DEBUG
6142                         if (*p == '\0')
6143                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6144 #endif
6145                         if (protect_against_glob) {
6146                                 /*
6147                                  * We used to trust glob() and fnmatch() to eat
6148                                  * superfluous escapes (\z where z has no
6149                                  * special meaning anyway). But this causes
6150                                  * bugs such as string of one greek letter rho
6151                                  * (unicode-encoded as two bytes "cf,81")
6152                                  * getting encoded as "cf,CTLESC,81"
6153                                  * and here, converted to "cf,\,81" -
6154                                  * which does not go well with some flavors
6155                                  * of fnmatch() in unicode locales
6156                                  * (for example, glibc <= 2.22).
6157                                  *
6158                                  * Lets add "\" only on the chars which need it.
6159                                  * Testcases for less obvious chars are shown.
6160                                  */
6161                                 if (*p == '*'
6162                                  || *p == '?'
6163                                  || *p == '['
6164                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6165                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6166                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6167                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6168                                 /* Some libc support [^negate], that's why "^" also needs love */
6169                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6170                                 ) {
6171                                         *q++ = '\\';
6172                                 }
6173                         }
6174                 }
6175 #if BASH_PATTERN_SUBST
6176                 else if (slash_position && p == str + *slash_position) {
6177                         /* stop handling globbing */
6178                         globbing = 0;
6179                         *slash_position = q - r;
6180                         slash_position = NULL;
6181                 }
6182 #endif
6183                 protect_against_glob = globbing;
6184  copy:
6185                 *q++ = *p++;
6186         }
6187         *q = '\0';
6188         if (flag & RMESCAPE_GROW) {
6189                 expdest = r;
6190                 STADJUST(q - r + 1, expdest);
6191         }
6192         return r;
6193 }
6194 #define pmatch(a, b) !fnmatch((a), (b), 0)
6195
6196 /*
6197  * Prepare a pattern for a expmeta (internal glob(3)) call.
6198  *
6199  * Returns an stalloced string.
6200  */
6201 static char *
6202 preglob(const char *pattern, int flag)
6203 {
6204         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6205 }
6206
6207 /*
6208  * Put a string on the stack.
6209  */
6210 static void
6211 memtodest(const char *p, size_t len, int syntax, int quotes)
6212 {
6213         char *q;
6214
6215         if (!len)
6216                 return;
6217
6218         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6219
6220         do {
6221                 unsigned char c = *p++;
6222                 if (c) {
6223                         if (quotes & QUOTES_ESC) {
6224                                 int n = SIT(c, syntax);
6225                                 if (n == CCTL
6226                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6227                                      && n == CBACK
6228                                     )
6229                                 ) {
6230                                         USTPUTC(CTLESC, q);
6231                                 }
6232                         }
6233                 } else if (!(quotes & QUOTES_KEEPNUL))
6234                         continue;
6235                 USTPUTC(c, q);
6236         } while (--len);
6237
6238         expdest = q;
6239 }
6240
6241 static size_t
6242 strtodest(const char *p, int syntax, int quotes)
6243 {
6244         size_t len = strlen(p);
6245         memtodest(p, len, syntax, quotes);
6246         return len;
6247 }
6248
6249 /*
6250  * Record the fact that we have to scan this region of the
6251  * string for IFS characters.
6252  */
6253 static void
6254 recordregion(int start, int end, int nulonly)
6255 {
6256         struct ifsregion *ifsp;
6257
6258         if (ifslastp == NULL) {
6259                 ifsp = &ifsfirst;
6260         } else {
6261                 INT_OFF;
6262                 ifsp = ckzalloc(sizeof(*ifsp));
6263                 /*ifsp->next = NULL; - ckzalloc did it */
6264                 ifslastp->next = ifsp;
6265                 INT_ON;
6266         }
6267         ifslastp = ifsp;
6268         ifslastp->begoff = start;
6269         ifslastp->endoff = end;
6270         ifslastp->nulonly = nulonly;
6271 }
6272
6273 static void
6274 removerecordregions(int endoff)
6275 {
6276         if (ifslastp == NULL)
6277                 return;
6278
6279         if (ifsfirst.endoff > endoff) {
6280                 while (ifsfirst.next) {
6281                         struct ifsregion *ifsp;
6282                         INT_OFF;
6283                         ifsp = ifsfirst.next->next;
6284                         free(ifsfirst.next);
6285                         ifsfirst.next = ifsp;
6286                         INT_ON;
6287                 }
6288                 if (ifsfirst.begoff > endoff) {
6289                         ifslastp = NULL;
6290                 } else {
6291                         ifslastp = &ifsfirst;
6292                         ifsfirst.endoff = endoff;
6293                 }
6294                 return;
6295         }
6296
6297         ifslastp = &ifsfirst;
6298         while (ifslastp->next && ifslastp->next->begoff < endoff)
6299                 ifslastp = ifslastp->next;
6300         while (ifslastp->next) {
6301                 struct ifsregion *ifsp;
6302                 INT_OFF;
6303                 ifsp = ifslastp->next->next;
6304                 free(ifslastp->next);
6305                 ifslastp->next = ifsp;
6306                 INT_ON;
6307         }
6308         if (ifslastp->endoff > endoff)
6309                 ifslastp->endoff = endoff;
6310 }
6311
6312 static char *
6313 exptilde(char *startp, char *p, int flags)
6314 {
6315         unsigned char c;
6316         char *name;
6317         struct passwd *pw;
6318         const char *home;
6319         int quotes = flags & QUOTES_ESC;
6320
6321         name = p + 1;
6322
6323         while ((c = *++p) != '\0') {
6324                 switch (c) {
6325                 case CTLESC:
6326                         return startp;
6327                 case CTLQUOTEMARK:
6328                         return startp;
6329                 case ':':
6330                         if (flags & EXP_VARTILDE)
6331                                 goto done;
6332                         break;
6333                 case '/':
6334                 case CTLENDVAR:
6335                         goto done;
6336                 }
6337         }
6338  done:
6339         *p = '\0';
6340         if (*name == '\0') {
6341                 home = lookupvar("HOME");
6342         } else {
6343                 pw = getpwnam(name);
6344                 if (pw == NULL)
6345                         goto lose;
6346                 home = pw->pw_dir;
6347         }
6348         if (!home || !*home)
6349                 goto lose;
6350         *p = c;
6351         strtodest(home, SQSYNTAX, quotes);
6352         return p;
6353  lose:
6354         *p = c;
6355         return startp;
6356 }
6357
6358 /*
6359  * Execute a command inside back quotes.  If it's a builtin command, we
6360  * want to save its output in a block obtained from malloc.  Otherwise
6361  * we fork off a subprocess and get the output of the command via a pipe.
6362  * Should be called with interrupts off.
6363  */
6364 struct backcmd {                /* result of evalbackcmd */
6365         int fd;                 /* file descriptor to read from */
6366         int nleft;              /* number of chars in buffer */
6367         char *buf;              /* buffer */
6368         struct job *jp;         /* job structure for command */
6369 };
6370
6371 /* These forward decls are needed to use "eval" code for backticks handling: */
6372 /* flags in argument to evaltree */
6373 #define EV_EXIT    01           /* exit after evaluating tree */
6374 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6375 static int evaltree(union node *, int);
6376
6377 /* An evaltree() which is known to never return.
6378  * Used to use an alias:
6379  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6380  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6381  */
6382 static ALWAYS_INLINE NORETURN void
6383 evaltreenr(union node *n, int flags)
6384 {
6385         evaltree(n, flags);
6386         bb_unreachable(abort());
6387         /* NOTREACHED */
6388 }
6389
6390 static void FAST_FUNC
6391 evalbackcmd(union node *n, struct backcmd *result)
6392 {
6393         int pip[2];
6394         struct job *jp;
6395
6396         result->fd = -1;
6397         result->buf = NULL;
6398         result->nleft = 0;
6399         result->jp = NULL;
6400         if (n == NULL) {
6401                 goto out;
6402         }
6403
6404         if (pipe(pip) < 0)
6405                 ash_msg_and_raise_perror("can't create pipe");
6406         jp = makejob(/*n,*/ 1);
6407         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6408                 /* child */
6409                 FORCE_INT_ON;
6410                 close(pip[0]);
6411                 if (pip[1] != 1) {
6412                         /*close(1);*/
6413                         dup2_or_raise(pip[1], 1);
6414                         close(pip[1]);
6415                 }
6416 /* TODO: eflag clearing makes the following not abort:
6417  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6418  * which is what bash does (unless it is in POSIX mode).
6419  * dash deleted "eflag = 0" line in the commit
6420  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6421  *  [EVAL] Don't clear eflag in evalbackcmd
6422  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6423  */
6424                 eflag = 0;
6425                 ifsfree();
6426                 evaltreenr(n, EV_EXIT);
6427                 /* NOTREACHED */
6428         }
6429         /* parent */
6430         close(pip[1]);
6431         result->fd = pip[0];
6432         result->jp = jp;
6433
6434  out:
6435         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6436                 result->fd, result->buf, result->nleft, result->jp));
6437 }
6438
6439 /*
6440  * Expand stuff in backwards quotes.
6441  */
6442 static void
6443 expbackq(union node *cmd, int flag)
6444 {
6445         struct backcmd in;
6446         int i;
6447         char buf[128];
6448         char *p;
6449         char *dest;
6450         int startloc;
6451         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6452         struct stackmark smark;
6453
6454         INT_OFF;
6455         startloc = expdest - (char *)stackblock();
6456         pushstackmark(&smark, startloc);
6457         evalbackcmd(cmd, &in);
6458         popstackmark(&smark);
6459
6460         p = in.buf;
6461         i = in.nleft;
6462         if (i == 0)
6463                 goto read;
6464         for (;;) {
6465                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6466  read:
6467                 if (in.fd < 0)
6468                         break;
6469                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6470                 TRACE(("expbackq: read returns %d\n", i));
6471                 if (i <= 0)
6472                         break;
6473                 p = buf;
6474         }
6475
6476         free(in.buf);
6477         if (in.fd >= 0) {
6478                 close(in.fd);
6479                 back_exitstatus = waitforjob(in.jp);
6480         }
6481         INT_ON;
6482
6483         /* Eat all trailing newlines */
6484         dest = expdest;
6485         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6486                 STUNPUTC(dest);
6487         expdest = dest;
6488
6489         if (!(flag & EXP_QUOTED))
6490                 recordregion(startloc, dest - (char *)stackblock(), 0);
6491         TRACE(("evalbackq: size:%d:'%.*s'\n",
6492                 (int)((dest - (char *)stackblock()) - startloc),
6493                 (int)((dest - (char *)stackblock()) - startloc),
6494                 stackblock() + startloc));
6495 }
6496
6497 #if ENABLE_FEATURE_SH_MATH
6498 /*
6499  * Expand arithmetic expression.  Backup to start of expression,
6500  * evaluate, place result in (backed up) result, adjust string position.
6501  */
6502 static void
6503 expari(int flag)
6504 {
6505         char *p, *start;
6506         int begoff;
6507         int len;
6508
6509         /* ifsfree(); */
6510
6511         /*
6512          * This routine is slightly over-complicated for
6513          * efficiency.  Next we scan backwards looking for the
6514          * start of arithmetic.
6515          */
6516         start = stackblock();
6517         p = expdest - 1;
6518         *p = '\0';
6519         p--;
6520         while (1) {
6521                 int esc;
6522
6523                 while ((unsigned char)*p != CTLARI) {
6524                         p--;
6525 #if DEBUG
6526                         if (p < start) {
6527                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6528                         }
6529 #endif
6530                 }
6531
6532                 esc = esclen(start, p);
6533                 if (!(esc % 2)) {
6534                         break;
6535                 }
6536
6537                 p -= esc + 1;
6538         }
6539
6540         begoff = p - start;
6541
6542         removerecordregions(begoff);
6543
6544         expdest = p;
6545
6546         if (flag & QUOTES_ESC)
6547                 rmescapes(p + 1, 0, NULL);
6548
6549         len = cvtnum(ash_arith(p + 1));
6550
6551         if (!(flag & EXP_QUOTED))
6552                 recordregion(begoff, begoff + len, 0);
6553 }
6554 #endif
6555
6556 /* argstr needs it */
6557 static char *evalvar(char *p, int flags);
6558
6559 /*
6560  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6561  * characters to allow for further processing.  Otherwise treat
6562  * $@ like $* since no splitting will be performed.
6563  */
6564 static void
6565 argstr(char *p, int flags)
6566 {
6567         static const char spclchars[] ALIGN1 = {
6568                 '=',
6569                 ':',
6570                 CTLQUOTEMARK,
6571                 CTLENDVAR,
6572                 CTLESC,
6573                 CTLVAR,
6574                 CTLBACKQ,
6575 #if ENABLE_FEATURE_SH_MATH
6576                 CTLENDARI,
6577 #endif
6578                 '\0'
6579         };
6580         const char *reject = spclchars;
6581         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6582         int inquotes;
6583         size_t length;
6584         int startloc;
6585
6586         if (!(flags & EXP_VARTILDE)) {
6587                 reject += 2;
6588         } else if (flags & EXP_VARTILDE2) {
6589                 reject++;
6590         }
6591         inquotes = 0;
6592         length = 0;
6593         if (flags & EXP_TILDE) {
6594                 char *q;
6595
6596                 flags &= ~EXP_TILDE;
6597  tilde:
6598                 q = p;
6599                 if (*q == '~')
6600                         p = exptilde(p, q, flags);
6601         }
6602  start:
6603         startloc = expdest - (char *)stackblock();
6604         for (;;) {
6605                 unsigned char c;
6606
6607                 length += strcspn(p + length, reject);
6608                 c = p[length];
6609                 if (c) {
6610                         if (!(c & 0x80)
6611                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6612                         ) {
6613                                 /* c == '=' || c == ':' || c == CTLENDARI */
6614                                 length++;
6615                         }
6616                 }
6617                 if (length > 0) {
6618                         int newloc;
6619                         expdest = stack_nputstr(p, length, expdest);
6620                         newloc = expdest - (char *)stackblock();
6621                         if (breakall && !inquotes && newloc > startloc) {
6622                                 recordregion(startloc, newloc, 0);
6623                         }
6624                         startloc = newloc;
6625                 }
6626                 p += length + 1;
6627                 length = 0;
6628
6629                 switch (c) {
6630                 case '\0':
6631                         goto breakloop;
6632                 case '=':
6633                         if (flags & EXP_VARTILDE2) {
6634                                 p--;
6635                                 continue;
6636                         }
6637                         flags |= EXP_VARTILDE2;
6638                         reject++;
6639                         /* fall through */
6640                 case ':':
6641                         /*
6642                          * sort of a hack - expand tildes in variable
6643                          * assignments (after the first '=' and after ':'s).
6644                          */
6645                         if (*--p == '~') {
6646                                 goto tilde;
6647                         }
6648                         continue;
6649                 }
6650
6651                 switch (c) {
6652                 case CTLENDVAR: /* ??? */
6653                         goto breakloop;
6654                 case CTLQUOTEMARK:
6655                         /* "$@" syntax adherence hack */
6656                         if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6657                                 p = evalvar(p + 1, flags | EXP_QUOTED) + 1;
6658                                 goto start;
6659                         }
6660                         inquotes ^= EXP_QUOTED;
6661  addquote:
6662                         if (flags & QUOTES_ESC) {
6663                                 p--;
6664                                 length++;
6665                                 startloc++;
6666                         }
6667                         break;
6668                 case CTLESC:
6669                         startloc++;
6670                         length++;
6671                         goto addquote;
6672                 case CTLVAR:
6673                         TRACE(("argstr: evalvar('%s')\n", p));
6674                         p = evalvar(p, flags | inquotes);
6675                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6676                         goto start;
6677                 case CTLBACKQ:
6678                         expbackq(argbackq->n, flags | inquotes);
6679                         argbackq = argbackq->next;
6680                         goto start;
6681 #if ENABLE_FEATURE_SH_MATH
6682                 case CTLENDARI:
6683                         p--;
6684                         expari(flags | inquotes);
6685                         goto start;
6686 #endif
6687                 }
6688         }
6689  breakloop: ;
6690 }
6691
6692 static char *
6693 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6694                 char *pattern, int quotes, int zero)
6695 {
6696         char *loc, *loc2;
6697         char c;
6698
6699         loc = startp;
6700         loc2 = rmesc;
6701         do {
6702                 int match;
6703                 const char *s = loc2;
6704
6705                 c = *loc2;
6706                 if (zero) {
6707                         *loc2 = '\0';
6708                         s = rmesc;
6709                 }
6710                 match = pmatch(pattern, s);
6711
6712                 *loc2 = c;
6713                 if (match)
6714                         return loc;
6715                 if (quotes && (unsigned char)*loc == CTLESC)
6716                         loc++;
6717                 loc++;
6718                 loc2++;
6719         } while (c);
6720         return NULL;
6721 }
6722
6723 static char *
6724 scanright(char *startp, char *rmesc, char *rmescend,
6725                 char *pattern, int quotes, int match_at_start)
6726 {
6727 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6728         int try2optimize = match_at_start;
6729 #endif
6730         int esc = 0;
6731         char *loc;
6732         char *loc2;
6733
6734         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6735          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6736          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6737          * Logic:
6738          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6739          * and on each iteration they go back two/one char until they reach the beginning.
6740          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6741          */
6742         /* TODO: document in what other circumstances we are called. */
6743
6744         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6745                 int match;
6746                 char c = *loc2;
6747                 const char *s = loc2;
6748                 if (match_at_start) {
6749                         *loc2 = '\0';
6750                         s = rmesc;
6751                 }
6752                 match = pmatch(pattern, s);
6753                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6754                 *loc2 = c;
6755                 if (match)
6756                         return loc;
6757 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6758                 if (try2optimize) {
6759                         /* Maybe we can optimize this:
6760                          * if pattern ends with unescaped *, we can avoid checking
6761                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6762                          * it won't match truncated "raw_value_of_" strings too.
6763                          */
6764                         unsigned plen = strlen(pattern);
6765                         /* Does it end with "*"? */
6766                         if (plen != 0 && pattern[--plen] == '*') {
6767                                 /* "xxxx*" is not escaped */
6768                                 /* "xxx\*" is escaped */
6769                                 /* "xx\\*" is not escaped */
6770                                 /* "x\\\*" is escaped */
6771                                 int slashes = 0;
6772                                 while (plen != 0 && pattern[--plen] == '\\')
6773                                         slashes++;
6774                                 if (!(slashes & 1))
6775                                         break; /* ends with unescaped "*" */
6776                         }
6777                         try2optimize = 0;
6778                 }
6779 #endif
6780                 loc--;
6781                 if (quotes) {
6782                         if (--esc < 0) {
6783                                 esc = esclen(startp, loc);
6784                         }
6785                         if (esc % 2) {
6786                                 esc--;
6787                                 loc--;
6788                         }
6789                 }
6790         }
6791         return NULL;
6792 }
6793
6794 static void varunset(const char *, const char *, const char *, int) NORETURN;
6795 static void
6796 varunset(const char *end, const char *var, const char *umsg, int varflags)
6797 {
6798         const char *msg;
6799         const char *tail;
6800
6801         tail = nullstr;
6802         msg = "parameter not set";
6803         if (umsg) {
6804                 if ((unsigned char)*end == CTLENDVAR) {
6805                         if (varflags & VSNUL)
6806                                 tail = " or null";
6807                 } else {
6808                         msg = umsg;
6809                 }
6810         }
6811         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6812 }
6813
6814 static const char *
6815 subevalvar(char *p, char *varname, int strloc, int subtype,
6816                 int startloc, int varflags, int flag)
6817 {
6818         struct nodelist *saveargbackq = argbackq;
6819         int quotes = flag & QUOTES_ESC;
6820         char *startp;
6821         char *loc;
6822         char *rmesc, *rmescend;
6823         char *str;
6824         int amount, resetloc;
6825         int argstr_flags;
6826         IF_BASH_PATTERN_SUBST(int workloc;)
6827         IF_BASH_PATTERN_SUBST(int slash_pos;)
6828         IF_BASH_PATTERN_SUBST(char *repl;)
6829         int zero;
6830         char *(*scan)(char*, char*, char*, char*, int, int);
6831
6832         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6833         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6834
6835 #if BASH_PATTERN_SUBST
6836         /* For "${v/pattern/repl}", we must find the delimiter _before_
6837          * argstr() call expands possible variable references in pattern:
6838          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6839          */
6840         repl = NULL;
6841         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6842                 /* Find '/' and replace with NUL */
6843                 repl = p;
6844                 for (;;) {
6845                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6846                         if (*repl == '\0') {
6847                                 repl = NULL;
6848                                 break;
6849                         }
6850                         if (*repl == '/') {
6851                                 *repl = '\0';
6852                                 break;
6853                         }
6854                         if ((unsigned char)*repl == CTLESC && repl[1])
6855                                 repl++;
6856                         repl++;
6857                 }
6858         }
6859 #endif
6860         argstr_flags = EXP_TILDE;
6861         if (subtype != VSASSIGN
6862          && subtype != VSQUESTION
6863 #if BASH_SUBSTR
6864          && subtype != VSSUBSTR
6865 #endif
6866         ) {
6867                 /* EXP_CASE keeps CTLESC's */
6868                 argstr_flags = EXP_TILDE | EXP_CASE;
6869         }
6870         argstr(p, argstr_flags);
6871         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
6872 #if BASH_PATTERN_SUBST
6873         slash_pos = -1;
6874         if (repl) {
6875                 slash_pos = expdest - ((char *)stackblock() + strloc);
6876                 STPUTC('/', expdest);
6877                 //bb_error_msg("repl+1:'%s'", repl + 1);
6878                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
6879                 *repl = '/';
6880         }
6881 #endif
6882         STPUTC('\0', expdest);
6883         argbackq = saveargbackq;
6884         startp = (char *)stackblock() + startloc;
6885         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6886
6887         switch (subtype) {
6888         case VSASSIGN:
6889                 setvar0(varname, startp);
6890                 amount = startp - expdest;
6891                 STADJUST(amount, expdest);
6892                 return startp;
6893
6894         case VSQUESTION:
6895                 varunset(p, varname, startp, varflags);
6896                 /* NOTREACHED */
6897
6898 #if BASH_SUBSTR
6899         case VSSUBSTR: {
6900                 int pos, len, orig_len;
6901                 char *colon;
6902
6903                 loc = str = stackblock() + strloc;
6904
6905                 /* Read POS in ${var:POS:LEN} */
6906                 colon = strchr(loc, ':');
6907                 if (colon) *colon = '\0';
6908                 pos = substr_atoi(loc);
6909                 if (colon) *colon = ':';
6910
6911                 /* Read LEN in ${var:POS:LEN} */
6912                 len = str - startp - 1;
6913                 /* *loc != '\0', guaranteed by parser */
6914                 if (quotes) {
6915                         char *ptr;
6916                         /* Adjust the length by the number of escapes */
6917                         for (ptr = startp; ptr < (str - 1); ptr++) {
6918                                 if ((unsigned char)*ptr == CTLESC) {
6919                                         len--;
6920                                         ptr++;
6921                                 }
6922                         }
6923                 }
6924                 orig_len = len;
6925                 if (*loc++ == ':') {
6926                         /* ${var::LEN} */
6927                         len = substr_atoi(loc);
6928                 } else {
6929                         /* Skip POS in ${var:POS:LEN} */
6930                         len = orig_len;
6931                         while (*loc && *loc != ':')
6932                                 loc++;
6933                         if (*loc++ == ':')
6934                                 len = substr_atoi(loc);
6935                 }
6936                 if (pos < 0) {
6937                         /* ${VAR:$((-n)):l} starts n chars from the end */
6938                         pos = orig_len + pos;
6939                 }
6940                 if ((unsigned)pos >= orig_len) {
6941                         /* apart from obvious ${VAR:999999:l},
6942                          * covers ${VAR:$((-9999999)):l} - result is ""
6943                          * (bash compat)
6944                          */
6945                         pos = 0;
6946                         len = 0;
6947                 }
6948                 if (len < 0) {
6949                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6950                         len = (orig_len - pos) + len;
6951                 }
6952                 if ((unsigned)len > (orig_len - pos))
6953                         len = orig_len - pos;
6954
6955                 for (str = startp; pos; str++, pos--) {
6956                         if (quotes && (unsigned char)*str == CTLESC)
6957                                 str++;
6958                 }
6959                 for (loc = startp; len; len--) {
6960                         if (quotes && (unsigned char)*str == CTLESC)
6961                                 *loc++ = *str++;
6962                         *loc++ = *str++;
6963                 }
6964                 *loc = '\0';
6965                 amount = loc - expdest;
6966                 STADJUST(amount, expdest);
6967                 return loc;
6968         }
6969 #endif /* BASH_SUBSTR */
6970         }
6971
6972         resetloc = expdest - (char *)stackblock();
6973
6974 #if BASH_PATTERN_SUBST
6975         repl = NULL;
6976
6977         /* We'll comeback here if we grow the stack while handling
6978          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6979          * stack will need rebasing, and we'll need to remove our work
6980          * areas each time
6981          */
6982  restart:
6983 #endif
6984
6985         amount = expdest - ((char *)stackblock() + resetloc);
6986         STADJUST(-amount, expdest);
6987         startp = (char *)stackblock() + startloc;
6988
6989         rmesc = startp;
6990         rmescend = (char *)stackblock() + strloc;
6991         //bb_error_msg("str7:'%s'", rmescend);
6992         if (quotes) {
6993 //TODO: how to handle slash_pos here if string changes (shortens?)
6994                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
6995                 if (rmesc != startp) {
6996                         rmescend = expdest;
6997                         startp = (char *)stackblock() + startloc;
6998                 }
6999         }
7000         rmescend--;
7001         str = (char *)stackblock() + strloc;
7002         /*
7003          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7004          * The result is a_\_z_c (not a\_\_z_c)!
7005          *
7006          * The search pattern and replace string treat backslashes differently!
7007          * "&slash_pos" causes rmescapes() to work differently on the pattern
7008          * and string.  It's only used on the first call.
7009          */
7010         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7011         rmescapes(str, RMESCAPE_GLOB,
7012                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7013         );
7014
7015 #if BASH_PATTERN_SUBST
7016         workloc = expdest - (char *)stackblock();
7017         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7018                 int len;
7019                 char *idx, *end;
7020
7021                 if (!repl) {
7022                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7023                         repl = nullstr;
7024                         if (slash_pos >= 0) {
7025                                 repl = str + slash_pos;
7026                                 *repl++ = '\0';
7027                         }
7028                 }
7029                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7030
7031                 /* If there's no pattern to match, return the expansion unmolested */
7032                 if (str[0] == '\0')
7033                         return NULL;
7034
7035                 len = 0;
7036                 idx = startp;
7037                 end = str - 1;
7038                 while (idx < end) {
7039  try_to_match:
7040                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7041                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7042                         if (!loc) {
7043                                 /* No match, advance */
7044                                 char *restart_detect = stackblock();
7045  skip_matching:
7046                                 STPUTC(*idx, expdest);
7047                                 if (quotes && (unsigned char)*idx == CTLESC) {
7048                                         idx++;
7049                                         len++;
7050                                         STPUTC(*idx, expdest);
7051                                 }
7052                                 if (stackblock() != restart_detect)
7053                                         goto restart;
7054                                 idx++;
7055                                 len++;
7056                                 rmesc++;
7057                                 /* continue; - prone to quadratic behavior, smarter code: */
7058                                 if (idx >= end)
7059                                         break;
7060                                 if (str[0] == '*') {
7061                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7062                                          * it would never match "ong_string" etc, no point in trying.
7063                                          */
7064                                         goto skip_matching;
7065                                 }
7066                                 goto try_to_match;
7067                         }
7068
7069                         if (subtype == VSREPLACEALL) {
7070                                 while (idx < loc) {
7071                                         if (quotes && (unsigned char)*idx == CTLESC)
7072                                                 idx++;
7073                                         idx++;
7074                                         rmesc++;
7075                                 }
7076                         } else {
7077                                 idx = loc;
7078                         }
7079
7080                         //bb_error_msg("repl:'%s'", repl);
7081                         for (loc = (char*)repl; *loc; loc++) {
7082                                 char *restart_detect = stackblock();
7083                                 if (quotes && *loc == '\\') {
7084                                         STPUTC(CTLESC, expdest);
7085                                         len++;
7086                                 }
7087                                 STPUTC(*loc, expdest);
7088                                 if (stackblock() != restart_detect)
7089                                         goto restart;
7090                                 len++;
7091                         }
7092
7093                         if (subtype == VSREPLACE) {
7094                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7095                                 while (*idx) {
7096                                         char *restart_detect = stackblock();
7097                                         STPUTC(*idx, expdest);
7098                                         if (stackblock() != restart_detect)
7099                                                 goto restart;
7100                                         len++;
7101                                         idx++;
7102                                 }
7103                                 break;
7104                         }
7105                 }
7106
7107                 /* We've put the replaced text into a buffer at workloc, now
7108                  * move it to the right place and adjust the stack.
7109                  */
7110                 STPUTC('\0', expdest);
7111                 startp = (char *)stackblock() + startloc;
7112                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7113                 //bb_error_msg("startp:'%s'", startp);
7114                 amount = expdest - (startp + len);
7115                 STADJUST(-amount, expdest);
7116                 return startp;
7117         }
7118 #endif /* BASH_PATTERN_SUBST */
7119
7120         subtype -= VSTRIMRIGHT;
7121 #if DEBUG
7122         if (subtype < 0 || subtype > 7)
7123                 abort();
7124 #endif
7125         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7126         zero = subtype >> 1;
7127         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7128         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7129
7130         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7131         if (loc) {
7132                 if (zero) {
7133                         memmove(startp, loc, str - loc);
7134                         loc = startp + (str - loc) - 1;
7135                 }
7136                 *loc = '\0';
7137                 amount = loc - expdest;
7138                 STADJUST(amount, expdest);
7139         }
7140         return loc;
7141 }
7142
7143 /*
7144  * Add the value of a specialized variable to the stack string.
7145  * name parameter (examples):
7146  * ash -c 'echo $1'      name:'1='
7147  * ash -c 'echo $qwe'    name:'qwe='
7148  * ash -c 'echo $$'      name:'$='
7149  * ash -c 'echo ${$}'    name:'$='
7150  * ash -c 'echo ${$##q}' name:'$=q'
7151  * ash -c 'echo ${#$}'   name:'$='
7152  * note: examples with bad shell syntax:
7153  * ash -c 'echo ${#$1}'  name:'$=1'
7154  * ash -c 'echo ${#1#}'  name:'1=#'
7155  */
7156 static NOINLINE ssize_t
7157 varvalue(char *name, int varflags, int flags, int *quotedp)
7158 {
7159         const char *p;
7160         int num;
7161         int i;
7162         ssize_t len = 0;
7163         int sep;
7164         int quoted = *quotedp;
7165         int subtype = varflags & VSTYPE;
7166         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7167         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7168         int syntax;
7169
7170         sep = (flags & EXP_FULL) << CHAR_BIT;
7171         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7172
7173         switch (*name) {
7174         case '$':
7175                 num = rootpid;
7176                 goto numvar;
7177         case '?':
7178                 num = exitstatus;
7179                 goto numvar;
7180         case '#':
7181                 num = shellparam.nparam;
7182                 goto numvar;
7183         case '!':
7184                 num = backgndpid;
7185                 if (num == 0)
7186                         return -1;
7187  numvar:
7188                 len = cvtnum(num);
7189                 goto check_1char_name;
7190         case '-':
7191                 expdest = makestrspace(NOPTS, expdest);
7192                 for (i = NOPTS - 1; i >= 0; i--) {
7193                         if (optlist[i] && optletters(i)) {
7194                                 USTPUTC(optletters(i), expdest);
7195                                 len++;
7196                         }
7197                 }
7198  check_1char_name:
7199 #if 0
7200                 /* handles cases similar to ${#$1} */
7201                 if (name[2] != '\0')
7202                         raise_error_syntax("bad substitution");
7203 #endif
7204                 break;
7205         case '@':
7206                 if (quoted && sep)
7207                         goto param;
7208                 /* fall through */
7209         case '*': {
7210                 char **ap;
7211                 char sepc;
7212
7213                 if (quoted)
7214                         sep = 0;
7215                 sep |= ifsset() ? ifsval()[0] : ' ';
7216  param:
7217                 sepc = sep;
7218                 *quotedp = !sepc;
7219                 ap = shellparam.p;
7220                 if (!ap)
7221                         return -1;
7222                 while ((p = *ap++) != NULL) {
7223                         len += strtodest(p, syntax, quotes);
7224
7225                         if (*ap && sep) {
7226                                 len++;
7227                                 memtodest(&sepc, 1, syntax, quotes);
7228                         }
7229                 }
7230                 break;
7231         } /* case '*' */
7232         case '0':
7233         case '1':
7234         case '2':
7235         case '3':
7236         case '4':
7237         case '5':
7238         case '6':
7239         case '7':
7240         case '8':
7241         case '9':
7242                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7243                 if (num < 0 || num > shellparam.nparam)
7244                         return -1;
7245                 p = num ? shellparam.p[num - 1] : arg0;
7246                 goto value;
7247         default:
7248                 /* NB: name has form "VAR=..." */
7249                 p = lookupvar(name);
7250  value:
7251                 if (!p)
7252                         return -1;
7253
7254                 len = strtodest(p, syntax, quotes);
7255 #if ENABLE_UNICODE_SUPPORT
7256                 if (subtype == VSLENGTH && len > 0) {
7257                         reinit_unicode_for_ash();
7258                         if (unicode_status == UNICODE_ON) {
7259                                 STADJUST(-len, expdest);
7260                                 discard = 0;
7261                                 len = unicode_strlen(p);
7262                         }
7263                 }
7264 #endif
7265                 break;
7266         }
7267
7268         if (discard)
7269                 STADJUST(-len, expdest);
7270         return len;
7271 }
7272
7273 /*
7274  * Expand a variable, and return a pointer to the next character in the
7275  * input string.
7276  */
7277 static char *
7278 evalvar(char *p, int flag)
7279 {
7280         char varflags;
7281         char subtype;
7282         int quoted;
7283         char easy;
7284         char *var;
7285         int patloc;
7286         int startloc;
7287         ssize_t varlen;
7288
7289         varflags = (unsigned char) *p++;
7290         subtype = varflags & VSTYPE;
7291
7292         if (!subtype)
7293                 raise_error_syntax("bad substitution");
7294
7295         quoted = flag & EXP_QUOTED;
7296         var = p;
7297         easy = (!quoted || (*var == '@' && shellparam.nparam));
7298         startloc = expdest - (char *)stackblock();
7299         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7300
7301  again:
7302         varlen = varvalue(var, varflags, flag, &quoted);
7303         if (varflags & VSNUL)
7304                 varlen--;
7305
7306         if (subtype == VSPLUS) {
7307                 varlen = -1 - varlen;
7308                 goto vsplus;
7309         }
7310
7311         if (subtype == VSMINUS) {
7312  vsplus:
7313                 if (varlen < 0) {
7314                         argstr(
7315                                 p,
7316                                 flag | EXP_TILDE | EXP_WORD
7317                         );
7318                         goto end;
7319                 }
7320                 goto record;
7321         }
7322
7323         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7324                 if (varlen >= 0)
7325                         goto record;
7326
7327                 subevalvar(p, var, 0, subtype, startloc, varflags,
7328                            flag & ~QUOTES_ESC);
7329                 varflags &= ~VSNUL;
7330                 /*
7331                  * Remove any recorded regions beyond
7332                  * start of variable
7333                  */
7334                 removerecordregions(startloc);
7335                 goto again;
7336         }
7337
7338         if (varlen < 0 && uflag)
7339                 varunset(p, var, 0, 0);
7340
7341         if (subtype == VSLENGTH) {
7342                 cvtnum(varlen > 0 ? varlen : 0);
7343                 goto record;
7344         }
7345
7346         if (subtype == VSNORMAL) {
7347  record:
7348                 if (!easy)
7349                         goto end;
7350                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7351                 goto end;
7352         }
7353
7354 #if DEBUG
7355         switch (subtype) {
7356         case VSTRIMLEFT:
7357         case VSTRIMLEFTMAX:
7358         case VSTRIMRIGHT:
7359         case VSTRIMRIGHTMAX:
7360 #if BASH_SUBSTR
7361         case VSSUBSTR:
7362 #endif
7363 #if BASH_PATTERN_SUBST
7364         case VSREPLACE:
7365         case VSREPLACEALL:
7366 #endif
7367                 break;
7368         default:
7369                 abort();
7370         }
7371 #endif
7372
7373         if (varlen >= 0) {
7374                 /*
7375                  * Terminate the string and start recording the pattern
7376                  * right after it
7377                  */
7378                 STPUTC('\0', expdest);
7379                 patloc = expdest - (char *)stackblock();
7380                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7381                                 startloc, varflags, flag)) {
7382                         int amount = expdest - (
7383                                 (char *)stackblock() + patloc - 1
7384                         );
7385                         STADJUST(-amount, expdest);
7386                 }
7387                 /* Remove any recorded regions beyond start of variable */
7388                 removerecordregions(startloc);
7389                 goto record;
7390         }
7391
7392  end:
7393         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7394                 int nesting = 1;
7395                 for (;;) {
7396                         unsigned char c = *p++;
7397                         if (c == CTLESC)
7398                                 p++;
7399                         else if (c == CTLBACKQ) {
7400                                 if (varlen >= 0)
7401                                         argbackq = argbackq->next;
7402                         } else if (c == CTLVAR) {
7403                                 if ((*p++ & VSTYPE) != VSNORMAL)
7404                                         nesting++;
7405                         } else if (c == CTLENDVAR) {
7406                                 if (--nesting == 0)
7407                                         break;
7408                         }
7409                 }
7410         }
7411         return p;
7412 }
7413
7414 /*
7415  * Add a file name to the list.
7416  */
7417 static void
7418 addfname(const char *name)
7419 {
7420         struct strlist *sp;
7421
7422         sp = stzalloc(sizeof(*sp));
7423         sp->text = sstrdup(name);
7424         *exparg.lastp = sp;
7425         exparg.lastp = &sp->next;
7426 }
7427
7428 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7429 static int
7430 hasmeta(const char *p)
7431 {
7432         static const char chars[] ALIGN1 = {
7433                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7434         };
7435
7436         for (;;) {
7437                 p = strpbrk(p, chars);
7438                 if (!p)
7439                         break;
7440                 switch ((unsigned char)*p) {
7441                 case CTLQUOTEMARK:
7442                         for (;;) {
7443                                 p++;
7444                                 if ((unsigned char)*p == CTLQUOTEMARK)
7445                                         break;
7446                                 if ((unsigned char)*p == CTLESC)
7447                                         p++;
7448                                 if (*p == '\0') /* huh? */
7449                                         return 0;
7450                         }
7451                         break;
7452                 case '\\':
7453                 case CTLESC:
7454                         p++;
7455                         if (*p == '\0')
7456                                 return 0;
7457                         break;
7458                 case '[':
7459                         if (!strchr(p + 1, ']')) {
7460                                 /* It's not a properly closed [] pattern,
7461                                  * but other metas may follow. Continue checking.
7462                                  * my[file* _is_ globbed by bash
7463                                  * and matches filenames like "my[file1".
7464                                  */
7465                                 break;
7466                         }
7467                         /* fallthrough */
7468                 default:
7469                 /* case '*': */
7470                 /* case '?': */
7471                         return 1;
7472                 }
7473                 p++;
7474         }
7475
7476         return 0;
7477 }
7478
7479 /* If we want to use glob() from libc... */
7480 #if !ENABLE_ASH_INTERNAL_GLOB
7481
7482 /* Add the result of glob() to the list */
7483 static void
7484 addglob(const glob_t *pglob)
7485 {
7486         char **p = pglob->gl_pathv;
7487
7488         do {
7489                 addfname(*p);
7490         } while (*++p);
7491 }
7492 static void
7493 expandmeta(struct strlist *str /*, int flag*/)
7494 {
7495         /* TODO - EXP_REDIR */
7496
7497         while (str) {
7498                 char *p;
7499                 glob_t pglob;
7500                 int i;
7501
7502                 if (fflag)
7503                         goto nometa;
7504
7505                 if (!hasmeta(str->text))
7506                         goto nometa;
7507
7508                 INT_OFF;
7509                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7510 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7511 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7512 //
7513 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7514 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7515 // Which means you need to unescape the string, right? Not so fast:
7516 // if there _is_ a file named "file\?" (with backslash), it is returned
7517 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7518 // You DON'T KNOW by looking at the result whether you need to unescape it.
7519 //
7520 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7521 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7522 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7523 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7524 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7525 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7526                 i = glob(p, 0, NULL, &pglob);
7527                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7528                 if (p != str->text)
7529                         free(p);
7530                 switch (i) {
7531                 case 0:
7532 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7533                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7534                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7535                                 goto nometa2;
7536 #endif
7537                         addglob(&pglob);
7538                         globfree(&pglob);
7539                         INT_ON;
7540                         break;
7541                 case GLOB_NOMATCH:
7542  //nometa2:
7543                         globfree(&pglob);
7544                         INT_ON;
7545  nometa:
7546                         *exparg.lastp = str;
7547                         rmescapes(str->text, 0, NULL);
7548                         exparg.lastp = &str->next;
7549                         break;
7550                 default:        /* GLOB_NOSPACE */
7551                         globfree(&pglob);
7552                         INT_ON;
7553                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7554                 }
7555                 str = str->next;
7556         }
7557 }
7558
7559 #else
7560 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7561
7562 /*
7563  * Do metacharacter (i.e. *, ?, [...]) expansion.
7564  */
7565 static void
7566 expmeta(char *expdir, char *enddir, char *name)
7567 {
7568         char *p;
7569         const char *cp;
7570         char *start;
7571         char *endname;
7572         int metaflag;
7573         struct stat statb;
7574         DIR *dirp;
7575         struct dirent *dp;
7576         int atend;
7577         int matchdot;
7578         int esc;
7579
7580         metaflag = 0;
7581         start = name;
7582         for (p = name; esc = 0, *p; p += esc + 1) {
7583                 if (*p == '*' || *p == '?')
7584                         metaflag = 1;
7585                 else if (*p == '[') {
7586                         char *q = p + 1;
7587                         if (*q == '!')
7588                                 q++;
7589                         for (;;) {
7590                                 if (*q == '\\')
7591                                         q++;
7592                                 if (*q == '/' || *q == '\0')
7593                                         break;
7594                                 if (*++q == ']') {
7595                                         metaflag = 1;
7596                                         break;
7597                                 }
7598                         }
7599                 } else {
7600                         if (*p == '\\')
7601                                 esc++;
7602                         if (p[esc] == '/') {
7603                                 if (metaflag)
7604                                         break;
7605                                 start = p + esc + 1;
7606                         }
7607                 }
7608         }
7609         if (metaflag == 0) {    /* we've reached the end of the file name */
7610                 if (enddir != expdir)
7611                         metaflag++;
7612                 p = name;
7613                 do {
7614                         if (*p == '\\')
7615                                 p++;
7616                         *enddir++ = *p;
7617                 } while (*p++);
7618                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7619                         addfname(expdir);
7620                 return;
7621         }
7622         endname = p;
7623         if (name < start) {
7624                 p = name;
7625                 do {
7626                         if (*p == '\\')
7627                                 p++;
7628                         *enddir++ = *p++;
7629                 } while (p < start);
7630         }
7631         if (enddir == expdir) {
7632                 cp = ".";
7633         } else if (enddir == expdir + 1 && *expdir == '/') {
7634                 cp = "/";
7635         } else {
7636                 cp = expdir;
7637                 enddir[-1] = '\0';
7638         }
7639         dirp = opendir(cp);
7640         if (dirp == NULL)
7641                 return;
7642         if (enddir != expdir)
7643                 enddir[-1] = '/';
7644         if (*endname == 0) {
7645                 atend = 1;
7646         } else {
7647                 atend = 0;
7648                 *endname = '\0';
7649                 endname += esc + 1;
7650         }
7651         matchdot = 0;
7652         p = start;
7653         if (*p == '\\')
7654                 p++;
7655         if (*p == '.')
7656                 matchdot++;
7657         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7658                 if (dp->d_name[0] == '.' && !matchdot)
7659                         continue;
7660                 if (pmatch(start, dp->d_name)) {
7661                         if (atend) {
7662                                 strcpy(enddir, dp->d_name);
7663                                 addfname(expdir);
7664                         } else {
7665                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7666                                         continue;
7667                                 p[-1] = '/';
7668                                 expmeta(expdir, p, endname);
7669                         }
7670                 }
7671         }
7672         closedir(dirp);
7673         if (!atend)
7674                 endname[-esc - 1] = esc ? '\\' : '/';
7675 }
7676
7677 static struct strlist *
7678 msort(struct strlist *list, int len)
7679 {
7680         struct strlist *p, *q = NULL;
7681         struct strlist **lpp;
7682         int half;
7683         int n;
7684
7685         if (len <= 1)
7686                 return list;
7687         half = len >> 1;
7688         p = list;
7689         for (n = half; --n >= 0;) {
7690                 q = p;
7691                 p = p->next;
7692         }
7693         q->next = NULL;                 /* terminate first half of list */
7694         q = msort(list, half);          /* sort first half of list */
7695         p = msort(p, len - half);               /* sort second half */
7696         lpp = &list;
7697         for (;;) {
7698 #if ENABLE_LOCALE_SUPPORT
7699                 if (strcoll(p->text, q->text) < 0)
7700 #else
7701                 if (strcmp(p->text, q->text) < 0)
7702 #endif
7703                                                 {
7704                         *lpp = p;
7705                         lpp = &p->next;
7706                         p = *lpp;
7707                         if (p == NULL) {
7708                                 *lpp = q;
7709                                 break;
7710                         }
7711                 } else {
7712                         *lpp = q;
7713                         lpp = &q->next;
7714                         q = *lpp;
7715                         if (q == NULL) {
7716                                 *lpp = p;
7717                                 break;
7718                         }
7719                 }
7720         }
7721         return list;
7722 }
7723
7724 /*
7725  * Sort the results of file name expansion.  It calculates the number of
7726  * strings to sort and then calls msort (short for merge sort) to do the
7727  * work.
7728  */
7729 static struct strlist *
7730 expsort(struct strlist *str)
7731 {
7732         int len;
7733         struct strlist *sp;
7734
7735         len = 0;
7736         for (sp = str; sp; sp = sp->next)
7737                 len++;
7738         return msort(str, len);
7739 }
7740
7741 static void
7742 expandmeta(struct strlist *str /*, int flag*/)
7743 {
7744         /* TODO - EXP_REDIR */
7745
7746         while (str) {
7747                 char *expdir;
7748                 struct strlist **savelastp;
7749                 struct strlist *sp;
7750                 char *p;
7751
7752                 if (fflag)
7753                         goto nometa;
7754                 if (!hasmeta(str->text))
7755                         goto nometa;
7756                 savelastp = exparg.lastp;
7757
7758                 INT_OFF;
7759                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7760                 {
7761                         int i = strlen(str->text);
7762 //BUGGY estimation of how long expanded name can be
7763                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7764                 }
7765                 expmeta(expdir, expdir, p);
7766                 free(expdir);
7767                 if (p != str->text)
7768                         free(p);
7769                 INT_ON;
7770                 if (exparg.lastp == savelastp) {
7771                         /*
7772                          * no matches
7773                          */
7774  nometa:
7775                         *exparg.lastp = str;
7776                         rmescapes(str->text, 0, NULL);
7777                         exparg.lastp = &str->next;
7778                 } else {
7779                         *exparg.lastp = NULL;
7780                         *savelastp = sp = expsort(*savelastp);
7781                         while (sp->next != NULL)
7782                                 sp = sp->next;
7783                         exparg.lastp = &sp->next;
7784                 }
7785                 str = str->next;
7786         }
7787 }
7788 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7789
7790 /*
7791  * Perform variable substitution and command substitution on an argument,
7792  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7793  * perform splitting and file name expansion.  When arglist is NULL, perform
7794  * here document expansion.
7795  */
7796 static void
7797 expandarg(union node *arg, struct arglist *arglist, int flag)
7798 {
7799         struct strlist *sp;
7800         char *p;
7801
7802         argbackq = arg->narg.backquote;
7803         STARTSTACKSTR(expdest);
7804         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7805         argstr(arg->narg.text, flag);
7806         p = _STPUTC('\0', expdest);
7807         expdest = p - 1;
7808         if (arglist == NULL) {
7809                 /* here document expanded */
7810                 goto out;
7811         }
7812         p = grabstackstr(p);
7813         TRACE(("expandarg: p:'%s'\n", p));
7814         exparg.lastp = &exparg.list;
7815         /*
7816          * TODO - EXP_REDIR
7817          */
7818         if (flag & EXP_FULL) {
7819                 ifsbreakup(p, &exparg);
7820                 *exparg.lastp = NULL;
7821                 exparg.lastp = &exparg.list;
7822                 expandmeta(exparg.list /*, flag*/);
7823         } else {
7824                 sp = stzalloc(sizeof(*sp));
7825                 sp->text = p;
7826                 *exparg.lastp = sp;
7827                 exparg.lastp = &sp->next;
7828         }
7829         *exparg.lastp = NULL;
7830         if (exparg.list) {
7831                 *arglist->lastp = exparg.list;
7832                 arglist->lastp = exparg.lastp;
7833         }
7834
7835  out:
7836         ifsfree();
7837 }
7838
7839 /*
7840  * Expand shell variables and backquotes inside a here document.
7841  */
7842 static void
7843 expandhere(union node *arg, int fd)
7844 {
7845         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7846         full_write(fd, stackblock(), expdest - (char *)stackblock());
7847 }
7848
7849 /*
7850  * Returns true if the pattern matches the string.
7851  */
7852 static int
7853 patmatch(char *pattern, const char *string)
7854 {
7855         char *p = preglob(pattern, 0);
7856         int r = pmatch(p, string);
7857         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7858         return r;
7859 }
7860
7861 /*
7862  * See if a pattern matches in a case statement.
7863  */
7864 static int
7865 casematch(union node *pattern, char *val)
7866 {
7867         struct stackmark smark;
7868         int result;
7869
7870         setstackmark(&smark);
7871         argbackq = pattern->narg.backquote;
7872         STARTSTACKSTR(expdest);
7873         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7874         STACKSTRNUL(expdest);
7875         ifsfree();
7876         result = patmatch(stackblock(), val);
7877         popstackmark(&smark);
7878         return result;
7879 }
7880
7881
7882 /* ============ find_command */
7883
7884 struct builtincmd {
7885         const char *name;
7886         int (*builtin)(int, char **) FAST_FUNC;
7887         /* unsigned flags; */
7888 };
7889 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7890 /* "regular" builtins always take precedence over commands,
7891  * regardless of PATH=....%builtin... position */
7892 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7893 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7894
7895 struct cmdentry {
7896         smallint cmdtype;       /* CMDxxx */
7897         union param {
7898                 int index;
7899                 /* index >= 0 for commands without path (slashes) */
7900                 /* (TODO: what exactly does the value mean? PATH position?) */
7901                 /* index == -1 for commands with slashes */
7902                 /* index == (-2 - applet_no) for NOFORK applets */
7903                 const struct builtincmd *cmd;
7904                 struct funcnode *func;
7905         } u;
7906 };
7907 /* values of cmdtype */
7908 #define CMDUNKNOWN      -1      /* no entry in table for command */
7909 #define CMDNORMAL       0       /* command is an executable program */
7910 #define CMDFUNCTION     1       /* command is a shell function */
7911 #define CMDBUILTIN      2       /* command is a shell builtin */
7912
7913 /* action to find_command() */
7914 #define DO_ERR          0x01    /* prints errors */
7915 #define DO_ABS          0x02    /* checks absolute paths */
7916 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7917 #define DO_ALTPATH      0x08    /* using alternate path */
7918 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7919
7920 static void find_command(char *, struct cmdentry *, int, const char *);
7921
7922
7923 /* ============ Hashing commands */
7924
7925 /*
7926  * When commands are first encountered, they are entered in a hash table.
7927  * This ensures that a full path search will not have to be done for them
7928  * on each invocation.
7929  *
7930  * We should investigate converting to a linear search, even though that
7931  * would make the command name "hash" a misnomer.
7932  */
7933
7934 struct tblentry {
7935         struct tblentry *next;  /* next entry in hash chain */
7936         union param param;      /* definition of builtin function */
7937         smallint cmdtype;       /* CMDxxx */
7938         char rehash;            /* if set, cd done since entry created */
7939         char cmdname[1];        /* name of command */
7940 };
7941
7942 static struct tblentry **cmdtable;
7943 #define INIT_G_cmdtable() do { \
7944         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7945 } while (0)
7946
7947 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7948
7949
7950 static void
7951 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7952 {
7953 #if ENABLE_FEATURE_SH_STANDALONE
7954         if (applet_no >= 0) {
7955                 if (APPLET_IS_NOEXEC(applet_no)) {
7956                         clearenv();
7957                         while (*envp)
7958                                 putenv(*envp++);
7959                         popredir(/*drop:*/ 1);
7960                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7961                 }
7962                 /* re-exec ourselves with the new arguments */
7963                 execve(bb_busybox_exec_path, argv, envp);
7964                 /* If they called chroot or otherwise made the binary no longer
7965                  * executable, fall through */
7966         }
7967 #endif
7968
7969  repeat:
7970 #ifdef SYSV
7971         do {
7972                 execve(cmd, argv, envp);
7973         } while (errno == EINTR);
7974 #else
7975         execve(cmd, argv, envp);
7976 #endif
7977         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7978                 /* Run "cmd" as a shell script:
7979                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7980                  * "If the execve() function fails with ENOEXEC, the shell
7981                  * shall execute a command equivalent to having a shell invoked
7982                  * with the command name as its first operand,
7983                  * with any remaining arguments passed to the new shell"
7984                  *
7985                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7986                  * just call ourselves.
7987                  *
7988                  * Note that bash reads ~80 chars of the file, and if it sees
7989                  * a zero byte before it sees newline, it doesn't try to
7990                  * interpret it, but fails with "cannot execute binary file"
7991                  * message and exit code 126. For one, this prevents attempts
7992                  * to interpret foreign ELF binaries as shell scripts.
7993                  */
7994                 argv[0] = (char*) cmd;
7995                 cmd = bb_busybox_exec_path;
7996                 /* NB: this is only possible because all callers of shellexec()
7997                  * ensure that the argv[-1] slot exists!
7998                  */
7999                 argv--;
8000                 argv[0] = (char*) "ash";
8001                 goto repeat;
8002         }
8003 }
8004
8005 /*
8006  * Exec a program.  Never returns.  If you change this routine, you may
8007  * have to change the find_command routine as well.
8008  * argv[-1] must exist and be writable! See tryexec() for why.
8009  */
8010 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8011 static void shellexec(char *prog, char **argv, const char *path, int idx)
8012 {
8013         char *cmdname;
8014         int e;
8015         char **envp;
8016         int exerrno;
8017         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8018
8019         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8020         if (strchr(prog, '/') != NULL
8021 #if ENABLE_FEATURE_SH_STANDALONE
8022          || (applet_no = find_applet_by_name(prog)) >= 0
8023 #endif
8024         ) {
8025                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8026                 if (applet_no >= 0) {
8027                         /* We tried execing ourself, but it didn't work.
8028                          * Maybe /proc/self/exe doesn't exist?
8029                          * Try $PATH search.
8030                          */
8031                         goto try_PATH;
8032                 }
8033                 e = errno;
8034         } else {
8035  try_PATH:
8036                 e = ENOENT;
8037                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8038                         if (--idx < 0 && pathopt == NULL) {
8039                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8040                                 if (errno != ENOENT && errno != ENOTDIR)
8041                                         e = errno;
8042                         }
8043                         stunalloc(cmdname);
8044                 }
8045         }
8046
8047         /* Map to POSIX errors */
8048         switch (e) {
8049         case EACCES:
8050                 exerrno = 126;
8051                 break;
8052         case ENOENT:
8053                 exerrno = 127;
8054                 break;
8055         default:
8056                 exerrno = 2;
8057                 break;
8058         }
8059         exitstatus = exerrno;
8060         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8061                 prog, e, suppress_int));
8062         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8063         /* NOTREACHED */
8064 }
8065
8066 static void
8067 printentry(struct tblentry *cmdp)
8068 {
8069         int idx;
8070         const char *path;
8071         char *name;
8072
8073         idx = cmdp->param.index;
8074         path = pathval();
8075         do {
8076                 name = path_advance(&path, cmdp->cmdname);
8077                 stunalloc(name);
8078         } while (--idx >= 0);
8079         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8080 }
8081
8082 /*
8083  * Clear out command entries.  The argument specifies the first entry in
8084  * PATH which has changed.
8085  */
8086 static void
8087 clearcmdentry(int firstchange)
8088 {
8089         struct tblentry **tblp;
8090         struct tblentry **pp;
8091         struct tblentry *cmdp;
8092
8093         INT_OFF;
8094         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8095                 pp = tblp;
8096                 while ((cmdp = *pp) != NULL) {
8097                         if ((cmdp->cmdtype == CMDNORMAL &&
8098                              cmdp->param.index >= firstchange)
8099                          || (cmdp->cmdtype == CMDBUILTIN &&
8100                              builtinloc >= firstchange)
8101                         ) {
8102                                 *pp = cmdp->next;
8103                                 free(cmdp);
8104                         } else {
8105                                 pp = &cmdp->next;
8106                         }
8107                 }
8108         }
8109         INT_ON;
8110 }
8111
8112 /*
8113  * Locate a command in the command hash table.  If "add" is nonzero,
8114  * add the command to the table if it is not already present.  The
8115  * variable "lastcmdentry" is set to point to the address of the link
8116  * pointing to the entry, so that delete_cmd_entry can delete the
8117  * entry.
8118  *
8119  * Interrupts must be off if called with add != 0.
8120  */
8121 static struct tblentry **lastcmdentry;
8122
8123 static struct tblentry *
8124 cmdlookup(const char *name, int add)
8125 {
8126         unsigned int hashval;
8127         const char *p;
8128         struct tblentry *cmdp;
8129         struct tblentry **pp;
8130
8131         p = name;
8132         hashval = (unsigned char)*p << 4;
8133         while (*p)
8134                 hashval += (unsigned char)*p++;
8135         hashval &= 0x7FFF;
8136         pp = &cmdtable[hashval % CMDTABLESIZE];
8137         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8138                 if (strcmp(cmdp->cmdname, name) == 0)
8139                         break;
8140                 pp = &cmdp->next;
8141         }
8142         if (add && cmdp == NULL) {
8143                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8144                                 + strlen(name)
8145                                 /* + 1 - already done because
8146                                  * tblentry::cmdname is char[1] */);
8147                 /*cmdp->next = NULL; - ckzalloc did it */
8148                 cmdp->cmdtype = CMDUNKNOWN;
8149                 strcpy(cmdp->cmdname, name);
8150         }
8151         lastcmdentry = pp;
8152         return cmdp;
8153 }
8154
8155 /*
8156  * Delete the command entry returned on the last lookup.
8157  */
8158 static void
8159 delete_cmd_entry(void)
8160 {
8161         struct tblentry *cmdp;
8162
8163         INT_OFF;
8164         cmdp = *lastcmdentry;
8165         *lastcmdentry = cmdp->next;
8166         if (cmdp->cmdtype == CMDFUNCTION)
8167                 freefunc(cmdp->param.func);
8168         free(cmdp);
8169         INT_ON;
8170 }
8171
8172 /*
8173  * Add a new command entry, replacing any existing command entry for
8174  * the same name - except special builtins.
8175  */
8176 static void
8177 addcmdentry(char *name, struct cmdentry *entry)
8178 {
8179         struct tblentry *cmdp;
8180
8181         cmdp = cmdlookup(name, 1);
8182         if (cmdp->cmdtype == CMDFUNCTION) {
8183                 freefunc(cmdp->param.func);
8184         }
8185         cmdp->cmdtype = entry->cmdtype;
8186         cmdp->param = entry->u;
8187         cmdp->rehash = 0;
8188 }
8189
8190 static int FAST_FUNC
8191 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8192 {
8193         struct tblentry **pp;
8194         struct tblentry *cmdp;
8195         int c;
8196         struct cmdentry entry;
8197         char *name;
8198
8199         if (nextopt("r") != '\0') {
8200                 clearcmdentry(0);
8201                 return 0;
8202         }
8203
8204         if (*argptr == NULL) {
8205                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8206                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8207                                 if (cmdp->cmdtype == CMDNORMAL)
8208                                         printentry(cmdp);
8209                         }
8210                 }
8211                 return 0;
8212         }
8213
8214         c = 0;
8215         while ((name = *argptr) != NULL) {
8216                 cmdp = cmdlookup(name, 0);
8217                 if (cmdp != NULL
8218                  && (cmdp->cmdtype == CMDNORMAL
8219                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8220                 ) {
8221                         delete_cmd_entry();
8222                 }
8223                 find_command(name, &entry, DO_ERR, pathval());
8224                 if (entry.cmdtype == CMDUNKNOWN)
8225                         c = 1;
8226                 argptr++;
8227         }
8228         return c;
8229 }
8230
8231 /*
8232  * Called when a cd is done.  Marks all commands so the next time they
8233  * are executed they will be rehashed.
8234  */
8235 static void
8236 hashcd(void)
8237 {
8238         struct tblentry **pp;
8239         struct tblentry *cmdp;
8240
8241         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8242                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8243                         if (cmdp->cmdtype == CMDNORMAL
8244                          || (cmdp->cmdtype == CMDBUILTIN
8245                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8246                              && builtinloc > 0)
8247                         ) {
8248                                 cmdp->rehash = 1;
8249                         }
8250                 }
8251         }
8252 }
8253
8254 /*
8255  * Fix command hash table when PATH changed.
8256  * Called before PATH is changed.  The argument is the new value of PATH;
8257  * pathval() still returns the old value at this point.
8258  * Called with interrupts off.
8259  */
8260 static void FAST_FUNC
8261 changepath(const char *new)
8262 {
8263         const char *old;
8264         int firstchange;
8265         int idx;
8266         int idx_bltin;
8267
8268         old = pathval();
8269         firstchange = 9999;     /* assume no change */
8270         idx = 0;
8271         idx_bltin = -1;
8272         for (;;) {
8273                 if (*old != *new) {
8274                         firstchange = idx;
8275                         if ((*old == '\0' && *new == ':')
8276                          || (*old == ':' && *new == '\0')
8277                         ) {
8278                                 firstchange++;
8279                         }
8280                         old = new;      /* ignore subsequent differences */
8281                 }
8282                 if (*new == '\0')
8283                         break;
8284                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8285                         idx_bltin = idx;
8286                 if (*new == ':')
8287                         idx++;
8288                 new++;
8289                 old++;
8290         }
8291         if (builtinloc < 0 && idx_bltin >= 0)
8292                 builtinloc = idx_bltin;             /* zap builtins */
8293         if (builtinloc >= 0 && idx_bltin < 0)
8294                 firstchange = 0;
8295         clearcmdentry(firstchange);
8296         builtinloc = idx_bltin;
8297 }
8298 enum {
8299         TEOF,
8300         TNL,
8301         TREDIR,
8302         TWORD,
8303         TSEMI,
8304         TBACKGND,
8305         TAND,
8306         TOR,
8307         TPIPE,
8308         TLP,
8309         TRP,
8310         TENDCASE,
8311         TENDBQUOTE,
8312         TNOT,
8313         TCASE,
8314         TDO,
8315         TDONE,
8316         TELIF,
8317         TELSE,
8318         TESAC,
8319         TFI,
8320         TFOR,
8321 #if BASH_FUNCTION
8322         TFUNCTION,
8323 #endif
8324         TIF,
8325         TIN,
8326         TTHEN,
8327         TUNTIL,
8328         TWHILE,
8329         TBEGIN,
8330         TEND
8331 };
8332 typedef smallint token_id_t;
8333
8334 /* Nth bit indicates if token marks the end of a list */
8335 enum {
8336         tokendlist = 0
8337         /*  0 */ | (1u << TEOF)
8338         /*  1 */ | (0u << TNL)
8339         /*  2 */ | (0u << TREDIR)
8340         /*  3 */ | (0u << TWORD)
8341         /*  4 */ | (0u << TSEMI)
8342         /*  5 */ | (0u << TBACKGND)
8343         /*  6 */ | (0u << TAND)
8344         /*  7 */ | (0u << TOR)
8345         /*  8 */ | (0u << TPIPE)
8346         /*  9 */ | (0u << TLP)
8347         /* 10 */ | (1u << TRP)
8348         /* 11 */ | (1u << TENDCASE)
8349         /* 12 */ | (1u << TENDBQUOTE)
8350         /* 13 */ | (0u << TNOT)
8351         /* 14 */ | (0u << TCASE)
8352         /* 15 */ | (1u << TDO)
8353         /* 16 */ | (1u << TDONE)
8354         /* 17 */ | (1u << TELIF)
8355         /* 18 */ | (1u << TELSE)
8356         /* 19 */ | (1u << TESAC)
8357         /* 20 */ | (1u << TFI)
8358         /* 21 */ | (0u << TFOR)
8359 #if BASH_FUNCTION
8360         /* 22 */ | (0u << TFUNCTION)
8361 #endif
8362         /* 23 */ | (0u << TIF)
8363         /* 24 */ | (0u << TIN)
8364         /* 25 */ | (1u << TTHEN)
8365         /* 26 */ | (0u << TUNTIL)
8366         /* 27 */ | (0u << TWHILE)
8367         /* 28 */ | (0u << TBEGIN)
8368         /* 29 */ | (1u << TEND)
8369         , /* thus far 29 bits used */
8370 };
8371
8372 static const char *const tokname_array[] = {
8373         "end of file",
8374         "newline",
8375         "redirection",
8376         "word",
8377         ";",
8378         "&",
8379         "&&",
8380         "||",
8381         "|",
8382         "(",
8383         ")",
8384         ";;",
8385         "`",
8386 #define KWDOFFSET 13
8387         /* the following are keywords */
8388         "!",
8389         "case",
8390         "do",
8391         "done",
8392         "elif",
8393         "else",
8394         "esac",
8395         "fi",
8396         "for",
8397 #if BASH_FUNCTION
8398         "function",
8399 #endif
8400         "if",
8401         "in",
8402         "then",
8403         "until",
8404         "while",
8405         "{",
8406         "}",
8407 };
8408
8409 /* Wrapper around strcmp for qsort/bsearch/... */
8410 static int
8411 pstrcmp(const void *a, const void *b)
8412 {
8413         return strcmp((char*)a, *(char**)b);
8414 }
8415
8416 static const char *const *
8417 findkwd(const char *s)
8418 {
8419         return bsearch(s, tokname_array + KWDOFFSET,
8420                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8421                         sizeof(tokname_array[0]), pstrcmp);
8422 }
8423
8424 /*
8425  * Locate and print what a word is...
8426  */
8427 static int
8428 describe_command(char *command, const char *path, int describe_command_verbose)
8429 {
8430         struct cmdentry entry;
8431 #if ENABLE_ASH_ALIAS
8432         const struct alias *ap;
8433 #endif
8434
8435         path = path ? path : pathval();
8436
8437         if (describe_command_verbose) {
8438                 out1str(command);
8439         }
8440
8441         /* First look at the keywords */
8442         if (findkwd(command)) {
8443                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8444                 goto out;
8445         }
8446
8447 #if ENABLE_ASH_ALIAS
8448         /* Then look at the aliases */
8449         ap = lookupalias(command, 0);
8450         if (ap != NULL) {
8451                 if (!describe_command_verbose) {
8452                         out1str("alias ");
8453                         printalias(ap);
8454                         return 0;
8455                 }
8456                 out1fmt(" is an alias for %s", ap->val);
8457                 goto out;
8458         }
8459 #endif
8460         /* Brute force */
8461         find_command(command, &entry, DO_ABS, path);
8462
8463         switch (entry.cmdtype) {
8464         case CMDNORMAL: {
8465                 int j = entry.u.index;
8466                 char *p;
8467                 if (j < 0) {
8468                         p = command;
8469                 } else {
8470                         do {
8471                                 p = path_advance(&path, command);
8472                                 stunalloc(p);
8473                         } while (--j >= 0);
8474                 }
8475                 if (describe_command_verbose) {
8476                         out1fmt(" is %s", p);
8477                 } else {
8478                         out1str(p);
8479                 }
8480                 break;
8481         }
8482
8483         case CMDFUNCTION:
8484                 if (describe_command_verbose) {
8485                         out1str(" is a shell function");
8486                 } else {
8487                         out1str(command);
8488                 }
8489                 break;
8490
8491         case CMDBUILTIN:
8492                 if (describe_command_verbose) {
8493                         out1fmt(" is a %sshell builtin",
8494                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8495                                         "special " : nullstr
8496                         );
8497                 } else {
8498                         out1str(command);
8499                 }
8500                 break;
8501
8502         default:
8503                 if (describe_command_verbose) {
8504                         out1str(": not found\n");
8505                 }
8506                 return 127;
8507         }
8508  out:
8509         out1str("\n");
8510         return 0;
8511 }
8512
8513 static int FAST_FUNC
8514 typecmd(int argc UNUSED_PARAM, char **argv)
8515 {
8516         int i = 1;
8517         int err = 0;
8518         int verbose = 1;
8519
8520         /* type -p ... ? (we don't bother checking for 'p') */
8521         if (argv[1] && argv[1][0] == '-') {
8522                 i++;
8523                 verbose = 0;
8524         }
8525         while (argv[i]) {
8526                 err |= describe_command(argv[i++], NULL, verbose);
8527         }
8528         return err;
8529 }
8530
8531 #if ENABLE_ASH_CMDCMD
8532 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8533 static char **
8534 parse_command_args(char **argv, const char **path)
8535 {
8536         char *cp, c;
8537
8538         for (;;) {
8539                 cp = *++argv;
8540                 if (!cp)
8541                         return NULL;
8542                 if (*cp++ != '-')
8543                         break;
8544                 c = *cp++;
8545                 if (!c)
8546                         break;
8547                 if (c == '-' && !*cp) {
8548                         if (!*++argv)
8549                                 return NULL;
8550                         break;
8551                 }
8552                 do {
8553                         switch (c) {
8554                         case 'p':
8555                                 *path = bb_default_path;
8556                                 break;
8557                         default:
8558                                 /* run 'typecmd' for other options */
8559                                 return NULL;
8560                         }
8561                         c = *cp++;
8562                 } while (c);
8563         }
8564         return argv;
8565 }
8566
8567 static int FAST_FUNC
8568 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8569 {
8570         char *cmd;
8571         int c;
8572         enum {
8573                 VERIFY_BRIEF = 1,
8574                 VERIFY_VERBOSE = 2,
8575         } verify = 0;
8576         const char *path = NULL;
8577
8578         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8579          * never reaches this function.
8580          */
8581
8582         while ((c = nextopt("pvV")) != '\0')
8583                 if (c == 'V')
8584                         verify |= VERIFY_VERBOSE;
8585                 else if (c == 'v')
8586                         /*verify |= VERIFY_BRIEF*/;
8587 #if DEBUG
8588                 else if (c != 'p')
8589                         abort();
8590 #endif
8591                 else
8592                         path = bb_default_path;
8593
8594         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8595         cmd = *argptr;
8596         if (/*verify && */ cmd)
8597                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8598
8599         return 0;
8600 }
8601 #endif
8602
8603
8604 /*static int funcblocksize;     // size of structures in function */
8605 /*static int funcstringsize;    // size of strings in node */
8606 static void *funcblock;         /* block to allocate function from */
8607 static char *funcstring_end;    /* end of block to allocate strings from */
8608
8609 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8610         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8611         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8612         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8613         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8614         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8615         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8616         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8617         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8618         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8619         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8620         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8621         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8622         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8623         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8624         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8625         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8626         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8627 #if BASH_REDIR_OUTPUT
8628         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8629 #endif
8630         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8631         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8632         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8633         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8634         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8635         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8636         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8637         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8638         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8639 };
8640
8641 static int calcsize(int funcblocksize, union node *n);
8642
8643 static int
8644 sizenodelist(int funcblocksize, struct nodelist *lp)
8645 {
8646         while (lp) {
8647                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8648                 funcblocksize = calcsize(funcblocksize, lp->n);
8649                 lp = lp->next;
8650         }
8651         return funcblocksize;
8652 }
8653
8654 static int
8655 calcsize(int funcblocksize, union node *n)
8656 {
8657         if (n == NULL)
8658                 return funcblocksize;
8659         funcblocksize += nodesize[n->type];
8660         switch (n->type) {
8661         case NCMD:
8662                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8663                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8664                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8665                 break;
8666         case NPIPE:
8667                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8668                 break;
8669         case NREDIR:
8670         case NBACKGND:
8671         case NSUBSHELL:
8672                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8673                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8674                 break;
8675         case NAND:
8676         case NOR:
8677         case NSEMI:
8678         case NWHILE:
8679         case NUNTIL:
8680                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8681                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8682                 break;
8683         case NIF:
8684                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8685                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8686                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8687                 break;
8688         case NFOR:
8689                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8690                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8691                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8692                 break;
8693         case NCASE:
8694                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8695                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8696                 break;
8697         case NCLIST:
8698                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8699                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8700                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8701                 break;
8702         case NDEFUN:
8703                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8704                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8705                 break;
8706         case NARG:
8707                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8708                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8709                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8710                 break;
8711         case NTO:
8712 #if BASH_REDIR_OUTPUT
8713         case NTO2:
8714 #endif
8715         case NCLOBBER:
8716         case NFROM:
8717         case NFROMTO:
8718         case NAPPEND:
8719                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8720                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8721                 break;
8722         case NTOFD:
8723         case NFROMFD:
8724                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8725                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8726         break;
8727         case NHERE:
8728         case NXHERE:
8729                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8730                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8731                 break;
8732         case NNOT:
8733                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8734                 break;
8735         };
8736         return funcblocksize;
8737 }
8738
8739 static char *
8740 nodeckstrdup(char *s)
8741 {
8742         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8743         return strcpy(funcstring_end, s);
8744 }
8745
8746 static union node *copynode(union node *);
8747
8748 static struct nodelist *
8749 copynodelist(struct nodelist *lp)
8750 {
8751         struct nodelist *start;
8752         struct nodelist **lpp;
8753
8754         lpp = &start;
8755         while (lp) {
8756                 *lpp = funcblock;
8757                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8758                 (*lpp)->n = copynode(lp->n);
8759                 lp = lp->next;
8760                 lpp = &(*lpp)->next;
8761         }
8762         *lpp = NULL;
8763         return start;
8764 }
8765
8766 static union node *
8767 copynode(union node *n)
8768 {
8769         union node *new;
8770
8771         if (n == NULL)
8772                 return NULL;
8773         new = funcblock;
8774         funcblock = (char *) funcblock + nodesize[n->type];
8775
8776         switch (n->type) {
8777         case NCMD:
8778                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8779                 new->ncmd.args = copynode(n->ncmd.args);
8780                 new->ncmd.assign = copynode(n->ncmd.assign);
8781                 new->ncmd.linno = n->ncmd.linno;
8782                 break;
8783         case NPIPE:
8784                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8785                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8786                 break;
8787         case NREDIR:
8788         case NBACKGND:
8789         case NSUBSHELL:
8790                 new->nredir.redirect = copynode(n->nredir.redirect);
8791                 new->nredir.n = copynode(n->nredir.n);
8792                 new->nredir.linno = n->nredir.linno;
8793                 break;
8794         case NAND:
8795         case NOR:
8796         case NSEMI:
8797         case NWHILE:
8798         case NUNTIL:
8799                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8800                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8801                 break;
8802         case NIF:
8803                 new->nif.elsepart = copynode(n->nif.elsepart);
8804                 new->nif.ifpart = copynode(n->nif.ifpart);
8805                 new->nif.test = copynode(n->nif.test);
8806                 break;
8807         case NFOR:
8808                 new->nfor.var = nodeckstrdup(n->nfor.var);
8809                 new->nfor.body = copynode(n->nfor.body);
8810                 new->nfor.args = copynode(n->nfor.args);
8811                 new->nfor.linno = n->nfor.linno;
8812                 break;
8813         case NCASE:
8814                 new->ncase.cases = copynode(n->ncase.cases);
8815                 new->ncase.expr = copynode(n->ncase.expr);
8816                 new->ncase.linno = n->ncase.linno;
8817                 break;
8818         case NCLIST:
8819                 new->nclist.body = copynode(n->nclist.body);
8820                 new->nclist.pattern = copynode(n->nclist.pattern);
8821                 new->nclist.next = copynode(n->nclist.next);
8822                 break;
8823         case NDEFUN:
8824                 new->ndefun.body = copynode(n->ndefun.body);
8825                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8826                 new->ndefun.linno = n->ndefun.linno;
8827                 break;
8828         case NARG:
8829                 new->narg.backquote = copynodelist(n->narg.backquote);
8830                 new->narg.text = nodeckstrdup(n->narg.text);
8831                 new->narg.next = copynode(n->narg.next);
8832                 break;
8833         case NTO:
8834 #if BASH_REDIR_OUTPUT
8835         case NTO2:
8836 #endif
8837         case NCLOBBER:
8838         case NFROM:
8839         case NFROMTO:
8840         case NAPPEND:
8841                 new->nfile.fname = copynode(n->nfile.fname);
8842                 new->nfile.fd = n->nfile.fd;
8843                 new->nfile.next = copynode(n->nfile.next);
8844                 break;
8845         case NTOFD:
8846         case NFROMFD:
8847                 new->ndup.vname = copynode(n->ndup.vname);
8848                 new->ndup.dupfd = n->ndup.dupfd;
8849                 new->ndup.fd = n->ndup.fd;
8850                 new->ndup.next = copynode(n->ndup.next);
8851                 break;
8852         case NHERE:
8853         case NXHERE:
8854                 new->nhere.doc = copynode(n->nhere.doc);
8855                 new->nhere.fd = n->nhere.fd;
8856                 new->nhere.next = copynode(n->nhere.next);
8857                 break;
8858         case NNOT:
8859                 new->nnot.com = copynode(n->nnot.com);
8860                 break;
8861         };
8862         new->type = n->type;
8863         return new;
8864 }
8865
8866 /*
8867  * Make a copy of a parse tree.
8868  */
8869 static struct funcnode *
8870 copyfunc(union node *n)
8871 {
8872         struct funcnode *f;
8873         size_t blocksize;
8874
8875         /*funcstringsize = 0;*/
8876         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8877         f = ckzalloc(blocksize /* + funcstringsize */);
8878         funcblock = (char *) f + offsetof(struct funcnode, n);
8879         funcstring_end = (char *) f + blocksize;
8880         copynode(n);
8881         /* f->count = 0; - ckzalloc did it */
8882         return f;
8883 }
8884
8885 /*
8886  * Define a shell function.
8887  */
8888 static void
8889 defun(union node *func)
8890 {
8891         struct cmdentry entry;
8892
8893         INT_OFF;
8894         entry.cmdtype = CMDFUNCTION;
8895         entry.u.func = copyfunc(func);
8896         addcmdentry(func->ndefun.text, &entry);
8897         INT_ON;
8898 }
8899
8900 /* Reasons for skipping commands (see comment on breakcmd routine) */
8901 #define SKIPBREAK      (1 << 0)
8902 #define SKIPCONT       (1 << 1)
8903 #define SKIPFUNC       (1 << 2)
8904 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8905 static int skipcount;           /* number of levels to skip */
8906 static int loopnest;            /* current loop nesting level */
8907 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8908
8909 /* Forward decl way out to parsing code - dotrap needs it */
8910 static int evalstring(char *s, int flags);
8911
8912 /* Called to execute a trap.
8913  * Single callsite - at the end of evaltree().
8914  * If we return non-zero, evaltree raises EXEXIT exception.
8915  *
8916  * Perhaps we should avoid entering new trap handlers
8917  * while we are executing a trap handler. [is it a TODO?]
8918  */
8919 static void
8920 dotrap(void)
8921 {
8922         uint8_t *g;
8923         int sig;
8924         uint8_t last_status;
8925
8926         if (!pending_sig)
8927                 return;
8928
8929         last_status = exitstatus;
8930         pending_sig = 0;
8931         barrier();
8932
8933         TRACE(("dotrap entered\n"));
8934         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8935                 char *p;
8936
8937                 if (!*g)
8938                         continue;
8939
8940                 if (evalskip) {
8941                         pending_sig = sig;
8942                         break;
8943                 }
8944
8945                 p = trap[sig];
8946                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8947                  * don't upset it by resetting gotsig[SIGINT-1] */
8948                 if (sig == SIGINT && !p)
8949                         continue;
8950
8951                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8952                 *g = 0;
8953                 if (!p)
8954                         continue;
8955                 evalstring(p, 0);
8956         }
8957         exitstatus = last_status;
8958         TRACE(("dotrap returns\n"));
8959 }
8960
8961 /* forward declarations - evaluation is fairly recursive business... */
8962 static int evalloop(union node *, int);
8963 static int evalfor(union node *, int);
8964 static int evalcase(union node *, int);
8965 static int evalsubshell(union node *, int);
8966 static void expredir(union node *);
8967 static int evalpipe(union node *, int);
8968 static int evalcommand(union node *, int);
8969 static int evalbltin(const struct builtincmd *, int, char **, int);
8970 static void prehash(union node *);
8971
8972 /*
8973  * Evaluate a parse tree.  The value is left in the global variable
8974  * exitstatus.
8975  */
8976 static int
8977 evaltree(union node *n, int flags)
8978 {
8979         int checkexit = 0;
8980         int (*evalfn)(union node *, int);
8981         int status = 0;
8982
8983         if (n == NULL) {
8984                 TRACE(("evaltree(NULL) called\n"));
8985                 goto out;
8986         }
8987         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8988
8989         dotrap();
8990
8991         switch (n->type) {
8992         default:
8993 #if DEBUG
8994                 out1fmt("Node type = %d\n", n->type);
8995                 fflush_all();
8996                 break;
8997 #endif
8998         case NNOT:
8999                 status = !evaltree(n->nnot.com, EV_TESTED);
9000                 goto setstatus;
9001         case NREDIR:
9002                 errlinno = lineno = n->nredir.linno;
9003                 if (funcline)
9004                         lineno -= funcline - 1;
9005                 expredir(n->nredir.redirect);
9006                 pushredir(n->nredir.redirect);
9007                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9008                 if (!status) {
9009                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9010                 }
9011                 if (n->nredir.redirect)
9012                         popredir(/*drop:*/ 0);
9013                 goto setstatus;
9014         case NCMD:
9015                 evalfn = evalcommand;
9016  checkexit:
9017                 if (eflag && !(flags & EV_TESTED))
9018                         checkexit = ~0;
9019                 goto calleval;
9020         case NFOR:
9021                 evalfn = evalfor;
9022                 goto calleval;
9023         case NWHILE:
9024         case NUNTIL:
9025                 evalfn = evalloop;
9026                 goto calleval;
9027         case NSUBSHELL:
9028         case NBACKGND:
9029                 evalfn = evalsubshell;
9030                 goto checkexit;
9031         case NPIPE:
9032                 evalfn = evalpipe;
9033                 goto checkexit;
9034         case NCASE:
9035                 evalfn = evalcase;
9036                 goto calleval;
9037         case NAND:
9038         case NOR:
9039         case NSEMI: {
9040
9041 #if NAND + 1 != NOR
9042 #error NAND + 1 != NOR
9043 #endif
9044 #if NOR + 1 != NSEMI
9045 #error NOR + 1 != NSEMI
9046 #endif
9047                 unsigned is_or = n->type - NAND;
9048                 status = evaltree(
9049                         n->nbinary.ch1,
9050                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9051                 );
9052                 if ((!status) == is_or || evalskip)
9053                         break;
9054                 n = n->nbinary.ch2;
9055  evaln:
9056                 evalfn = evaltree;
9057  calleval:
9058                 status = evalfn(n, flags);
9059                 goto setstatus;
9060         }
9061         case NIF:
9062                 status = evaltree(n->nif.test, EV_TESTED);
9063                 if (evalskip)
9064                         break;
9065                 if (!status) {
9066                         n = n->nif.ifpart;
9067                         goto evaln;
9068                 }
9069                 if (n->nif.elsepart) {
9070                         n = n->nif.elsepart;
9071                         goto evaln;
9072                 }
9073                 status = 0;
9074                 goto setstatus;
9075         case NDEFUN:
9076                 defun(n);
9077                 /* Not necessary. To test it:
9078                  * "false; f() { qwerty; }; echo $?" should print 0.
9079                  */
9080                 /* status = 0; */
9081  setstatus:
9082                 exitstatus = status;
9083                 break;
9084         }
9085  out:
9086         /* Order of checks below is important:
9087          * signal handlers trigger before exit caused by "set -e".
9088          */
9089         dotrap();
9090
9091         if (checkexit & status)
9092                 raise_exception(EXEXIT);
9093         if (flags & EV_EXIT)
9094                 raise_exception(EXEXIT);
9095
9096         TRACE(("leaving evaltree (no interrupts)\n"));
9097         return exitstatus;
9098 }
9099
9100 static int
9101 skiploop(void)
9102 {
9103         int skip = evalskip;
9104
9105         switch (skip) {
9106         case 0:
9107                 break;
9108         case SKIPBREAK:
9109         case SKIPCONT:
9110                 if (--skipcount <= 0) {
9111                         evalskip = 0;
9112                         break;
9113                 }
9114                 skip = SKIPBREAK;
9115                 break;
9116         }
9117         return skip;
9118 }
9119
9120 static int
9121 evalloop(union node *n, int flags)
9122 {
9123         int skip;
9124         int status;
9125
9126         loopnest++;
9127         status = 0;
9128         flags &= EV_TESTED;
9129         do {
9130                 int i;
9131
9132                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9133                 skip = skiploop();
9134                 if (skip == SKIPFUNC)
9135                         status = i;
9136                 if (skip)
9137                         continue;
9138                 if (n->type != NWHILE)
9139                         i = !i;
9140                 if (i != 0)
9141                         break;
9142                 status = evaltree(n->nbinary.ch2, flags);
9143                 skip = skiploop();
9144         } while (!(skip & ~SKIPCONT));
9145         loopnest--;
9146
9147         return status;
9148 }
9149
9150 static int
9151 evalfor(union node *n, int flags)
9152 {
9153         struct arglist arglist;
9154         union node *argp;
9155         struct strlist *sp;
9156         struct stackmark smark;
9157         int status = 0;
9158
9159         errlinno = lineno = n->ncase.linno;
9160         if (funcline)
9161                 lineno -= funcline - 1;
9162
9163         setstackmark(&smark);
9164         arglist.list = NULL;
9165         arglist.lastp = &arglist.list;
9166         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9167                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9168         }
9169         *arglist.lastp = NULL;
9170
9171         loopnest++;
9172         flags &= EV_TESTED;
9173         for (sp = arglist.list; sp; sp = sp->next) {
9174                 setvar0(n->nfor.var, sp->text);
9175                 status = evaltree(n->nfor.body, flags);
9176                 if (skiploop() & ~SKIPCONT)
9177                         break;
9178         }
9179         loopnest--;
9180         popstackmark(&smark);
9181
9182         return status;
9183 }
9184
9185 static int
9186 evalcase(union node *n, int flags)
9187 {
9188         union node *cp;
9189         union node *patp;
9190         struct arglist arglist;
9191         struct stackmark smark;
9192         int status = 0;
9193
9194         errlinno = lineno = n->ncase.linno;
9195         if (funcline)
9196                 lineno -= funcline - 1;
9197
9198         setstackmark(&smark);
9199         arglist.list = NULL;
9200         arglist.lastp = &arglist.list;
9201         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9202         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9203                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9204                         if (casematch(patp, arglist.list->text)) {
9205                                 /* Ensure body is non-empty as otherwise
9206                                  * EV_EXIT may prevent us from setting the
9207                                  * exit status.
9208                                  */
9209                                 if (evalskip == 0 && cp->nclist.body) {
9210                                         status = evaltree(cp->nclist.body, flags);
9211                                 }
9212                                 goto out;
9213                         }
9214                 }
9215         }
9216  out:
9217         popstackmark(&smark);
9218
9219         return status;
9220 }
9221
9222 /*
9223  * Kick off a subshell to evaluate a tree.
9224  */
9225 static int
9226 evalsubshell(union node *n, int flags)
9227 {
9228         struct job *jp;
9229         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9230         int status;
9231
9232         errlinno = lineno = n->nredir.linno;
9233         if (funcline)
9234                 lineno -= funcline - 1;
9235
9236         expredir(n->nredir.redirect);
9237         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9238                 goto nofork;
9239         INT_OFF;
9240         if (backgnd == FORK_FG)
9241                 get_tty_state();
9242         jp = makejob(/*n,*/ 1);
9243         if (forkshell(jp, n, backgnd) == 0) {
9244                 /* child */
9245                 INT_ON;
9246                 flags |= EV_EXIT;
9247                 if (backgnd)
9248                         flags &= ~EV_TESTED;
9249  nofork:
9250                 redirect(n->nredir.redirect, 0);
9251                 evaltreenr(n->nredir.n, flags);
9252                 /* never returns */
9253         }
9254         /* parent */
9255         status = 0;
9256         if (backgnd == FORK_FG)
9257                 status = waitforjob(jp);
9258         INT_ON;
9259         return status;
9260 }
9261
9262 /*
9263  * Compute the names of the files in a redirection list.
9264  */
9265 static void fixredir(union node *, const char *, int);
9266 static void
9267 expredir(union node *n)
9268 {
9269         union node *redir;
9270
9271         for (redir = n; redir; redir = redir->nfile.next) {
9272                 struct arglist fn;
9273
9274                 fn.list = NULL;
9275                 fn.lastp = &fn.list;
9276                 switch (redir->type) {
9277                 case NFROMTO:
9278                 case NFROM:
9279                 case NTO:
9280 #if BASH_REDIR_OUTPUT
9281                 case NTO2:
9282 #endif
9283                 case NCLOBBER:
9284                 case NAPPEND:
9285                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9286                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9287 #if BASH_REDIR_OUTPUT
9288  store_expfname:
9289 #endif
9290 #if 0
9291 // By the design of stack allocator, the loop of this kind:
9292 //      while true; do while true; do break; done </dev/null; done
9293 // will look like a memory leak: ash plans to free expfname's
9294 // of "/dev/null" as soon as it finishes running the loop
9295 // (in this case, never).
9296 // This "fix" is wrong:
9297                         if (redir->nfile.expfname)
9298                                 stunalloc(redir->nfile.expfname);
9299 // It results in corrupted state of stacked allocations.
9300 #endif
9301                         redir->nfile.expfname = fn.list->text;
9302                         break;
9303                 case NFROMFD:
9304                 case NTOFD: /* >& */
9305                         if (redir->ndup.vname) {
9306                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9307                                 if (fn.list == NULL)
9308                                         ash_msg_and_raise_error("redir error");
9309 #if BASH_REDIR_OUTPUT
9310 //FIXME: we used expandarg with different args!
9311                                 if (!isdigit_str9(fn.list->text)) {
9312                                         /* >&file, not >&fd */
9313                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9314                                                 ash_msg_and_raise_error("redir error");
9315                                         redir->type = NTO2;
9316                                         goto store_expfname;
9317                                 }
9318 #endif
9319                                 fixredir(redir, fn.list->text, 1);
9320                         }
9321                         break;
9322                 }
9323         }
9324 }
9325
9326 /*
9327  * Evaluate a pipeline.  All the processes in the pipeline are children
9328  * of the process creating the pipeline.  (This differs from some versions
9329  * of the shell, which make the last process in a pipeline the parent
9330  * of all the rest.)
9331  */
9332 static int
9333 evalpipe(union node *n, int flags)
9334 {
9335         struct job *jp;
9336         struct nodelist *lp;
9337         int pipelen;
9338         int prevfd;
9339         int pip[2];
9340         int status = 0;
9341
9342         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9343         pipelen = 0;
9344         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9345                 pipelen++;
9346         flags |= EV_EXIT;
9347         INT_OFF;
9348         if (n->npipe.pipe_backgnd == 0)
9349                 get_tty_state();
9350         jp = makejob(/*n,*/ pipelen);
9351         prevfd = -1;
9352         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9353                 prehash(lp->n);
9354                 pip[1] = -1;
9355                 if (lp->next) {
9356                         if (pipe(pip) < 0) {
9357                                 close(prevfd);
9358                                 ash_msg_and_raise_perror("can't create pipe");
9359                         }
9360                 }
9361                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9362                         /* child */
9363                         INT_ON;
9364                         if (pip[1] >= 0) {
9365                                 close(pip[0]);
9366                         }
9367                         if (prevfd > 0) {
9368                                 dup2(prevfd, 0);
9369                                 close(prevfd);
9370                         }
9371                         if (pip[1] > 1) {
9372                                 dup2(pip[1], 1);
9373                                 close(pip[1]);
9374                         }
9375                         evaltreenr(lp->n, flags);
9376                         /* never returns */
9377                 }
9378                 /* parent */
9379                 if (prevfd >= 0)
9380                         close(prevfd);
9381                 prevfd = pip[0];
9382                 /* Don't want to trigger debugging */
9383                 if (pip[1] != -1)
9384                         close(pip[1]);
9385         }
9386         if (n->npipe.pipe_backgnd == 0) {
9387                 status = waitforjob(jp);
9388                 TRACE(("evalpipe:  job done exit status %d\n", status));
9389         }
9390         INT_ON;
9391
9392         return status;
9393 }
9394
9395 /*
9396  * Controls whether the shell is interactive or not.
9397  */
9398 static void
9399 setinteractive(int on)
9400 {
9401         static smallint is_interactive;
9402
9403         if (++on == is_interactive)
9404                 return;
9405         is_interactive = on;
9406         setsignal(SIGINT);
9407         setsignal(SIGQUIT);
9408         setsignal(SIGTERM);
9409 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9410         if (is_interactive > 1) {
9411                 /* Looks like they want an interactive shell */
9412                 static smallint did_banner;
9413
9414                 if (!did_banner) {
9415                         /* note: ash and hush share this string */
9416                         out1fmt("\n\n%s %s\n"
9417                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9418                                 "\n",
9419                                 bb_banner,
9420                                 "built-in shell (ash)"
9421                         );
9422                         did_banner = 1;
9423                 }
9424         }
9425 #endif
9426 }
9427
9428 static void
9429 optschanged(void)
9430 {
9431 #if DEBUG
9432         opentrace();
9433 #endif
9434         setinteractive(iflag);
9435         setjobctl(mflag);
9436 #if ENABLE_FEATURE_EDITING_VI
9437         if (viflag)
9438                 line_input_state->flags |= VI_MODE;
9439         else
9440                 line_input_state->flags &= ~VI_MODE;
9441 #else
9442         viflag = 0; /* forcibly keep the option off */
9443 #endif
9444 }
9445
9446 struct localvar_list {
9447         struct localvar_list *next;
9448         struct localvar *lv;
9449 };
9450
9451 static struct localvar_list *localvar_stack;
9452
9453 /*
9454  * Called after a function returns.
9455  * Interrupts must be off.
9456  */
9457 static void
9458 poplocalvars(int keep)
9459 {
9460         struct localvar_list *ll;
9461         struct localvar *lvp, *next;
9462         struct var *vp;
9463
9464         INT_OFF;
9465         ll = localvar_stack;
9466         localvar_stack = ll->next;
9467
9468         next = ll->lv;
9469         free(ll);
9470
9471         while ((lvp = next) != NULL) {
9472                 next = lvp->next;
9473                 vp = lvp->vp;
9474                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9475                 if (keep) {
9476                         int bits = VSTRFIXED;
9477
9478                         if (lvp->flags != VUNSET) {
9479                                 if (vp->var_text == lvp->text)
9480                                         bits |= VTEXTFIXED;
9481                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9482                                         free((char*)lvp->text);
9483                         }
9484
9485                         vp->flags &= ~bits;
9486                         vp->flags |= (lvp->flags & bits);
9487
9488                         if ((vp->flags &
9489                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9490                                 unsetvar(vp->var_text);
9491                 } else if (vp == NULL) {        /* $- saved */
9492                         memcpy(optlist, lvp->text, sizeof(optlist));
9493                         free((char*)lvp->text);
9494                         optschanged();
9495                 } else if (lvp->flags == VUNSET) {
9496                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9497                         unsetvar(vp->var_text);
9498                 } else {
9499                         if (vp->var_func)
9500                                 vp->var_func(var_end(lvp->text));
9501                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9502                                 free((char*)vp->var_text);
9503                         vp->flags = lvp->flags;
9504                         vp->var_text = lvp->text;
9505                 }
9506                 free(lvp);
9507         }
9508         INT_ON;
9509 }
9510
9511 /*
9512  * Create a new localvar environment.
9513  */
9514 static struct localvar_list *
9515 pushlocalvars(void)
9516 {
9517         struct localvar_list *ll;
9518
9519         INT_OFF;
9520         ll = ckzalloc(sizeof(*ll));
9521         /*ll->lv = NULL; - zalloc did it */
9522         ll->next = localvar_stack;
9523         localvar_stack = ll;
9524         INT_ON;
9525
9526         return ll->next;
9527 }
9528
9529 static void
9530 unwindlocalvars(struct localvar_list *stop)
9531 {
9532         while (localvar_stack != stop)
9533                 poplocalvars(0);
9534 }
9535
9536 static int
9537 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9538 {
9539         volatile struct shparam saveparam;
9540         struct jmploc *volatile savehandler;
9541         struct jmploc jmploc;
9542         int e;
9543         int savefuncline;
9544
9545         saveparam = shellparam;
9546         savefuncline = funcline;
9547         savehandler = exception_handler;
9548         e = setjmp(jmploc.loc);
9549         if (e) {
9550                 goto funcdone;
9551         }
9552         INT_OFF;
9553         exception_handler = &jmploc;
9554         shellparam.malloced = 0;
9555         func->count++;
9556         funcline = func->n.ndefun.linno;
9557         INT_ON;
9558         shellparam.nparam = argc - 1;
9559         shellparam.p = argv + 1;
9560 #if ENABLE_ASH_GETOPTS
9561         shellparam.optind = 1;
9562         shellparam.optoff = -1;
9563 #endif
9564         pushlocalvars();
9565         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9566         poplocalvars(0);
9567  funcdone:
9568         INT_OFF;
9569         funcline = savefuncline;
9570         freefunc(func);
9571         freeparam(&shellparam);
9572         shellparam = saveparam;
9573         exception_handler = savehandler;
9574         INT_ON;
9575         evalskip &= ~SKIPFUNC;
9576         return e;
9577 }
9578
9579 /*
9580  * Make a variable a local variable.  When a variable is made local, it's
9581  * value and flags are saved in a localvar structure.  The saved values
9582  * will be restored when the shell function returns.  We handle the name
9583  * "-" as a special case: it makes changes to "set +-options" local
9584  * (options will be restored on return from the function).
9585  */
9586 static void
9587 mklocal(char *name)
9588 {
9589         struct localvar *lvp;
9590         struct var **vpp;
9591         struct var *vp;
9592         char *eq = strchr(name, '=');
9593
9594         INT_OFF;
9595         /* Cater for duplicate "local". Examples:
9596          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9597          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9598          */
9599         lvp = localvar_stack->lv;
9600         while (lvp) {
9601                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9602                         if (eq)
9603                                 setvareq(name, 0);
9604                         /* else:
9605                          * it's a duplicate "local VAR" declaration, do nothing
9606                          */
9607                         goto ret;
9608                 }
9609                 lvp = lvp->next;
9610         }
9611
9612         lvp = ckzalloc(sizeof(*lvp));
9613         if (LONE_DASH(name)) {
9614                 char *p;
9615                 p = ckmalloc(sizeof(optlist));
9616                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9617                 vp = NULL;
9618         } else {
9619                 vpp = hashvar(name);
9620                 vp = *findvar(vpp, name);
9621                 if (vp == NULL) {
9622                         /* variable did not exist yet */
9623                         if (eq)
9624                                 vp = setvareq(name, VSTRFIXED);
9625                         else
9626                                 vp = setvar(name, NULL, VSTRFIXED);
9627                         lvp->flags = VUNSET;
9628                 } else {
9629                         lvp->text = vp->var_text;
9630                         lvp->flags = vp->flags;
9631                         /* make sure neither "struct var" nor string gets freed
9632                          * during (un)setting:
9633                          */
9634                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9635                         if (eq)
9636                                 setvareq(name, 0);
9637                         else
9638                                 /* "local VAR" unsets VAR: */
9639                                 setvar0(name, NULL);
9640                 }
9641         }
9642         lvp->vp = vp;
9643         lvp->next = localvar_stack->lv;
9644         localvar_stack->lv = lvp;
9645  ret:
9646         INT_ON;
9647 }
9648
9649 /*
9650  * The "local" command.
9651  */
9652 static int FAST_FUNC
9653 localcmd(int argc UNUSED_PARAM, char **argv)
9654 {
9655         char *name;
9656
9657         if (!localvar_stack)
9658                 ash_msg_and_raise_error("not in a function");
9659
9660         argv = argptr;
9661         while ((name = *argv++) != NULL) {
9662                 mklocal(name);
9663         }
9664         return 0;
9665 }
9666
9667 static int FAST_FUNC
9668 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9669 {
9670         return 1;
9671 }
9672
9673 static int FAST_FUNC
9674 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9675 {
9676         return 0;
9677 }
9678
9679 static int FAST_FUNC
9680 execcmd(int argc UNUSED_PARAM, char **argv)
9681 {
9682         optionarg = NULL;
9683         while (nextopt("a:") != '\0')
9684                 /* nextopt() sets optionarg to "-a ARGV0" */;
9685
9686         argv = argptr;
9687         if (argv[0]) {
9688                 char *prog;
9689
9690                 iflag = 0;              /* exit on error */
9691                 mflag = 0;
9692                 optschanged();
9693                 /* We should set up signals for "exec CMD"
9694                  * the same way as for "CMD" without "exec".
9695                  * But optschanged->setinteractive->setsignal
9696                  * still thought we are a root shell. Therefore, for example,
9697                  * SIGQUIT is still set to IGN. Fix it:
9698                  */
9699                 shlvl++;
9700                 setsignal(SIGQUIT);
9701                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9702                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9703                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9704
9705                 prog = argv[0];
9706                 if (optionarg)
9707                         argv[0] = optionarg;
9708                 shellexec(prog, argv, pathval(), 0);
9709                 /* NOTREACHED */
9710         }
9711         return 0;
9712 }
9713
9714 /*
9715  * The return command.
9716  */
9717 static int FAST_FUNC
9718 returncmd(int argc UNUSED_PARAM, char **argv)
9719 {
9720         /*
9721          * If called outside a function, do what ksh does;
9722          * skip the rest of the file.
9723          */
9724         evalskip = SKIPFUNC;
9725         return argv[1] ? number(argv[1]) : exitstatus;
9726 }
9727
9728 /* Forward declarations for builtintab[] */
9729 static int breakcmd(int, char **) FAST_FUNC;
9730 static int dotcmd(int, char **) FAST_FUNC;
9731 static int evalcmd(int, char **, int) FAST_FUNC;
9732 static int exitcmd(int, char **) FAST_FUNC;
9733 static int exportcmd(int, char **) FAST_FUNC;
9734 #if ENABLE_ASH_GETOPTS
9735 static int getoptscmd(int, char **) FAST_FUNC;
9736 #endif
9737 #if ENABLE_ASH_HELP
9738 static int helpcmd(int, char **) FAST_FUNC;
9739 #endif
9740 #if MAX_HISTORY
9741 static int historycmd(int, char **) FAST_FUNC;
9742 #endif
9743 #if ENABLE_FEATURE_SH_MATH
9744 static int letcmd(int, char **) FAST_FUNC;
9745 #endif
9746 static int readcmd(int, char **) FAST_FUNC;
9747 static int setcmd(int, char **) FAST_FUNC;
9748 static int shiftcmd(int, char **) FAST_FUNC;
9749 static int timescmd(int, char **) FAST_FUNC;
9750 static int trapcmd(int, char **) FAST_FUNC;
9751 static int umaskcmd(int, char **) FAST_FUNC;
9752 static int unsetcmd(int, char **) FAST_FUNC;
9753 static int ulimitcmd(int, char **) FAST_FUNC;
9754
9755 #define BUILTIN_NOSPEC          "0"
9756 #define BUILTIN_SPECIAL         "1"
9757 #define BUILTIN_REGULAR         "2"
9758 #define BUILTIN_SPEC_REG        "3"
9759 #define BUILTIN_ASSIGN          "4"
9760 #define BUILTIN_SPEC_ASSG       "5"
9761 #define BUILTIN_REG_ASSG        "6"
9762 #define BUILTIN_SPEC_REG_ASSG   "7"
9763
9764 /* Stubs for calling non-FAST_FUNC's */
9765 #if ENABLE_ASH_ECHO
9766 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9767 #endif
9768 #if ENABLE_ASH_PRINTF
9769 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9770 #endif
9771 #if ENABLE_ASH_TEST || BASH_TEST2
9772 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9773 #endif
9774
9775 /* Keep these in proper order since it is searched via bsearch() */
9776 static const struct builtincmd builtintab[] = {
9777         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9778         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9779 #if ENABLE_ASH_TEST
9780         { BUILTIN_REGULAR       "["       , testcmd    },
9781 #endif
9782 #if BASH_TEST2
9783         { BUILTIN_REGULAR       "[["      , testcmd    },
9784 #endif
9785 #if ENABLE_ASH_ALIAS
9786         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9787 #endif
9788 #if JOBS
9789         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9790 #endif
9791         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9792         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9793         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9794 #if ENABLE_ASH_CMDCMD
9795         { BUILTIN_REGULAR       "command" , commandcmd },
9796 #endif
9797         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9798 #if ENABLE_ASH_ECHO
9799         { BUILTIN_REGULAR       "echo"    , echocmd    },
9800 #endif
9801         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9802         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9803         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9804         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9805         { BUILTIN_REGULAR       "false"   , falsecmd   },
9806 #if JOBS
9807         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9808 #endif
9809 #if ENABLE_ASH_GETOPTS
9810         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9811 #endif
9812         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9813 #if ENABLE_ASH_HELP
9814         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9815 #endif
9816 #if MAX_HISTORY
9817         { BUILTIN_NOSPEC        "history" , historycmd },
9818 #endif
9819 #if JOBS
9820         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9821         { BUILTIN_REGULAR       "kill"    , killcmd    },
9822 #endif
9823 #if ENABLE_FEATURE_SH_MATH
9824         { BUILTIN_NOSPEC        "let"     , letcmd     },
9825 #endif
9826         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9827 #if ENABLE_ASH_PRINTF
9828         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9829 #endif
9830         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9831         { BUILTIN_REGULAR       "read"    , readcmd    },
9832         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9833         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9834         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9835         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9836 #if BASH_SOURCE
9837         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9838 #endif
9839 #if ENABLE_ASH_TEST
9840         { BUILTIN_REGULAR       "test"    , testcmd    },
9841 #endif
9842         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9843         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9844         { BUILTIN_REGULAR       "true"    , truecmd    },
9845         { BUILTIN_NOSPEC        "type"    , typecmd    },
9846         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9847         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9848 #if ENABLE_ASH_ALIAS
9849         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9850 #endif
9851         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9852         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9853 };
9854
9855 /* Should match the above table! */
9856 #define COMMANDCMD (builtintab + \
9857         /* . : */       2 + \
9858         /* [ */         1 * ENABLE_ASH_TEST + \
9859         /* [[ */        1 * BASH_TEST2 + \
9860         /* alias */     1 * ENABLE_ASH_ALIAS + \
9861         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9862         /* break cd cddir  */   3)
9863 #define EVALCMD (COMMANDCMD + \
9864         /* command */   1 * ENABLE_ASH_CMDCMD + \
9865         /* continue */  1 + \
9866         /* echo */      1 * ENABLE_ASH_ECHO + \
9867         0)
9868 #define EXECCMD (EVALCMD + \
9869         /* eval */      1)
9870
9871 /*
9872  * Search the table of builtin commands.
9873  */
9874 static int
9875 pstrcmp1(const void *a, const void *b)
9876 {
9877         return strcmp((char*)a, *(char**)b + 1);
9878 }
9879 static struct builtincmd *
9880 find_builtin(const char *name)
9881 {
9882         struct builtincmd *bp;
9883
9884         bp = bsearch(
9885                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9886                 pstrcmp1
9887         );
9888         return bp;
9889 }
9890
9891 /*
9892  * Execute a simple command.
9893  */
9894 static int
9895 isassignment(const char *p)
9896 {
9897         const char *q = endofname(p);
9898         if (p == q)
9899                 return 0;
9900         return *q == '=';
9901 }
9902 static int FAST_FUNC
9903 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9904 {
9905         /* Preserve exitstatus of a previous possible redirection
9906          * as POSIX mandates */
9907         return back_exitstatus;
9908 }
9909 static int
9910 evalcommand(union node *cmd, int flags)
9911 {
9912         static const struct builtincmd null_bltin = {
9913                 "\0\0", bltincmd /* why three NULs? */
9914         };
9915         struct localvar_list *localvar_stop;
9916         struct redirtab *redir_stop;
9917         struct stackmark smark;
9918         union node *argp;
9919         struct arglist arglist;
9920         struct arglist varlist;
9921         char **argv;
9922         int argc;
9923         const struct strlist *sp;
9924         struct cmdentry cmdentry;
9925         struct job *jp;
9926         char *lastarg;
9927         const char *path;
9928         int spclbltin;
9929         int status;
9930         char **nargv;
9931         smallint cmd_is_exec;
9932
9933         errlinno = lineno = cmd->ncmd.linno;
9934         if (funcline)
9935                 lineno -= funcline - 1;
9936
9937         /* First expand the arguments. */
9938         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9939         setstackmark(&smark);
9940         localvar_stop = pushlocalvars();
9941         back_exitstatus = 0;
9942
9943         cmdentry.cmdtype = CMDBUILTIN;
9944         cmdentry.u.cmd = &null_bltin;
9945         varlist.lastp = &varlist.list;
9946         *varlist.lastp = NULL;
9947         arglist.lastp = &arglist.list;
9948         *arglist.lastp = NULL;
9949
9950         argc = 0;
9951         if (cmd->ncmd.args) {
9952                 struct builtincmd *bcmd;
9953                 smallint pseudovarflag;
9954
9955                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9956                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9957
9958                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9959                         struct strlist **spp;
9960
9961                         spp = arglist.lastp;
9962                         if (pseudovarflag && isassignment(argp->narg.text))
9963                                 expandarg(argp, &arglist, EXP_VARTILDE);
9964                         else
9965                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9966
9967                         for (sp = *spp; sp; sp = sp->next)
9968                                 argc++;
9969                 }
9970         }
9971
9972         /* Reserve one extra spot at the front for shellexec. */
9973         nargv = stalloc(sizeof(char *) * (argc + 2));
9974         argv = ++nargv;
9975         for (sp = arglist.list; sp; sp = sp->next) {
9976                 TRACE(("evalcommand arg: %s\n", sp->text));
9977                 *nargv++ = sp->text;
9978         }
9979         *nargv = NULL;
9980
9981         lastarg = NULL;
9982         if (iflag && funcline == 0 && argc > 0)
9983                 lastarg = nargv[-1];
9984
9985         expredir(cmd->ncmd.redirect);
9986         redir_stop = pushredir(cmd->ncmd.redirect);
9987         preverrout_fd = 2;
9988         if (BASH_XTRACEFD && xflag) {
9989                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9990                  * we do not emulate this. We only use its value.
9991                  */
9992                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9993                 if (xtracefd && is_number(xtracefd))
9994                         preverrout_fd = atoi(xtracefd);
9995
9996         }
9997         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9998
9999         path = vpath.var_text;
10000         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10001                 struct strlist **spp;
10002                 char *p;
10003
10004                 spp = varlist.lastp;
10005                 expandarg(argp, &varlist, EXP_VARTILDE);
10006
10007                 mklocal((*spp)->text);
10008
10009                 /*
10010                  * Modify the command lookup path, if a PATH= assignment
10011                  * is present
10012                  */
10013                 p = (*spp)->text;
10014                 if (varcmp(p, path) == 0)
10015                         path = p;
10016         }
10017
10018         /* Print the command if xflag is set. */
10019         if (xflag) {
10020                 const char *pfx = "";
10021
10022                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10023
10024                 sp = varlist.list;
10025                 while (sp) {
10026                         char *varval = sp->text;
10027                         char *eq = strchrnul(varval, '=');
10028                         if (*eq)
10029                                 eq++;
10030                         fdprintf(preverrout_fd, "%s%.*s%s",
10031                                 pfx,
10032                                 (int)(eq - varval), varval,
10033                                 maybe_single_quote(eq)
10034                         );
10035                         sp = sp->next;
10036                         pfx = " ";
10037                 }
10038
10039                 sp = arglist.list;
10040                 while (sp) {
10041                         fdprintf(preverrout_fd, "%s%s",
10042                                 pfx,
10043                                 /* always quote if matches reserved word: */
10044                                 findkwd(sp->text)
10045                                 ? single_quote(sp->text)
10046                                 : maybe_single_quote(sp->text)
10047                         );
10048                         sp = sp->next;
10049                         pfx = " ";
10050                 }
10051                 safe_write(preverrout_fd, "\n", 1);
10052         }
10053
10054         cmd_is_exec = 0;
10055         spclbltin = -1;
10056
10057         /* Now locate the command. */
10058         if (argc) {
10059                 int cmd_flag = DO_ERR;
10060 #if ENABLE_ASH_CMDCMD
10061                 const char *oldpath = path + 5;
10062 #endif
10063                 path += 5;
10064                 for (;;) {
10065                         find_command(argv[0], &cmdentry, cmd_flag, path);
10066                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10067                                 flush_stdout_stderr();
10068                                 status = 127;
10069                                 goto bail;
10070                         }
10071
10072                         /* implement bltin and command here */
10073                         if (cmdentry.cmdtype != CMDBUILTIN)
10074                                 break;
10075                         if (spclbltin < 0)
10076                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10077                         if (cmdentry.u.cmd == EXECCMD)
10078                                 cmd_is_exec = 1;
10079 #if ENABLE_ASH_CMDCMD
10080                         if (cmdentry.u.cmd == COMMANDCMD) {
10081                                 path = oldpath;
10082                                 nargv = parse_command_args(argv, &path);
10083                                 if (!nargv)
10084                                         break;
10085                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10086                                  * nargv => "PROG". path is updated if -p.
10087                                  */
10088                                 argc -= nargv - argv;
10089                                 argv = nargv;
10090                                 cmd_flag |= DO_NOFUNC;
10091                         } else
10092 #endif
10093                                 break;
10094                 }
10095         }
10096
10097         if (status) {
10098  bail:
10099                 exitstatus = status;
10100
10101                 /* We have a redirection error. */
10102                 if (spclbltin > 0)
10103                         raise_exception(EXERROR);
10104
10105                 goto out;
10106         }
10107
10108         /* Execute the command. */
10109         switch (cmdentry.cmdtype) {
10110         default: {
10111
10112 #if ENABLE_FEATURE_SH_STANDALONE \
10113  && ENABLE_FEATURE_SH_NOFORK \
10114  && NUM_APPLETS > 1
10115 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10116  *     around run_nofork_applet() call.
10117  * (2) Should this check also be done in forkshell()?
10118  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10119  */
10120                 /* find_command() encodes applet_no as (-2 - applet_no) */
10121                 int applet_no = (- cmdentry.u.index - 2);
10122                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10123                         char **sv_environ;
10124
10125                         INT_OFF;
10126                         sv_environ = environ;
10127                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10128                         /*
10129                          * Run <applet>_main().
10130                          * Signals (^C) can't interrupt here.
10131                          * Otherwise we can mangle stdio or malloc internal state.
10132                          * This makes applets which can run for a long time
10133                          * and/or wait for user input ineligible for NOFORK:
10134                          * for example, "yes" or "rm" (rm -i waits for input).
10135                          */
10136                         status = run_nofork_applet(applet_no, argv);
10137                         environ = sv_environ;
10138                         /*
10139                          * Try enabling NOFORK for "yes" applet.
10140                          * ^C _will_ stop it (write returns EINTR),
10141                          * but this causes stdout FILE to be stuck
10142                          * and needing clearerr(). What if other applets
10143                          * also can get EINTRs? Do we need to switch
10144                          * our signals to SA_RESTART?
10145                          */
10146                         /*clearerr(stdout);*/
10147                         INT_ON;
10148                         break;
10149                 }
10150 #endif
10151                 /* Can we avoid forking? For example, very last command
10152                  * in a script or a subshell does not need forking,
10153                  * we can just exec it.
10154                  */
10155                 if (!(flags & EV_EXIT) || may_have_traps) {
10156                         /* No, forking off a child is necessary */
10157                         INT_OFF;
10158                         get_tty_state();
10159                         jp = makejob(/*cmd,*/ 1);
10160                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10161                                 /* parent */
10162                                 status = waitforjob(jp);
10163                                 INT_ON;
10164                                 TRACE(("forked child exited with %d\n", status));
10165                                 break;
10166                         }
10167                         /* child */
10168                         FORCE_INT_ON;
10169                         /* fall through to exec'ing external program */
10170                 }
10171                 listsetvar(varlist.list, VEXPORT|VSTACK);
10172                 shellexec(argv[0], argv, path, cmdentry.u.index);
10173                 /* NOTREACHED */
10174         } /* default */
10175         case CMDBUILTIN:
10176                 if (spclbltin > 0 || argc == 0) {
10177                         poplocalvars(1);
10178                         if (cmd_is_exec && argc > 1)
10179                                 listsetvar(varlist.list, VEXPORT);
10180                 }
10181
10182                 /* Tight loop with builtins only:
10183                  * "while kill -0 $child; do true; done"
10184                  * will never exit even if $child died, unless we do this
10185                  * to reap the zombie and make kill detect that it's gone: */
10186                 dowait(DOWAIT_NONBLOCK, NULL);
10187
10188                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10189                         if (exception_type == EXERROR && spclbltin <= 0) {
10190                                 FORCE_INT_ON;
10191                                 goto readstatus;
10192                         }
10193  raise:
10194                         longjmp(exception_handler->loc, 1);
10195                 }
10196                 goto readstatus;
10197
10198         case CMDFUNCTION:
10199                 poplocalvars(1);
10200                 /* See above for the rationale */
10201                 dowait(DOWAIT_NONBLOCK, NULL);
10202                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10203                         goto raise;
10204  readstatus:
10205                 status = exitstatus;
10206                 break;
10207         } /* switch */
10208
10209  out:
10210         if (cmd->ncmd.redirect)
10211                 popredir(/*drop:*/ cmd_is_exec);
10212         unwindredir(redir_stop);
10213         unwindlocalvars(localvar_stop);
10214         if (lastarg) {
10215                 /* dsl: I think this is intended to be used to support
10216                  * '_' in 'vi' command mode during line editing...
10217                  * However I implemented that within libedit itself.
10218                  */
10219                 setvar0("_", lastarg);
10220         }
10221         popstackmark(&smark);
10222
10223         return status;
10224 }
10225
10226 static int
10227 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10228 {
10229         char *volatile savecmdname;
10230         struct jmploc *volatile savehandler;
10231         struct jmploc jmploc;
10232         int status;
10233         int i;
10234
10235         savecmdname = commandname;
10236         savehandler = exception_handler;
10237         i = setjmp(jmploc.loc);
10238         if (i)
10239                 goto cmddone;
10240         exception_handler = &jmploc;
10241         commandname = argv[0];
10242         argptr = argv + 1;
10243         optptr = NULL;                  /* initialize nextopt */
10244         if (cmd == EVALCMD)
10245                 status = evalcmd(argc, argv, flags);
10246         else
10247                 status = (*cmd->builtin)(argc, argv);
10248         flush_stdout_stderr();
10249         status |= ferror(stdout);
10250         exitstatus = status;
10251  cmddone:
10252         clearerr(stdout);
10253         commandname = savecmdname;
10254         exception_handler = savehandler;
10255
10256         return i;
10257 }
10258
10259 static int
10260 goodname(const char *p)
10261 {
10262         return endofname(p)[0] == '\0';
10263 }
10264
10265
10266 /*
10267  * Search for a command.  This is called before we fork so that the
10268  * location of the command will be available in the parent as well as
10269  * the child.  The check for "goodname" is an overly conservative
10270  * check that the name will not be subject to expansion.
10271  */
10272 static void
10273 prehash(union node *n)
10274 {
10275         struct cmdentry entry;
10276
10277         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10278                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10279 }
10280
10281
10282 /* ============ Builtin commands
10283  *
10284  * Builtin commands whose functions are closely tied to evaluation
10285  * are implemented here.
10286  */
10287
10288 /*
10289  * Handle break and continue commands.  Break, continue, and return are
10290  * all handled by setting the evalskip flag.  The evaluation routines
10291  * above all check this flag, and if it is set they start skipping
10292  * commands rather than executing them.  The variable skipcount is
10293  * the number of loops to break/continue, or the number of function
10294  * levels to return.  (The latter is always 1.)  It should probably
10295  * be an error to break out of more loops than exist, but it isn't
10296  * in the standard shell so we don't make it one here.
10297  */
10298 static int FAST_FUNC
10299 breakcmd(int argc UNUSED_PARAM, char **argv)
10300 {
10301         int n = argv[1] ? number(argv[1]) : 1;
10302
10303         if (n <= 0)
10304                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10305         if (n > loopnest)
10306                 n = loopnest;
10307         if (n > 0) {
10308                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10309                 skipcount = n;
10310         }
10311         return 0;
10312 }
10313
10314
10315 /*
10316  * This implements the input routines used by the parser.
10317  */
10318
10319 enum {
10320         INPUT_PUSH_FILE = 1,
10321         INPUT_NOFILE_OK = 2,
10322 };
10323
10324 static smallint checkkwd;
10325 /* values of checkkwd variable */
10326 #define CHKALIAS        0x1
10327 #define CHKKWD          0x2
10328 #define CHKNL           0x4
10329 #define CHKEOFMARK      0x8
10330
10331 /*
10332  * Push a string back onto the input at this current parsefile level.
10333  * We handle aliases this way.
10334  */
10335 #if !ENABLE_ASH_ALIAS
10336 #define pushstring(s, ap) pushstring(s)
10337 #endif
10338 static void
10339 pushstring(char *s, struct alias *ap)
10340 {
10341         struct strpush *sp;
10342         int len;
10343
10344         len = strlen(s);
10345         INT_OFF;
10346         if (g_parsefile->strpush) {
10347                 sp = ckzalloc(sizeof(*sp));
10348                 sp->prev = g_parsefile->strpush;
10349         } else {
10350                 sp = &(g_parsefile->basestrpush);
10351         }
10352         g_parsefile->strpush = sp;
10353         sp->prev_string = g_parsefile->next_to_pgetc;
10354         sp->prev_left_in_line = g_parsefile->left_in_line;
10355         sp->unget = g_parsefile->unget;
10356         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10357 #if ENABLE_ASH_ALIAS
10358         sp->ap = ap;
10359         if (ap) {
10360                 ap->flag |= ALIASINUSE;
10361                 sp->string = s;
10362         }
10363 #endif
10364         g_parsefile->next_to_pgetc = s;
10365         g_parsefile->left_in_line = len;
10366         g_parsefile->unget = 0;
10367         INT_ON;
10368 }
10369
10370 static void
10371 popstring(void)
10372 {
10373         struct strpush *sp = g_parsefile->strpush;
10374
10375         INT_OFF;
10376 #if ENABLE_ASH_ALIAS
10377         if (sp->ap) {
10378                 if (g_parsefile->next_to_pgetc[-1] == ' '
10379                  || g_parsefile->next_to_pgetc[-1] == '\t'
10380                 ) {
10381                         checkkwd |= CHKALIAS;
10382                 }
10383                 if (sp->string != sp->ap->val) {
10384                         free(sp->string);
10385                 }
10386                 sp->ap->flag &= ~ALIASINUSE;
10387                 if (sp->ap->flag & ALIASDEAD) {
10388                         unalias(sp->ap->name);
10389                 }
10390         }
10391 #endif
10392         g_parsefile->next_to_pgetc = sp->prev_string;
10393         g_parsefile->left_in_line = sp->prev_left_in_line;
10394         g_parsefile->unget = sp->unget;
10395         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10396         g_parsefile->strpush = sp->prev;
10397         if (sp != &(g_parsefile->basestrpush))
10398                 free(sp);
10399         INT_ON;
10400 }
10401
10402 static int
10403 preadfd(void)
10404 {
10405         int nr;
10406         char *buf = g_parsefile->buf;
10407
10408         g_parsefile->next_to_pgetc = buf;
10409 #if ENABLE_FEATURE_EDITING
10410  retry:
10411         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10412                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10413         else {
10414 # if ENABLE_ASH_IDLE_TIMEOUT
10415                 int timeout = -1;
10416                 if (iflag) {
10417                         const char *tmout_var = lookupvar("TMOUT");
10418                         if (tmout_var) {
10419                                 timeout = atoi(tmout_var) * 1000;
10420                                 if (timeout <= 0)
10421                                         timeout = -1;
10422                         }
10423                 }
10424                 line_input_state->timeout = timeout;
10425 # endif
10426 # if ENABLE_FEATURE_TAB_COMPLETION
10427                 line_input_state->path_lookup = pathval();
10428 # endif
10429                 reinit_unicode_for_ash();
10430                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10431                 if (nr == 0) {
10432                         /* ^C pressed, "convert" to SIGINT */
10433                         write(STDOUT_FILENO, "^C", 2);
10434                         if (trap[SIGINT]) {
10435                                 buf[0] = '\n';
10436                                 buf[1] = '\0';
10437                                 raise(SIGINT);
10438                                 return 1;
10439                         }
10440                         exitstatus = 128 + SIGINT;
10441                         bb_putchar('\n');
10442                         goto retry;
10443                 }
10444                 if (nr < 0) {
10445                         if (errno == 0) {
10446                                 /* Ctrl+D pressed */
10447                                 nr = 0;
10448                         }
10449 # if ENABLE_ASH_IDLE_TIMEOUT
10450                         else if (errno == EAGAIN && timeout > 0) {
10451                                 puts("\007timed out waiting for input: auto-logout");
10452                                 exitshell();
10453                         }
10454 # endif
10455                 }
10456         }
10457 #else
10458         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10459 #endif
10460
10461 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10462         if (nr < 0) {
10463                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10464                         int flags = fcntl(0, F_GETFL);
10465                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10466                                 flags &= ~O_NONBLOCK;
10467                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10468                                         out2str("sh: turning off NDELAY mode\n");
10469                                         goto retry;
10470                                 }
10471                         }
10472                 }
10473         }
10474 #endif
10475         return nr;
10476 }
10477
10478 /*
10479  * Refill the input buffer and return the next input character:
10480  *
10481  * 1) If a string was pushed back on the input, pop it;
10482  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10483  *    or we are reading from a string so we can't refill the buffer,
10484  *    return EOF.
10485  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10486  * 4) Process input up to the next newline, deleting nul characters.
10487  */
10488 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10489 #define pgetc_debug(...) ((void)0)
10490 static int pgetc(void);
10491 static int
10492 preadbuffer(void)
10493 {
10494         char *q;
10495         int more;
10496
10497         if (g_parsefile->strpush) {
10498 #if ENABLE_ASH_ALIAS
10499                 if (g_parsefile->left_in_line == -1
10500                  && g_parsefile->strpush->ap
10501                  && g_parsefile->next_to_pgetc[-1] != ' '
10502                  && g_parsefile->next_to_pgetc[-1] != '\t'
10503                 ) {
10504                         pgetc_debug("preadbuffer PEOA");
10505                         return PEOA;
10506                 }
10507 #endif
10508                 popstring();
10509                 return pgetc();
10510         }
10511         /* on both branches above g_parsefile->left_in_line < 0.
10512          * "pgetc" needs refilling.
10513          */
10514
10515         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10516          * pungetc() may increment it a few times.
10517          * Assuming it won't increment it to less than -90.
10518          */
10519         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10520                 pgetc_debug("preadbuffer PEOF1");
10521                 /* even in failure keep left_in_line and next_to_pgetc
10522                  * in lock step, for correct multi-layer pungetc.
10523                  * left_in_line was decremented before preadbuffer(),
10524                  * must inc next_to_pgetc: */
10525                 g_parsefile->next_to_pgetc++;
10526                 return PEOF;
10527         }
10528
10529         more = g_parsefile->left_in_buffer;
10530         if (more <= 0) {
10531                 flush_stdout_stderr();
10532  again:
10533                 more = preadfd();
10534                 if (more <= 0) {
10535                         /* don't try reading again */
10536                         g_parsefile->left_in_line = -99;
10537                         pgetc_debug("preadbuffer PEOF2");
10538                         g_parsefile->next_to_pgetc++;
10539                         return PEOF;
10540                 }
10541         }
10542
10543         /* Find out where's the end of line.
10544          * Set g_parsefile->left_in_line
10545          * and g_parsefile->left_in_buffer acordingly.
10546          * NUL chars are deleted.
10547          */
10548         q = g_parsefile->next_to_pgetc;
10549         for (;;) {
10550                 char c;
10551
10552                 more--;
10553
10554                 c = *q;
10555                 if (c == '\0') {
10556                         memmove(q, q + 1, more);
10557                 } else {
10558                         q++;
10559                         if (c == '\n') {
10560                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10561                                 break;
10562                         }
10563                 }
10564
10565                 if (more <= 0) {
10566                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10567                         if (g_parsefile->left_in_line < 0)
10568                                 goto again;
10569                         break;
10570                 }
10571         }
10572         g_parsefile->left_in_buffer = more;
10573
10574         if (vflag) {
10575                 char save = *q;
10576                 *q = '\0';
10577                 out2str(g_parsefile->next_to_pgetc);
10578                 *q = save;
10579         }
10580
10581         pgetc_debug("preadbuffer at %d:%p'%s'",
10582                         g_parsefile->left_in_line,
10583                         g_parsefile->next_to_pgetc,
10584                         g_parsefile->next_to_pgetc);
10585         return (unsigned char)*g_parsefile->next_to_pgetc++;
10586 }
10587
10588 static void
10589 nlprompt(void)
10590 {
10591         g_parsefile->linno++;
10592         setprompt_if(doprompt, 2);
10593 }
10594 static void
10595 nlnoprompt(void)
10596 {
10597         g_parsefile->linno++;
10598         needprompt = doprompt;
10599 }
10600
10601 static int
10602 pgetc(void)
10603 {
10604         int c;
10605
10606         pgetc_debug("pgetc at %d:%p'%s'",
10607                         g_parsefile->left_in_line,
10608                         g_parsefile->next_to_pgetc,
10609                         g_parsefile->next_to_pgetc);
10610         if (g_parsefile->unget)
10611                 return g_parsefile->lastc[--g_parsefile->unget];
10612
10613         if (--g_parsefile->left_in_line >= 0)
10614                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10615         else
10616                 c = preadbuffer();
10617
10618         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10619         g_parsefile->lastc[0] = c;
10620
10621         return c;
10622 }
10623
10624 #if ENABLE_ASH_ALIAS
10625 static int
10626 pgetc_without_PEOA(void)
10627 {
10628         int c;
10629         do {
10630                 pgetc_debug("pgetc at %d:%p'%s'",
10631                                 g_parsefile->left_in_line,
10632                                 g_parsefile->next_to_pgetc,
10633                                 g_parsefile->next_to_pgetc);
10634                 c = pgetc();
10635         } while (c == PEOA);
10636         return c;
10637 }
10638 #else
10639 # define pgetc_without_PEOA() pgetc()
10640 #endif
10641
10642 /*
10643  * Undo a call to pgetc.  Only two characters may be pushed back.
10644  * PEOF may be pushed back.
10645  */
10646 static void
10647 pungetc(void)
10648 {
10649         g_parsefile->unget++;
10650 }
10651
10652 /* This one eats backslash+newline */
10653 static int
10654 pgetc_eatbnl(void)
10655 {
10656         int c;
10657
10658         while ((c = pgetc()) == '\\') {
10659                 if (pgetc() != '\n') {
10660                         pungetc();
10661                         break;
10662                 }
10663
10664                 nlprompt();
10665         }
10666
10667         return c;
10668 }
10669
10670 struct synstack {
10671         smalluint syntax;
10672         uint8_t innerdq   :1;
10673         uint8_t varpushed :1;
10674         uint8_t dblquote  :1;
10675         int varnest;            /* levels of variables expansion */
10676         int dqvarnest;          /* levels of variables expansion within double quotes */
10677         int parenlevel;         /* levels of parens in arithmetic */
10678         struct synstack *prev;
10679         struct synstack *next;
10680 };
10681
10682 static void
10683 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10684 {
10685         memset(next, 0, sizeof(*next));
10686         next->syntax = syntax;
10687         next->next = *stack;
10688         (*stack)->prev = next;
10689         *stack = next;
10690 }
10691
10692 static ALWAYS_INLINE void
10693 synstack_pop(struct synstack **stack)
10694 {
10695         *stack = (*stack)->next;
10696 }
10697
10698 /*
10699  * To handle the "." command, a stack of input files is used.  Pushfile
10700  * adds a new entry to the stack and popfile restores the previous level.
10701  */
10702 static void
10703 pushfile(void)
10704 {
10705         struct parsefile *pf;
10706
10707         pf = ckzalloc(sizeof(*pf));
10708         pf->prev = g_parsefile;
10709         pf->pf_fd = -1;
10710         /*pf->strpush = NULL; - ckzalloc did it */
10711         /*pf->basestrpush.prev = NULL;*/
10712         /*pf->unget = 0;*/
10713         g_parsefile = pf;
10714 }
10715
10716 static void
10717 popfile(void)
10718 {
10719         struct parsefile *pf = g_parsefile;
10720
10721         if (pf == &basepf)
10722                 return;
10723
10724         INT_OFF;
10725         if (pf->pf_fd >= 0)
10726                 close(pf->pf_fd);
10727         free(pf->buf);
10728         while (pf->strpush)
10729                 popstring();
10730         g_parsefile = pf->prev;
10731         free(pf);
10732         INT_ON;
10733 }
10734
10735 /*
10736  * Return to top level.
10737  */
10738 static void
10739 popallfiles(void)
10740 {
10741         while (g_parsefile != &basepf)
10742                 popfile();
10743 }
10744
10745 /*
10746  * Close the file(s) that the shell is reading commands from.  Called
10747  * after a fork is done.
10748  */
10749 static void
10750 closescript(void)
10751 {
10752         popallfiles();
10753         if (g_parsefile->pf_fd > 0) {
10754                 close(g_parsefile->pf_fd);
10755                 g_parsefile->pf_fd = 0;
10756         }
10757 }
10758
10759 /*
10760  * Like setinputfile, but takes an open file descriptor.  Call this with
10761  * interrupts off.
10762  */
10763 static void
10764 setinputfd(int fd, int push)
10765 {
10766         if (push) {
10767                 pushfile();
10768                 g_parsefile->buf = NULL;
10769         }
10770         g_parsefile->pf_fd = fd;
10771         if (g_parsefile->buf == NULL)
10772                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10773         g_parsefile->left_in_buffer = 0;
10774         g_parsefile->left_in_line = 0;
10775         g_parsefile->linno = 1;
10776 }
10777
10778 /*
10779  * Set the input to take input from a file.  If push is set, push the
10780  * old input onto the stack first.
10781  */
10782 static int
10783 setinputfile(const char *fname, int flags)
10784 {
10785         int fd;
10786
10787         INT_OFF;
10788         fd = open(fname, O_RDONLY | O_CLOEXEC);
10789         if (fd < 0) {
10790                 if (flags & INPUT_NOFILE_OK)
10791                         goto out;
10792                 exitstatus = 127;
10793                 ash_msg_and_raise_perror("can't open '%s'", fname);
10794         }
10795         if (fd < 10)
10796                 fd = savefd(fd);
10797         else if (O_CLOEXEC == 0) /* old libc */
10798                 close_on_exec_on(fd);
10799
10800         setinputfd(fd, flags & INPUT_PUSH_FILE);
10801  out:
10802         INT_ON;
10803         return fd;
10804 }
10805
10806 /*
10807  * Like setinputfile, but takes input from a string.
10808  */
10809 static void
10810 setinputstring(char *string)
10811 {
10812         INT_OFF;
10813         pushfile();
10814         g_parsefile->next_to_pgetc = string;
10815         g_parsefile->left_in_line = strlen(string);
10816         g_parsefile->buf = NULL;
10817         g_parsefile->linno = 1;
10818         INT_ON;
10819 }
10820
10821
10822 /*
10823  * Routines to check for mail.
10824  */
10825
10826 #if ENABLE_ASH_MAIL
10827
10828 /* Hash of mtimes of mailboxes */
10829 static unsigned mailtime_hash;
10830 /* Set if MAIL or MAILPATH is changed. */
10831 static smallint mail_var_path_changed;
10832
10833 /*
10834  * Print appropriate message(s) if mail has arrived.
10835  * If mail_var_path_changed is set,
10836  * then the value of MAIL has mail_var_path_changed,
10837  * so we just update the values.
10838  */
10839 static void
10840 chkmail(void)
10841 {
10842         const char *mpath;
10843         char *p;
10844         char *q;
10845         unsigned new_hash;
10846         struct stackmark smark;
10847         struct stat statb;
10848
10849         setstackmark(&smark);
10850         mpath = mpathset() ? mpathval() : mailval();
10851         new_hash = 0;
10852         for (;;) {
10853                 p = path_advance(&mpath, nullstr);
10854                 if (p == NULL)
10855                         break;
10856                 if (*p == '\0')
10857                         continue;
10858                 for (q = p; *q; q++)
10859                         continue;
10860 #if DEBUG
10861                 if (q[-1] != '/')
10862                         abort();
10863 #endif
10864                 q[-1] = '\0';                   /* delete trailing '/' */
10865                 if (stat(p, &statb) < 0) {
10866                         continue;
10867                 }
10868                 /* Very simplistic "hash": just a sum of all mtimes */
10869                 new_hash += (unsigned)statb.st_mtime;
10870         }
10871         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10872                 if (mailtime_hash != 0)
10873                         out2str("you have mail\n");
10874                 mailtime_hash = new_hash;
10875         }
10876         mail_var_path_changed = 0;
10877         popstackmark(&smark);
10878 }
10879
10880 static void FAST_FUNC
10881 changemail(const char *val UNUSED_PARAM)
10882 {
10883         mail_var_path_changed = 1;
10884 }
10885
10886 #endif /* ASH_MAIL */
10887
10888
10889 /* ============ ??? */
10890
10891 /*
10892  * Set the shell parameters.
10893  */
10894 static void
10895 setparam(char **argv)
10896 {
10897         char **newparam;
10898         char **ap;
10899         int nparam;
10900
10901         for (nparam = 0; argv[nparam]; nparam++)
10902                 continue;
10903         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10904         while (*argv) {
10905                 *ap++ = ckstrdup(*argv++);
10906         }
10907         *ap = NULL;
10908         freeparam(&shellparam);
10909         shellparam.malloced = 1;
10910         shellparam.nparam = nparam;
10911         shellparam.p = newparam;
10912 #if ENABLE_ASH_GETOPTS
10913         shellparam.optind = 1;
10914         shellparam.optoff = -1;
10915 #endif
10916 }
10917
10918 /*
10919  * Process shell options.  The global variable argptr contains a pointer
10920  * to the argument list; we advance it past the options.
10921  *
10922  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10923  * For a non-interactive shell, an error condition encountered
10924  * by a special built-in ... shall cause the shell to write a diagnostic message
10925  * to standard error and exit as shown in the following table:
10926  * Error                                           Special Built-In
10927  * ...
10928  * Utility syntax error (option or operand error)  Shall exit
10929  * ...
10930  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10931  * we see that bash does not do that (set "finishes" with error code 1 instead,
10932  * and shell continues), and people rely on this behavior!
10933  * Testcase:
10934  * set -o barfoo 2>/dev/null
10935  * echo $?
10936  *
10937  * Oh well. Let's mimic that.
10938  */
10939 static int
10940 plus_minus_o(char *name, int val)
10941 {
10942         int i;
10943
10944         if (name) {
10945                 for (i = 0; i < NOPTS; i++) {
10946                         if (strcmp(name, optnames(i)) == 0) {
10947                                 optlist[i] = val;
10948                                 return 0;
10949                         }
10950                 }
10951                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10952                 return 1;
10953         }
10954         for (i = 0; i < NOPTS; i++) {
10955                 if (val) {
10956                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10957                 } else {
10958                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10959                 }
10960         }
10961         return 0;
10962 }
10963 static void
10964 setoption(int flag, int val)
10965 {
10966         int i;
10967
10968         for (i = 0; i < NOPTS; i++) {
10969                 if (optletters(i) == flag) {
10970                         optlist[i] = val;
10971                         return;
10972                 }
10973         }
10974         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10975         /* NOTREACHED */
10976 }
10977 static int
10978 options(int cmdline, int *login_sh)
10979 {
10980         char *p;
10981         int val;
10982         int c;
10983
10984         if (cmdline)
10985                 minusc = NULL;
10986         while ((p = *argptr) != NULL) {
10987                 c = *p++;
10988                 if (c != '-' && c != '+')
10989                         break;
10990                 argptr++;
10991                 val = 0; /* val = 0 if c == '+' */
10992                 if (c == '-') {
10993                         val = 1;
10994                         if (p[0] == '\0' || LONE_DASH(p)) {
10995                                 if (!cmdline) {
10996                                         /* "-" means turn off -x and -v */
10997                                         if (p[0] == '\0')
10998                                                 xflag = vflag = 0;
10999                                         /* "--" means reset params */
11000                                         else if (*argptr == NULL)
11001                                                 setparam(argptr);
11002                                 }
11003                                 break;    /* "-" or "--" terminates options */
11004                         }
11005                 }
11006                 /* first char was + or - */
11007                 while ((c = *p++) != '\0') {
11008                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11009                         if (c == 'c' && cmdline) {
11010                                 minusc = p;     /* command is after shell args */
11011                         } else if (c == 'o') {
11012                                 if (plus_minus_o(*argptr, val)) {
11013                                         /* it already printed err message */
11014                                         return 1; /* error */
11015                                 }
11016                                 if (*argptr)
11017                                         argptr++;
11018                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
11019                                 if (login_sh)
11020                                         *login_sh = 1;
11021                         /* bash does not accept +-login, we also won't */
11022                         } else if (cmdline && val && (c == '-')) { /* long options */
11023                                 if (strcmp(p, "login") == 0) {
11024                                         if (login_sh)
11025                                                 *login_sh = 1;
11026                                 }
11027                                 break;
11028                         } else {
11029                                 setoption(c, val);
11030                         }
11031                 }
11032         }
11033         return 0;
11034 }
11035
11036 /*
11037  * The shift builtin command.
11038  */
11039 static int FAST_FUNC
11040 shiftcmd(int argc UNUSED_PARAM, char **argv)
11041 {
11042         int n;
11043         char **ap1, **ap2;
11044
11045         n = 1;
11046         if (argv[1])
11047                 n = number(argv[1]);
11048         if (n > shellparam.nparam)
11049                 return 1;
11050         INT_OFF;
11051         shellparam.nparam -= n;
11052         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11053                 if (shellparam.malloced)
11054                         free(*ap1);
11055         }
11056         ap2 = shellparam.p;
11057         while ((*ap2++ = *ap1++) != NULL)
11058                 continue;
11059 #if ENABLE_ASH_GETOPTS
11060         shellparam.optind = 1;
11061         shellparam.optoff = -1;
11062 #endif
11063         INT_ON;
11064         return 0;
11065 }
11066
11067 /*
11068  * POSIX requires that 'set' (but not export or readonly) output the
11069  * variables in lexicographic order - by the locale's collating order (sigh).
11070  * Maybe we could keep them in an ordered balanced binary tree
11071  * instead of hashed lists.
11072  * For now just roll 'em through qsort for printing...
11073  */
11074 static int
11075 showvars(const char *sep_prefix, int on, int off)
11076 {
11077         const char *sep;
11078         char **ep, **epend;
11079
11080         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11081         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11082
11083         sep = *sep_prefix ? " " : sep_prefix;
11084
11085         for (; ep < epend; ep++) {
11086                 const char *p;
11087                 const char *q;
11088
11089                 p = endofname(*ep);
11090 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11091  * makes "export -p" to have output not suitable for "eval":
11092  * import os
11093  * os.environ["test-test"]="test"
11094  * if os.fork() == 0:
11095  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11096  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11097  */
11098                 q = nullstr;
11099                 if (*p == '=')
11100                         q = single_quote(++p);
11101                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11102         }
11103         return 0;
11104 }
11105
11106 /*
11107  * The set command builtin.
11108  */
11109 static int FAST_FUNC
11110 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11111 {
11112         int retval;
11113
11114         if (!argv[1])
11115                 return showvars(nullstr, 0, VUNSET);
11116
11117         INT_OFF;
11118         retval = options(/*cmdline:*/ 0, NULL);
11119         if (retval == 0) { /* if no parse error... */
11120                 optschanged();
11121                 if (*argptr != NULL) {
11122                         setparam(argptr);
11123                 }
11124         }
11125         INT_ON;
11126         return retval;
11127 }
11128
11129 #if ENABLE_ASH_RANDOM_SUPPORT
11130 static void FAST_FUNC
11131 change_random(const char *value)
11132 {
11133         uint32_t t;
11134
11135         if (value == NULL) {
11136                 /* "get", generate */
11137                 t = next_random(&random_gen);
11138                 /* set without recursion */
11139                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11140                 vrandom.flags &= ~VNOFUNC;
11141         } else {
11142                 /* set/reset */
11143                 t = strtoul(value, NULL, 10);
11144                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11145         }
11146 }
11147 #endif
11148
11149 #if ENABLE_ASH_GETOPTS
11150 static int
11151 getopts(char *optstr, char *optvar, char **optfirst)
11152 {
11153         char *p, *q;
11154         char c = '?';
11155         int done = 0;
11156         char sbuf[2];
11157         char **optnext;
11158         int ind = shellparam.optind;
11159         int off = shellparam.optoff;
11160
11161         sbuf[1] = '\0';
11162
11163         shellparam.optind = -1;
11164         optnext = optfirst + ind - 1;
11165
11166         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11167                 p = NULL;
11168         else
11169                 p = optnext[-1] + off;
11170         if (p == NULL || *p == '\0') {
11171                 /* Current word is done, advance */
11172                 p = *optnext;
11173                 if (p == NULL || *p != '-' || *++p == '\0') {
11174  atend:
11175                         unsetvar("OPTARG");
11176                         p = NULL;
11177                         done = 1;
11178                         goto out;
11179                 }
11180                 optnext++;
11181                 if (LONE_DASH(p))        /* check for "--" */
11182                         goto atend;
11183         }
11184
11185         c = *p++;
11186         for (q = optstr; *q != c;) {
11187                 if (*q == '\0') {
11188                         /* OPTERR is a bashism */
11189                         const char *cp = lookupvar("OPTERR");
11190                         if ((cp && LONE_CHAR(cp, '0'))
11191                          || (optstr[0] == ':')
11192                         ) {
11193                                 sbuf[0] = c;
11194                                 /*sbuf[1] = '\0'; - already is */
11195                                 setvar0("OPTARG", sbuf);
11196                         } else {
11197                                 fprintf(stderr, "Illegal option -%c\n", c);
11198                                 unsetvar("OPTARG");
11199                         }
11200                         c = '?';
11201                         goto out;
11202                 }
11203                 if (*++q == ':')
11204                         q++;
11205         }
11206
11207         if (*++q == ':') {
11208                 if (*p == '\0' && (p = *optnext) == NULL) {
11209                         /* OPTERR is a bashism */
11210                         const char *cp = lookupvar("OPTERR");
11211                         if ((cp && LONE_CHAR(cp, '0'))
11212                          || (optstr[0] == ':')
11213                         ) {
11214                                 sbuf[0] = c;
11215                                 /*sbuf[1] = '\0'; - already is */
11216                                 setvar0("OPTARG", sbuf);
11217                                 c = ':';
11218                         } else {
11219                                 fprintf(stderr, "No arg for -%c option\n", c);
11220                                 unsetvar("OPTARG");
11221                                 c = '?';
11222                         }
11223                         goto out;
11224                 }
11225
11226                 if (p == *optnext)
11227                         optnext++;
11228                 setvar0("OPTARG", p);
11229                 p = NULL;
11230         } else
11231                 setvar0("OPTARG", nullstr);
11232  out:
11233         ind = optnext - optfirst + 1;
11234         setvar("OPTIND", itoa(ind), VNOFUNC);
11235         sbuf[0] = c;
11236         /*sbuf[1] = '\0'; - already is */
11237         setvar0(optvar, sbuf);
11238
11239         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11240         shellparam.optind = ind;
11241
11242         return done;
11243 }
11244
11245 /*
11246  * The getopts builtin.  Shellparam.optnext points to the next argument
11247  * to be processed.  Shellparam.optptr points to the next character to
11248  * be processed in the current argument.  If shellparam.optnext is NULL,
11249  * then it's the first time getopts has been called.
11250  */
11251 static int FAST_FUNC
11252 getoptscmd(int argc, char **argv)
11253 {
11254         char **optbase;
11255
11256         if (argc < 3)
11257                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11258         if (argc == 3) {
11259                 optbase = shellparam.p;
11260                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11261                         shellparam.optind = 1;
11262                         shellparam.optoff = -1;
11263                 }
11264         } else {
11265                 optbase = &argv[3];
11266                 if ((unsigned)shellparam.optind > argc - 2) {
11267                         shellparam.optind = 1;
11268                         shellparam.optoff = -1;
11269                 }
11270         }
11271
11272         return getopts(argv[1], argv[2], optbase);
11273 }
11274 #endif /* ASH_GETOPTS */
11275
11276
11277 /* ============ Shell parser */
11278
11279 struct heredoc {
11280         struct heredoc *next;   /* next here document in list */
11281         union node *here;       /* redirection node */
11282         char *eofmark;          /* string indicating end of input */
11283         smallint striptabs;     /* if set, strip leading tabs */
11284 };
11285
11286 static smallint tokpushback;           /* last token pushed back */
11287 static smallint quoteflag;             /* set if (part of) last token was quoted */
11288 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11289 static struct heredoc *heredoclist;    /* list of here documents to read */
11290 static char *wordtext;                 /* text of last word returned by readtoken */
11291 static struct nodelist *backquotelist;
11292 static union node *redirnode;
11293 static struct heredoc *heredoc;
11294
11295 static const char *
11296 tokname(char *buf, int tok)
11297 {
11298         if (tok < TSEMI)
11299                 return tokname_array[tok];
11300         sprintf(buf, "\"%s\"", tokname_array[tok]);
11301         return buf;
11302 }
11303
11304 /* raise_error_unexpected_syntax:
11305  * Called when an unexpected token is read during the parse.  The argument
11306  * is the token that is expected, or -1 if more than one type of token can
11307  * occur at this point.
11308  */
11309 static void raise_error_unexpected_syntax(int) NORETURN;
11310 static void
11311 raise_error_unexpected_syntax(int token)
11312 {
11313         char msg[64];
11314         char buf[16];
11315         int l;
11316
11317         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11318         if (token >= 0)
11319                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11320         raise_error_syntax(msg);
11321         /* NOTREACHED */
11322 }
11323
11324 /* parsing is heavily cross-recursive, need these forward decls */
11325 static union node *andor(void);
11326 static union node *pipeline(void);
11327 static union node *parse_command(void);
11328 static void parseheredoc(void);
11329 static int peektoken(void);
11330 static int readtoken(void);
11331
11332 static union node *
11333 list(int nlflag)
11334 {
11335         union node *n1, *n2, *n3;
11336         int tok;
11337
11338         n1 = NULL;
11339         for (;;) {
11340                 switch (peektoken()) {
11341                 case TNL:
11342                         if (!(nlflag & 1))
11343                                 break;
11344                         parseheredoc();
11345                         return n1;
11346
11347                 case TEOF:
11348                         if (!n1 && (nlflag & 1))
11349                                 n1 = NODE_EOF;
11350                         parseheredoc();
11351                         return n1;
11352                 }
11353
11354                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11355                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11356                         return n1;
11357                 nlflag |= 2;
11358
11359                 n2 = andor();
11360                 tok = readtoken();
11361                 if (tok == TBACKGND) {
11362                         if (n2->type == NPIPE) {
11363                                 n2->npipe.pipe_backgnd = 1;
11364                         } else {
11365                                 if (n2->type != NREDIR) {
11366                                         n3 = stzalloc(sizeof(struct nredir));
11367                                         n3->nredir.n = n2;
11368                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11369                                         n2 = n3;
11370                                 }
11371                                 n2->type = NBACKGND;
11372                         }
11373                 }
11374                 if (n1 == NULL) {
11375                         n1 = n2;
11376                 } else {
11377                         n3 = stzalloc(sizeof(struct nbinary));
11378                         n3->type = NSEMI;
11379                         n3->nbinary.ch1 = n1;
11380                         n3->nbinary.ch2 = n2;
11381                         n1 = n3;
11382                 }
11383                 switch (tok) {
11384                 case TNL:
11385                 case TEOF:
11386                         tokpushback = 1;
11387                         /* fall through */
11388                 case TBACKGND:
11389                 case TSEMI:
11390                         break;
11391                 default:
11392                         if ((nlflag & 1))
11393                                 raise_error_unexpected_syntax(-1);
11394                         tokpushback = 1;
11395                         return n1;
11396                 }
11397         }
11398 }
11399
11400 static union node *
11401 andor(void)
11402 {
11403         union node *n1, *n2, *n3;
11404         int t;
11405
11406         n1 = pipeline();
11407         for (;;) {
11408                 t = readtoken();
11409                 if (t == TAND) {
11410                         t = NAND;
11411                 } else if (t == TOR) {
11412                         t = NOR;
11413                 } else {
11414                         tokpushback = 1;
11415                         return n1;
11416                 }
11417                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11418                 n2 = pipeline();
11419                 n3 = stzalloc(sizeof(struct nbinary));
11420                 n3->type = t;
11421                 n3->nbinary.ch1 = n1;
11422                 n3->nbinary.ch2 = n2;
11423                 n1 = n3;
11424         }
11425 }
11426
11427 static union node *
11428 pipeline(void)
11429 {
11430         union node *n1, *n2, *pipenode;
11431         struct nodelist *lp, *prev;
11432         int negate;
11433
11434         negate = 0;
11435         TRACE(("pipeline: entered\n"));
11436         if (readtoken() == TNOT) {
11437                 negate = !negate;
11438                 checkkwd = CHKKWD | CHKALIAS;
11439         } else
11440                 tokpushback = 1;
11441         n1 = parse_command();
11442         if (readtoken() == TPIPE) {
11443                 pipenode = stzalloc(sizeof(struct npipe));
11444                 pipenode->type = NPIPE;
11445                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11446                 lp = stzalloc(sizeof(struct nodelist));
11447                 pipenode->npipe.cmdlist = lp;
11448                 lp->n = n1;
11449                 do {
11450                         prev = lp;
11451                         lp = stzalloc(sizeof(struct nodelist));
11452                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11453                         lp->n = parse_command();
11454                         prev->next = lp;
11455                 } while (readtoken() == TPIPE);
11456                 lp->next = NULL;
11457                 n1 = pipenode;
11458         }
11459         tokpushback = 1;
11460         if (negate) {
11461                 n2 = stzalloc(sizeof(struct nnot));
11462                 n2->type = NNOT;
11463                 n2->nnot.com = n1;
11464                 return n2;
11465         }
11466         return n1;
11467 }
11468
11469 static union node *
11470 makename(void)
11471 {
11472         union node *n;
11473
11474         n = stzalloc(sizeof(struct narg));
11475         n->type = NARG;
11476         /*n->narg.next = NULL; - stzalloc did it */
11477         n->narg.text = wordtext;
11478         n->narg.backquote = backquotelist;
11479         return n;
11480 }
11481
11482 static void
11483 fixredir(union node *n, const char *text, int err)
11484 {
11485         int fd;
11486
11487         TRACE(("Fix redir %s %d\n", text, err));
11488         if (!err)
11489                 n->ndup.vname = NULL;
11490
11491         fd = bb_strtou(text, NULL, 10);
11492         if (!errno && fd >= 0)
11493                 n->ndup.dupfd = fd;
11494         else if (LONE_DASH(text))
11495                 n->ndup.dupfd = -1;
11496         else {
11497                 if (err)
11498                         raise_error_syntax("bad fd number");
11499                 n->ndup.vname = makename();
11500         }
11501 }
11502
11503 static void
11504 parsefname(void)
11505 {
11506         union node *n = redirnode;
11507
11508         if (n->type == NHERE)
11509                 checkkwd = CHKEOFMARK;
11510         if (readtoken() != TWORD)
11511                 raise_error_unexpected_syntax(-1);
11512         if (n->type == NHERE) {
11513                 struct heredoc *here = heredoc;
11514                 struct heredoc *p;
11515
11516                 if (quoteflag == 0)
11517                         n->type = NXHERE;
11518                 TRACE(("Here document %d\n", n->type));
11519                 rmescapes(wordtext, 0, NULL);
11520                 here->eofmark = wordtext;
11521                 here->next = NULL;
11522                 if (heredoclist == NULL)
11523                         heredoclist = here;
11524                 else {
11525                         for (p = heredoclist; p->next; p = p->next)
11526                                 continue;
11527                         p->next = here;
11528                 }
11529         } else if (n->type == NTOFD || n->type == NFROMFD) {
11530                 fixredir(n, wordtext, 0);
11531         } else {
11532                 n->nfile.fname = makename();
11533         }
11534 }
11535
11536 static union node *
11537 simplecmd(void)
11538 {
11539         union node *args, **app;
11540         union node *n = NULL;
11541         union node *vars, **vpp;
11542         union node **rpp, *redir;
11543         int savecheckkwd;
11544         int savelinno;
11545 #if BASH_TEST2
11546         smallint double_brackets_flag = 0;
11547 #endif
11548         IF_BASH_FUNCTION(smallint function_flag = 0;)
11549
11550         args = NULL;
11551         app = &args;
11552         vars = NULL;
11553         vpp = &vars;
11554         redir = NULL;
11555         rpp = &redir;
11556
11557         savecheckkwd = CHKALIAS;
11558         savelinno = g_parsefile->linno;
11559         for (;;) {
11560                 int t;
11561                 checkkwd = savecheckkwd;
11562                 t = readtoken();
11563                 switch (t) {
11564 #if BASH_FUNCTION
11565                 case TFUNCTION:
11566                         if (peektoken() != TWORD)
11567                                 raise_error_unexpected_syntax(TWORD);
11568                         function_flag = 1;
11569                         break;
11570 #endif
11571 #if BASH_TEST2
11572                 case TAND: /* "&&" */
11573                 case TOR: /* "||" */
11574                         if (!double_brackets_flag) {
11575                                 tokpushback = 1;
11576                                 goto out;
11577                         }
11578                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11579 #endif
11580                 case TWORD:
11581                         n = stzalloc(sizeof(struct narg));
11582                         n->type = NARG;
11583                         /*n->narg.next = NULL; - stzalloc did it */
11584                         n->narg.text = wordtext;
11585 #if BASH_TEST2
11586                         if (strcmp("[[", wordtext) == 0)
11587                                 double_brackets_flag = 1;
11588                         else if (strcmp("]]", wordtext) == 0)
11589                                 double_brackets_flag = 0;
11590 #endif
11591                         n->narg.backquote = backquotelist;
11592                         if (savecheckkwd && isassignment(wordtext)) {
11593                                 *vpp = n;
11594                                 vpp = &n->narg.next;
11595                         } else {
11596                                 *app = n;
11597                                 app = &n->narg.next;
11598                                 savecheckkwd = 0;
11599                         }
11600 #if BASH_FUNCTION
11601                         if (function_flag) {
11602                                 checkkwd = CHKNL | CHKKWD;
11603                                 switch (peektoken()) {
11604                                 case TBEGIN:
11605                                 case TIF:
11606                                 case TCASE:
11607                                 case TUNTIL:
11608                                 case TWHILE:
11609                                 case TFOR:
11610                                         goto do_func;
11611                                 case TLP:
11612                                         function_flag = 0;
11613                                         break;
11614                                 case TWORD:
11615                                         if (strcmp("[[", wordtext) == 0)
11616                                                 goto do_func;
11617                                         /* fall through */
11618                                 default:
11619                                         raise_error_unexpected_syntax(-1);
11620                                 }
11621                         }
11622 #endif
11623                         break;
11624                 case TREDIR:
11625                         *rpp = n = redirnode;
11626                         rpp = &n->nfile.next;
11627                         parsefname();   /* read name of redirection file */
11628                         break;
11629                 case TLP:
11630  IF_BASH_FUNCTION(do_func:)
11631                         if (args && app == &args->narg.next
11632                          && !vars && !redir
11633                         ) {
11634                                 struct builtincmd *bcmd;
11635                                 const char *name;
11636
11637                                 /* We have a function */
11638                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11639                                         raise_error_unexpected_syntax(TRP);
11640                                 name = n->narg.text;
11641                                 if (!goodname(name)
11642                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11643                                 ) {
11644                                         raise_error_syntax("bad function name");
11645                                 }
11646                                 n->type = NDEFUN;
11647                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11648                                 n->ndefun.text = n->narg.text;
11649                                 n->ndefun.linno = g_parsefile->linno;
11650                                 n->ndefun.body = parse_command();
11651                                 return n;
11652                         }
11653                         IF_BASH_FUNCTION(function_flag = 0;)
11654                         /* fall through */
11655                 default:
11656                         tokpushback = 1;
11657                         goto out;
11658                 }
11659         }
11660  out:
11661         *app = NULL;
11662         *vpp = NULL;
11663         *rpp = NULL;
11664         n = stzalloc(sizeof(struct ncmd));
11665         n->type = NCMD;
11666         n->ncmd.linno = savelinno;
11667         n->ncmd.args = args;
11668         n->ncmd.assign = vars;
11669         n->ncmd.redirect = redir;
11670         return n;
11671 }
11672
11673 static union node *
11674 parse_command(void)
11675 {
11676         union node *n1, *n2;
11677         union node *ap, **app;
11678         union node *cp, **cpp;
11679         union node *redir, **rpp;
11680         union node **rpp2;
11681         int t;
11682         int savelinno;
11683
11684         redir = NULL;
11685         rpp2 = &redir;
11686
11687         savelinno = g_parsefile->linno;
11688
11689         switch (readtoken()) {
11690         default:
11691                 raise_error_unexpected_syntax(-1);
11692                 /* NOTREACHED */
11693         case TIF:
11694                 n1 = stzalloc(sizeof(struct nif));
11695                 n1->type = NIF;
11696                 n1->nif.test = list(0);
11697                 if (readtoken() != TTHEN)
11698                         raise_error_unexpected_syntax(TTHEN);
11699                 n1->nif.ifpart = list(0);
11700                 n2 = n1;
11701                 while (readtoken() == TELIF) {
11702                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11703                         n2 = n2->nif.elsepart;
11704                         n2->type = NIF;
11705                         n2->nif.test = list(0);
11706                         if (readtoken() != TTHEN)
11707                                 raise_error_unexpected_syntax(TTHEN);
11708                         n2->nif.ifpart = list(0);
11709                 }
11710                 if (lasttoken == TELSE)
11711                         n2->nif.elsepart = list(0);
11712                 else {
11713                         n2->nif.elsepart = NULL;
11714                         tokpushback = 1;
11715                 }
11716                 t = TFI;
11717                 break;
11718         case TWHILE:
11719         case TUNTIL: {
11720                 int got;
11721                 n1 = stzalloc(sizeof(struct nbinary));
11722                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11723                 n1->nbinary.ch1 = list(0);
11724                 got = readtoken();
11725                 if (got != TDO) {
11726                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11727                                         got == TWORD ? wordtext : ""));
11728                         raise_error_unexpected_syntax(TDO);
11729                 }
11730                 n1->nbinary.ch2 = list(0);
11731                 t = TDONE;
11732                 break;
11733         }
11734         case TFOR:
11735                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11736                         raise_error_syntax("bad for loop variable");
11737                 n1 = stzalloc(sizeof(struct nfor));
11738                 n1->type = NFOR;
11739                 n1->nfor.linno = savelinno;
11740                 n1->nfor.var = wordtext;
11741                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11742                 if (readtoken() == TIN) {
11743                         app = &ap;
11744                         while (readtoken() == TWORD) {
11745                                 n2 = stzalloc(sizeof(struct narg));
11746                                 n2->type = NARG;
11747                                 /*n2->narg.next = NULL; - stzalloc did it */
11748                                 n2->narg.text = wordtext;
11749                                 n2->narg.backquote = backquotelist;
11750                                 *app = n2;
11751                                 app = &n2->narg.next;
11752                         }
11753                         *app = NULL;
11754                         n1->nfor.args = ap;
11755                         if (lasttoken != TNL && lasttoken != TSEMI)
11756                                 raise_error_unexpected_syntax(-1);
11757                 } else {
11758                         n2 = stzalloc(sizeof(struct narg));
11759                         n2->type = NARG;
11760                         /*n2->narg.next = NULL; - stzalloc did it */
11761                         n2->narg.text = (char *)dolatstr;
11762                         /*n2->narg.backquote = NULL;*/
11763                         n1->nfor.args = n2;
11764                         /*
11765                          * Newline or semicolon here is optional (but note
11766                          * that the original Bourne shell only allowed NL).
11767                          */
11768                         if (lasttoken != TSEMI)
11769                                 tokpushback = 1;
11770                 }
11771                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11772                 if (readtoken() != TDO)
11773                         raise_error_unexpected_syntax(TDO);
11774                 n1->nfor.body = list(0);
11775                 t = TDONE;
11776                 break;
11777         case TCASE:
11778                 n1 = stzalloc(sizeof(struct ncase));
11779                 n1->type = NCASE;
11780                 n1->ncase.linno = savelinno;
11781                 if (readtoken() != TWORD)
11782                         raise_error_unexpected_syntax(TWORD);
11783                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11784                 n2->type = NARG;
11785                 /*n2->narg.next = NULL; - stzalloc did it */
11786                 n2->narg.text = wordtext;
11787                 n2->narg.backquote = backquotelist;
11788                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11789                 if (readtoken() != TIN)
11790                         raise_error_unexpected_syntax(TIN);
11791                 cpp = &n1->ncase.cases;
11792  next_case:
11793                 checkkwd = CHKNL | CHKKWD;
11794                 t = readtoken();
11795                 while (t != TESAC) {
11796                         if (lasttoken == TLP)
11797                                 readtoken();
11798                         *cpp = cp = stzalloc(sizeof(struct nclist));
11799                         cp->type = NCLIST;
11800                         app = &cp->nclist.pattern;
11801                         for (;;) {
11802                                 *app = ap = stzalloc(sizeof(struct narg));
11803                                 ap->type = NARG;
11804                                 /*ap->narg.next = NULL; - stzalloc did it */
11805                                 ap->narg.text = wordtext;
11806                                 ap->narg.backquote = backquotelist;
11807                                 if (readtoken() != TPIPE)
11808                                         break;
11809                                 app = &ap->narg.next;
11810                                 readtoken();
11811                         }
11812                         //ap->narg.next = NULL;
11813                         if (lasttoken != TRP)
11814                                 raise_error_unexpected_syntax(TRP);
11815                         cp->nclist.body = list(2);
11816
11817                         cpp = &cp->nclist.next;
11818
11819                         checkkwd = CHKNL | CHKKWD;
11820                         t = readtoken();
11821                         if (t != TESAC) {
11822                                 if (t != TENDCASE)
11823                                         raise_error_unexpected_syntax(TENDCASE);
11824                                 goto next_case;
11825                         }
11826                 }
11827                 *cpp = NULL;
11828                 goto redir;
11829         case TLP:
11830                 n1 = stzalloc(sizeof(struct nredir));
11831                 n1->type = NSUBSHELL;
11832                 n1->nredir.linno = savelinno;
11833                 n1->nredir.n = list(0);
11834                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11835                 t = TRP;
11836                 break;
11837         case TBEGIN:
11838                 n1 = list(0);
11839                 t = TEND;
11840                 break;
11841         IF_BASH_FUNCTION(case TFUNCTION:)
11842         case TWORD:
11843         case TREDIR:
11844                 tokpushback = 1;
11845                 return simplecmd();
11846         }
11847
11848         if (readtoken() != t)
11849                 raise_error_unexpected_syntax(t);
11850
11851  redir:
11852         /* Now check for redirection which may follow command */
11853         checkkwd = CHKKWD | CHKALIAS;
11854         rpp = rpp2;
11855         while (readtoken() == TREDIR) {
11856                 *rpp = n2 = redirnode;
11857                 rpp = &n2->nfile.next;
11858                 parsefname();
11859         }
11860         tokpushback = 1;
11861         *rpp = NULL;
11862         if (redir) {
11863                 if (n1->type != NSUBSHELL) {
11864                         n2 = stzalloc(sizeof(struct nredir));
11865                         n2->type = NREDIR;
11866                         n2->nredir.linno = savelinno;
11867                         n2->nredir.n = n1;
11868                         n1 = n2;
11869                 }
11870                 n1->nredir.redirect = redir;
11871         }
11872         return n1;
11873 }
11874
11875 #if BASH_DOLLAR_SQUOTE
11876 static int
11877 decode_dollar_squote(void)
11878 {
11879         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11880         int c, cnt;
11881         char *p;
11882         char buf[4];
11883
11884         c = pgetc();
11885         p = strchr(C_escapes, c);
11886         if (p) {
11887                 buf[0] = c;
11888                 p = buf;
11889                 cnt = 3;
11890                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11891                         do {
11892                                 c = pgetc();
11893                                 *++p = c;
11894                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11895                         pungetc();
11896                 } else if (c == 'x') { /* \xHH */
11897                         do {
11898                                 c = pgetc();
11899                                 *++p = c;
11900                         } while (isxdigit(c) && --cnt);
11901                         pungetc();
11902                         if (cnt == 3) { /* \x but next char is "bad" */
11903                                 c = 'x';
11904                                 goto unrecognized;
11905                         }
11906                 } else { /* simple seq like \\ or \t */
11907                         p++;
11908                 }
11909                 *p = '\0';
11910                 p = buf;
11911                 c = bb_process_escape_sequence((void*)&p);
11912         } else { /* unrecognized "\z": print both chars unless ' or " */
11913                 if (c != '\'' && c != '"') {
11914  unrecognized:
11915                         c |= 0x100; /* "please encode \, then me" */
11916                 }
11917         }
11918         return c;
11919 }
11920 #endif
11921
11922 /* Used by expandstr to get here-doc like behaviour. */
11923 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11924
11925 static ALWAYS_INLINE int
11926 realeofmark(const char *eofmark)
11927 {
11928         return eofmark && eofmark != FAKEEOFMARK;
11929 }
11930
11931 /*
11932  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11933  * is not NULL, read a here document.  In the latter case, eofmark is the
11934  * word which marks the end of the document and striptabs is true if
11935  * leading tabs should be stripped from the document.  The argument c
11936  * is the first character of the input token or document.
11937  *
11938  * Because C does not have internal subroutines, I have simulated them
11939  * using goto's to implement the subroutine linkage.  The following macros
11940  * will run code that appears at the end of readtoken1.
11941  */
11942 #define CHECKEND()      {goto checkend; checkend_return:;}
11943 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11944 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11945 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11946 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11947 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11948 static int
11949 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11950 {
11951         /* NB: syntax parameter fits into smallint */
11952         /* c parameter is an unsigned char or PEOF or PEOA */
11953         char *out;
11954         size_t len;
11955         struct nodelist *bqlist;
11956         smallint quotef;
11957         smallint oldstyle;
11958         smallint pssyntax;   /* we are expanding a prompt string */
11959         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11960         /* syntax stack */
11961         struct synstack synbase = { };
11962         struct synstack *synstack = &synbase;
11963
11964 #if ENABLE_ASH_EXPAND_PRMT
11965         pssyntax = (syntax == PSSYNTAX);
11966         if (pssyntax)
11967                 syntax = DQSYNTAX;
11968 #else
11969         pssyntax = 0; /* constant */
11970 #endif
11971         synstack->syntax = syntax;
11972
11973         if (syntax == DQSYNTAX)
11974                 synstack->dblquote = 1;
11975         quotef = 0;
11976         bqlist = NULL;
11977
11978         STARTSTACKSTR(out);
11979  loop:
11980         /* For each line, until end of word */
11981         CHECKEND();     /* set c to PEOF if at end of here document */
11982         for (;;) {      /* until end of line or end of word */
11983                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11984                 switch (SIT(c, synstack->syntax)) {
11985                 case CNL:       /* '\n' */
11986                         if (synstack->syntax == BASESYNTAX)
11987                                 goto endword;   /* exit outer loop */
11988                         USTPUTC(c, out);
11989                         nlprompt();
11990                         c = pgetc();
11991                         goto loop;              /* continue outer loop */
11992                 case CWORD:
11993                         USTPUTC(c, out);
11994                         break;
11995                 case CCTL:
11996 #if BASH_DOLLAR_SQUOTE
11997                         if (c == '\\' && bash_dollar_squote) {
11998                                 c = decode_dollar_squote();
11999                                 if (c == '\0') {
12000                                         /* skip $'\000', $'\x00' (like bash) */
12001                                         break;
12002                                 }
12003                                 if (c & 0x100) {
12004                                         /* Unknown escape. Encode as '\z' */
12005                                         c = (unsigned char)c;
12006                                         if (eofmark == NULL || synstack->dblquote)
12007                                                 USTPUTC(CTLESC, out);
12008                                         USTPUTC('\\', out);
12009                                 }
12010                         }
12011 #endif
12012                         if (!eofmark || synstack->dblquote || synstack->varnest)
12013                                 USTPUTC(CTLESC, out);
12014                         USTPUTC(c, out);
12015                         break;
12016                 case CBACK:     /* backslash */
12017                         c = pgetc_without_PEOA();
12018                         if (c == PEOF) {
12019                                 USTPUTC(CTLESC, out);
12020                                 USTPUTC('\\', out);
12021                                 pungetc();
12022                         } else if (c == '\n') {
12023                                 nlprompt();
12024                         } else {
12025                                 if (pssyntax && c == '$') {
12026                                         USTPUTC(CTLESC, out);
12027                                         USTPUTC('\\', out);
12028                                 }
12029                                 /* Backslash is retained if we are in "str"
12030                                  * and next char isn't dquote-special.
12031                                  */
12032                                 if (synstack->dblquote
12033                                  && c != '\\'
12034                                  && c != '`'
12035                                  && c != '$'
12036                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12037                                  && (c != '}' || !synstack->varnest)
12038                                 ) {
12039                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12040                                         USTPUTC('\\', out);
12041                                 }
12042                                 USTPUTC(CTLESC, out);
12043                                 USTPUTC(c, out);
12044                                 quotef = 1;
12045                         }
12046                         break;
12047                 case CSQUOTE:
12048                         synstack->syntax = SQSYNTAX;
12049  quotemark:
12050                         if (eofmark == NULL) {
12051                                 USTPUTC(CTLQUOTEMARK, out);
12052                         }
12053                         break;
12054                 case CDQUOTE:
12055                         synstack->syntax = DQSYNTAX;
12056                         synstack->dblquote = 1;
12057  toggledq:
12058                         if (synstack->varnest)
12059                                 synstack->innerdq ^= 1;
12060                         goto quotemark;
12061                 case CENDQUOTE:
12062                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12063                         if (eofmark != NULL && synstack->varnest == 0) {
12064                                 USTPUTC(c, out);
12065                                 break;
12066                         }
12067
12068                         if (synstack->dqvarnest == 0) {
12069                                 synstack->syntax = BASESYNTAX;
12070                                 synstack->dblquote = 0;
12071                         }
12072
12073                         quotef = 1;
12074
12075                         if (c == '"')
12076                                 goto toggledq;
12077
12078                         goto quotemark;
12079                 case CVAR:      /* '$' */
12080                         PARSESUB();             /* parse substitution */
12081                         break;
12082                 case CENDVAR:   /* '}' */
12083                         if (!synstack->innerdq && synstack->varnest > 0) {
12084                                 if (!--synstack->varnest && synstack->varpushed)
12085                                         synstack_pop(&synstack);
12086                                 else if (synstack->dqvarnest > 0)
12087                                         synstack->dqvarnest--;
12088                                 c = CTLENDVAR;
12089                         }
12090                         USTPUTC(c, out);
12091                         break;
12092 #if ENABLE_FEATURE_SH_MATH
12093                 case CLP:       /* '(' in arithmetic */
12094                         synstack->parenlevel++;
12095                         USTPUTC(c, out);
12096                         break;
12097                 case CRP:       /* ')' in arithmetic */
12098                         if (synstack->parenlevel > 0) {
12099                                 synstack->parenlevel--;
12100                         } else {
12101                                 if (pgetc_eatbnl() == ')') {
12102                                         c = CTLENDARI;
12103                                         synstack_pop(&synstack);
12104                                 } else {
12105                                         /*
12106                                          * unbalanced parens
12107                                          * (don't 2nd guess - no error)
12108                                          */
12109                                         pungetc();
12110                                 }
12111                         }
12112                         USTPUTC(c, out);
12113                         break;
12114 #endif
12115                 case CBQUOTE:   /* '`' */
12116                         if (checkkwd & CHKEOFMARK) {
12117                                 quotef = 1;
12118                                 USTPUTC('`', out);
12119                                 break;
12120                         }
12121
12122                         PARSEBACKQOLD();
12123                         break;
12124                 case CENDFILE:
12125                         goto endword;           /* exit outer loop */
12126                 case CIGN:
12127                         break;
12128                 default:
12129                         if (synstack->varnest == 0) {
12130 #if BASH_REDIR_OUTPUT
12131                                 if (c == '&') {
12132 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12133                                         if (pgetc() == '>')
12134                                                 c = 0x100 + '>'; /* flag &> */
12135                                         pungetc();
12136                                 }
12137 #endif
12138                                 goto endword;   /* exit outer loop */
12139                         }
12140                         IF_ASH_ALIAS(if (c != PEOA))
12141                                 USTPUTC(c, out);
12142                 }
12143                 c = pgetc();
12144         } /* for (;;) */
12145  endword:
12146
12147 #if ENABLE_FEATURE_SH_MATH
12148         if (synstack->syntax == ARISYNTAX)
12149                 raise_error_syntax("missing '))'");
12150 #endif
12151         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12152                 raise_error_syntax("unterminated quoted string");
12153         if (synstack->varnest != 0) {
12154                 /* { */
12155                 raise_error_syntax("missing '}'");
12156         }
12157         USTPUTC('\0', out);
12158         len = out - (char *)stackblock();
12159         out = stackblock();
12160         if (eofmark == NULL) {
12161                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12162                  && quotef == 0
12163                 ) {
12164                         if (isdigit_str9(out)) {
12165                                 PARSEREDIR(); /* passed as params: out, c */
12166                                 lasttoken = TREDIR;
12167                                 return lasttoken;
12168                         }
12169                         /* else: non-number X seen, interpret it
12170                          * as "NNNX>file" = "NNNX >file" */
12171                 }
12172                 pungetc();
12173         }
12174         quoteflag = quotef;
12175         backquotelist = bqlist;
12176         grabstackblock(len);
12177         wordtext = out;
12178         lasttoken = TWORD;
12179         return lasttoken;
12180 /* end of readtoken routine */
12181
12182 /*
12183  * Check to see whether we are at the end of the here document.  When this
12184  * is called, c is set to the first character of the next input line.  If
12185  * we are at the end of the here document, this routine sets the c to PEOF.
12186  */
12187 checkend: {
12188         if (realeofmark(eofmark)) {
12189                 int markloc;
12190                 char *p;
12191
12192 #if ENABLE_ASH_ALIAS
12193                 if (c == PEOA)
12194                         c = pgetc_without_PEOA();
12195 #endif
12196                 if (striptabs) {
12197                         while (c == '\t') {
12198                                 c = pgetc_without_PEOA();
12199                         }
12200                 }
12201
12202                 markloc = out - (char *)stackblock();
12203                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12204                         if (c != *p)
12205                                 goto more_heredoc;
12206
12207                         c = pgetc_without_PEOA();
12208                 }
12209
12210                 if (c == '\n' || c == PEOF) {
12211                         c = PEOF;
12212                         g_parsefile->linno++;
12213                         needprompt = doprompt;
12214                 } else {
12215                         int len_here;
12216
12217  more_heredoc:
12218                         p = (char *)stackblock() + markloc + 1;
12219                         len_here = out - p;
12220
12221                         if (len_here) {
12222                                 len_here -= (c >= PEOF);
12223                                 c = p[-1];
12224
12225                                 if (len_here) {
12226                                         char *str;
12227
12228                                         str = alloca(len_here + 1);
12229                                         *(char *)mempcpy(str, p, len_here) = '\0';
12230
12231                                         pushstring(str, NULL);
12232                                 }
12233                         }
12234                 }
12235
12236                 STADJUST((char *)stackblock() + markloc - out, out);
12237         }
12238         goto checkend_return;
12239 }
12240
12241 /*
12242  * Parse a redirection operator.  The variable "out" points to a string
12243  * specifying the fd to be redirected.  The variable "c" contains the
12244  * first character of the redirection operator.
12245  */
12246 parseredir: {
12247         /* out is already checked to be a valid number or "" */
12248         int fd = (*out == '\0' ? -1 : atoi(out));
12249         union node *np;
12250
12251         np = stzalloc(sizeof(struct nfile));
12252         if (c == '>') {
12253                 np->nfile.fd = 1;
12254                 c = pgetc_eatbnl();
12255                 if (c == '>')
12256                         np->type = NAPPEND;
12257                 else if (c == '|')
12258                         np->type = NCLOBBER;
12259                 else if (c == '&')
12260                         np->type = NTOFD;
12261                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12262                 else {
12263                         np->type = NTO;
12264                         pungetc();
12265                 }
12266         }
12267 #if BASH_REDIR_OUTPUT
12268         else if (c == 0x100 + '>') { /* this flags &> redirection */
12269                 np->nfile.fd = 1;
12270                 pgetc(); /* this is '>', no need to check */
12271                 np->type = NTO2;
12272         }
12273 #endif
12274         else { /* c == '<' */
12275                 /*np->nfile.fd = 0; - stzalloc did it */
12276                 c = pgetc_eatbnl();
12277                 switch (c) {
12278                 case '<':
12279                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12280                                 np = stzalloc(sizeof(struct nhere));
12281                                 /*np->nfile.fd = 0; - stzalloc did it */
12282                         }
12283                         np->type = NHERE;
12284                         heredoc = stzalloc(sizeof(struct heredoc));
12285                         heredoc->here = np;
12286                         c = pgetc_eatbnl();
12287                         if (c == '-') {
12288                                 heredoc->striptabs = 1;
12289                         } else {
12290                                 /*heredoc->striptabs = 0; - stzalloc did it */
12291                                 pungetc();
12292                         }
12293                         break;
12294
12295                 case '&':
12296                         np->type = NFROMFD;
12297                         break;
12298
12299                 case '>':
12300                         np->type = NFROMTO;
12301                         break;
12302
12303                 default:
12304                         np->type = NFROM;
12305                         pungetc();
12306                         break;
12307                 }
12308         }
12309         if (fd >= 0)
12310                 np->nfile.fd = fd;
12311         redirnode = np;
12312         goto parseredir_return;
12313 }
12314
12315 /*
12316  * Parse a substitution.  At this point, we have read the dollar sign
12317  * and nothing else.
12318  */
12319
12320 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12321  * (assuming ascii char codes, as the original implementation did) */
12322 #define is_special(c) \
12323         (((unsigned)(c) - 33 < 32) \
12324                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12325 parsesub: {
12326         unsigned char subtype;
12327         int typeloc;
12328
12329         c = pgetc_eatbnl();
12330         if ((checkkwd & CHKEOFMARK)
12331          || c > 255 /* PEOA or PEOF */
12332          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12333         ) {
12334 #if BASH_DOLLAR_SQUOTE
12335                 if (synstack->syntax != DQSYNTAX && c == '\'')
12336                         bash_dollar_squote = 1;
12337                 else
12338 #endif
12339                         USTPUTC('$', out);
12340                 pungetc();
12341         } else if (c == '(') {
12342                 /* $(command) or $((arith)) */
12343                 if (pgetc_eatbnl() == '(') {
12344 #if ENABLE_FEATURE_SH_MATH
12345                         PARSEARITH();
12346 #else
12347                         raise_error_syntax("support for $((arith)) is disabled");
12348 #endif
12349                 } else {
12350                         pungetc();
12351                         PARSEBACKQNEW();
12352                 }
12353         } else {
12354                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12355                 smalluint newsyn = synstack->syntax;
12356
12357                 USTPUTC(CTLVAR, out);
12358                 typeloc = out - (char *)stackblock();
12359                 STADJUST(1, out);
12360                 subtype = VSNORMAL;
12361                 if (c == '{') {
12362                         c = pgetc_eatbnl();
12363                         subtype = 0;
12364                 }
12365  varname:
12366                 if (is_name(c)) {
12367                         /* $[{[#]]NAME[}] */
12368                         do {
12369                                 STPUTC(c, out);
12370                                 c = pgetc_eatbnl();
12371                         } while (is_in_name(c));
12372                 } else if (isdigit(c)) {
12373                         /* $[{[#]]NUM[}] */
12374                         do {
12375                                 STPUTC(c, out);
12376                                 c = pgetc_eatbnl();
12377                         } while (isdigit(c));
12378                 } else {
12379                         /* $[{[#]]<specialchar>[}] */
12380                         int cc = c;
12381
12382                         c = pgetc_eatbnl();
12383                         if (!subtype && cc == '#') {
12384                                 subtype = VSLENGTH;
12385                                 if (c == '_' || isalnum(c))
12386                                         goto varname;
12387                                 cc = c;
12388                                 c = pgetc_eatbnl();
12389                                 if (cc == '}' || c != '}') {
12390                                         pungetc();
12391                                         subtype = 0;
12392                                         c = cc;
12393                                         cc = '#';
12394                                 }
12395                         }
12396
12397                         if (!is_special(cc)) {
12398                                 if (subtype == VSLENGTH)
12399                                         subtype = 0;
12400                                 goto badsub;
12401                         }
12402
12403                         USTPUTC(cc, out);
12404                 }
12405
12406                 if (c != '}' && subtype == VSLENGTH) {
12407                         /* ${#VAR didn't end with } */
12408                         goto badsub;
12409                 }
12410
12411                 if (subtype == 0) {
12412                         static const char types[] ALIGN1 = "}-+?=";
12413                         /* ${VAR...} but not $VAR or ${#VAR} */
12414                         /* c == first char after VAR */
12415                         int cc = c;
12416
12417                         switch (c) {
12418                         case ':':
12419                                 c = pgetc_eatbnl();
12420 #if BASH_SUBSTR
12421                                 /* This check is only needed to not misinterpret
12422                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12423                                  * constructs.
12424                                  */
12425                                 if (!strchr(types, c)) {
12426                                         subtype = VSSUBSTR;
12427                                         pungetc();
12428                                         break; /* "goto badsub" is bigger (!) */
12429                                 }
12430 #endif
12431                                 subtype = VSNUL;
12432                                 /*FALLTHROUGH*/
12433                         default: {
12434                                 const char *p = strchr(types, c);
12435                                 if (p == NULL)
12436                                         break;
12437                                 subtype |= p - types + VSNORMAL;
12438                                 break;
12439                         }
12440                         case '%':
12441                         case '#':
12442                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12443                                 c = pgetc_eatbnl();
12444                                 if (c == cc)
12445                                         subtype++;
12446                                 else
12447                                         pungetc();
12448
12449                                 newsyn = BASESYNTAX;
12450                                 break;
12451 #if BASH_PATTERN_SUBST
12452                         case '/':
12453                                 /* ${v/[/]pattern/repl} */
12454 //TODO: encode pattern and repl separately.
12455 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12456 // are broken (should print "ONE")
12457                                 subtype = VSREPLACE;
12458                                 newsyn = BASESYNTAX;
12459                                 c = pgetc_eatbnl();
12460                                 if (c != '/')
12461                                         goto badsub;
12462                                 subtype++; /* VSREPLACEALL */
12463                                 break;
12464 #endif
12465                         }
12466                 } else {
12467  badsub:
12468                         pungetc();
12469                 }
12470
12471                 if (newsyn == ARISYNTAX)
12472                         newsyn = DQSYNTAX;
12473
12474                 if ((newsyn != synstack->syntax || synstack->innerdq)
12475                  && subtype != VSNORMAL
12476                 ) {
12477                         synstack_push(&synstack,
12478                                 synstack->prev ?: alloca(sizeof(*synstack)),
12479                                 newsyn);
12480
12481                         synstack->varpushed = 1;
12482                         synstack->dblquote = newsyn != BASESYNTAX;
12483                 }
12484
12485                 ((unsigned char *)stackblock())[typeloc] = subtype;
12486                 if (subtype != VSNORMAL) {
12487                         synstack->varnest++;
12488                         if (synstack->dblquote)
12489                                 synstack->dqvarnest++;
12490                 }
12491                 STPUTC('=', out);
12492         }
12493         goto parsesub_return;
12494 }
12495
12496 /*
12497  * Called to parse command substitutions.  Newstyle is set if the command
12498  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12499  * list of commands (passed by reference), and savelen is the number of
12500  * characters on the top of the stack which must be preserved.
12501  */
12502 parsebackq: {
12503         struct nodelist **nlpp;
12504         union node *n;
12505         char *str;
12506         size_t savelen;
12507         smallint saveprompt = 0;
12508
12509         str = NULL;
12510         savelen = out - (char *)stackblock();
12511         if (savelen > 0) {
12512                 /*
12513                  * FIXME: this can allocate very large block on stack and SEGV.
12514                  * Example:
12515                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12516                  * allocates 100kb for every command subst. With about
12517                  * a hundred command substitutions stack overflows.
12518                  * With larger prepended string, SEGV happens sooner.
12519                  */
12520                 str = alloca(savelen);
12521                 memcpy(str, stackblock(), savelen);
12522         }
12523
12524         if (oldstyle) {
12525                 /* We must read until the closing backquote, giving special
12526                  * treatment to some slashes, and then push the string and
12527                  * reread it as input, interpreting it normally.
12528                  */
12529                 char *pout;
12530                 size_t psavelen;
12531                 char *pstr;
12532
12533                 STARTSTACKSTR(pout);
12534                 for (;;) {
12535                         int pc;
12536
12537                         setprompt_if(needprompt, 2);
12538                         pc = pgetc_eatbnl();
12539                         switch (pc) {
12540                         case '`':
12541                                 goto done;
12542
12543                         case '\\':
12544                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12545                                 if (pc != '\\' && pc != '`' && pc != '$'
12546                                  && (!synstack->dblquote || pc != '"')
12547                                 ) {
12548                                         STPUTC('\\', pout);
12549                                 }
12550                                 if (pc <= 255 /* not PEOA or PEOF */) {
12551                                         break;
12552                                 }
12553                                 /* fall through */
12554
12555                         case PEOF:
12556                         IF_ASH_ALIAS(case PEOA:)
12557                                 raise_error_syntax("EOF in backquote substitution");
12558
12559                         case '\n':
12560                                 nlnoprompt();
12561                                 break;
12562
12563                         default:
12564                                 break;
12565                         }
12566                         STPUTC(pc, pout);
12567                 }
12568  done:
12569                 STPUTC('\0', pout);
12570                 psavelen = pout - (char *)stackblock();
12571                 if (psavelen > 0) {
12572                         pstr = grabstackstr(pout);
12573                         setinputstring(pstr);
12574                 }
12575         }
12576         nlpp = &bqlist;
12577         while (*nlpp)
12578                 nlpp = &(*nlpp)->next;
12579         *nlpp = stzalloc(sizeof(**nlpp));
12580         /* (*nlpp)->next = NULL; - stzalloc did it */
12581
12582         if (oldstyle) {
12583                 saveprompt = doprompt;
12584                 doprompt = 0;
12585         }
12586
12587         n = list(2);
12588
12589         if (oldstyle)
12590                 doprompt = saveprompt;
12591         else if (readtoken() != TRP)
12592                 raise_error_unexpected_syntax(TRP);
12593
12594         (*nlpp)->n = n;
12595         if (oldstyle) {
12596                 /*
12597                  * Start reading from old file again, ignoring any pushed back
12598                  * tokens left from the backquote parsing
12599                  */
12600                 popfile();
12601                 tokpushback = 0;
12602         }
12603         while (stackblocksize() <= savelen)
12604                 growstackblock();
12605         STARTSTACKSTR(out);
12606         if (str) {
12607                 memcpy(out, str, savelen);
12608                 STADJUST(savelen, out);
12609         }
12610         USTPUTC(CTLBACKQ, out);
12611         if (oldstyle)
12612                 goto parsebackq_oldreturn;
12613         goto parsebackq_newreturn;
12614 }
12615
12616 #if ENABLE_FEATURE_SH_MATH
12617 /*
12618  * Parse an arithmetic expansion (indicate start of one and set state)
12619  */
12620 parsearith: {
12621
12622         synstack_push(&synstack,
12623                         synstack->prev ?: alloca(sizeof(*synstack)),
12624                         ARISYNTAX);
12625         synstack->dblquote = 1;
12626         USTPUTC(CTLARI, out);
12627         goto parsearith_return;
12628 }
12629 #endif
12630 } /* end of readtoken */
12631
12632 /*
12633  * Read the next input token.
12634  * If the token is a word, we set backquotelist to the list of cmds in
12635  *      backquotes.  We set quoteflag to true if any part of the word was
12636  *      quoted.
12637  * If the token is TREDIR, then we set redirnode to a structure containing
12638  *      the redirection.
12639  *
12640  * [Change comment:  here documents and internal procedures]
12641  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12642  *  word parsing code into a separate routine.  In this case, readtoken
12643  *  doesn't need to have any internal procedures, but parseword does.
12644  *  We could also make parseoperator in essence the main routine, and
12645  *  have parseword (readtoken1?) handle both words and redirection.]
12646  */
12647 #define NEW_xxreadtoken
12648 #ifdef NEW_xxreadtoken
12649 /* singles must be first! */
12650 static const char xxreadtoken_chars[7] ALIGN1 = {
12651         '\n', '(', ')', /* singles */
12652         '&', '|', ';',  /* doubles */
12653         0
12654 };
12655
12656 #define xxreadtoken_singles 3
12657 #define xxreadtoken_doubles 3
12658
12659 static const char xxreadtoken_tokens[] ALIGN1 = {
12660         TNL, TLP, TRP,          /* only single occurrence allowed */
12661         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12662         TEOF,                   /* corresponds to trailing nul */
12663         TAND, TOR, TENDCASE     /* if double occurrence */
12664 };
12665
12666 static int
12667 xxreadtoken(void)
12668 {
12669         int c;
12670
12671         if (tokpushback) {
12672                 tokpushback = 0;
12673                 return lasttoken;
12674         }
12675         setprompt_if(needprompt, 2);
12676         for (;;) {                      /* until token or start of word found */
12677                 c = pgetc_eatbnl();
12678                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12679                         continue;
12680
12681                 if (c == '#') {
12682                         while ((c = pgetc()) != '\n' && c != PEOF)
12683                                 continue;
12684                         pungetc();
12685                 } else if (c == '\\') {
12686                         break; /* return readtoken1(...) */
12687                 } else {
12688                         const char *p;
12689
12690                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12691                         if (c != PEOF) {
12692                                 if (c == '\n') {
12693                                         nlnoprompt();
12694                                 }
12695
12696                                 p = strchr(xxreadtoken_chars, c);
12697                                 if (p == NULL)
12698                                         break; /* return readtoken1(...) */
12699
12700                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12701                                         int cc = pgetc_eatbnl();
12702                                         if (cc == c) {    /* double occurrence? */
12703                                                 p += xxreadtoken_doubles + 1;
12704                                         } else {
12705                                                 pungetc();
12706 #if BASH_REDIR_OUTPUT
12707                                                 if (c == '&' && cc == '>') /* &> */
12708                                                         break; /* return readtoken1(...) */
12709 #endif
12710                                         }
12711                                 }
12712                         }
12713                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12714                         return lasttoken;
12715                 }
12716         } /* for (;;) */
12717
12718         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12719 }
12720 #else /* old xxreadtoken */
12721 #define RETURN(token)   return lasttoken = token
12722 static int
12723 xxreadtoken(void)
12724 {
12725         int c;
12726
12727         if (tokpushback) {
12728                 tokpushback = 0;
12729                 return lasttoken;
12730         }
12731         setprompt_if(needprompt, 2);
12732         for (;;) {      /* until token or start of word found */
12733                 c = pgetc_eatbnl();
12734                 switch (c) {
12735                 case ' ': case '\t':
12736                 IF_ASH_ALIAS(case PEOA:)
12737                         continue;
12738                 case '#':
12739                         while ((c = pgetc()) != '\n' && c != PEOF)
12740                                 continue;
12741                         pungetc();
12742                         continue;
12743                 case '\n':
12744                         nlnoprompt();
12745                         RETURN(TNL);
12746                 case PEOF:
12747                         RETURN(TEOF);
12748                 case '&':
12749                         if (pgetc_eatbnl() == '&')
12750                                 RETURN(TAND);
12751                         pungetc();
12752                         RETURN(TBACKGND);
12753                 case '|':
12754                         if (pgetc_eatbnl() == '|')
12755                                 RETURN(TOR);
12756                         pungetc();
12757                         RETURN(TPIPE);
12758                 case ';':
12759                         if (pgetc_eatbnl() == ';')
12760                                 RETURN(TENDCASE);
12761                         pungetc();
12762                         RETURN(TSEMI);
12763                 case '(':
12764                         RETURN(TLP);
12765                 case ')':
12766                         RETURN(TRP);
12767                 }
12768                 break;
12769         }
12770         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12771 #undef RETURN
12772 }
12773 #endif /* old xxreadtoken */
12774
12775 static int
12776 readtoken(void)
12777 {
12778         int t;
12779         int kwd = checkkwd;
12780 #if DEBUG
12781         smallint alreadyseen = tokpushback;
12782 #endif
12783
12784 #if ENABLE_ASH_ALIAS
12785  top:
12786 #endif
12787
12788         t = xxreadtoken();
12789
12790         /*
12791          * eat newlines
12792          */
12793         if (kwd & CHKNL) {
12794                 while (t == TNL) {
12795                         parseheredoc();
12796                         t = xxreadtoken();
12797                 }
12798         }
12799
12800         if (t != TWORD || quoteflag) {
12801                 goto out;
12802         }
12803
12804         /*
12805          * check for keywords
12806          */
12807         if (kwd & CHKKWD) {
12808                 const char *const *pp;
12809
12810                 pp = findkwd(wordtext);
12811                 if (pp) {
12812                         lasttoken = t = pp - tokname_array;
12813                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12814                         goto out;
12815                 }
12816         }
12817
12818         if (checkkwd & CHKALIAS) {
12819 #if ENABLE_ASH_ALIAS
12820                 struct alias *ap;
12821                 ap = lookupalias(wordtext, 1);
12822                 if (ap != NULL) {
12823                         if (*ap->val) {
12824                                 pushstring(ap->val, ap);
12825                         }
12826                         goto top;
12827                 }
12828 #endif
12829         }
12830  out:
12831         checkkwd = 0;
12832 #if DEBUG
12833         if (!alreadyseen)
12834                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12835         else
12836                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12837 #endif
12838         return t;
12839 }
12840
12841 static int
12842 peektoken(void)
12843 {
12844         int t;
12845
12846         t = readtoken();
12847         tokpushback = 1;
12848         return t;
12849 }
12850
12851 /*
12852  * Read and parse a command.  Returns NODE_EOF on end of file.
12853  * (NULL is a valid parse tree indicating a blank line.)
12854  */
12855 static union node *
12856 parsecmd(int interact)
12857 {
12858         tokpushback = 0;
12859         checkkwd = 0;
12860         heredoclist = 0;
12861         doprompt = interact;
12862         setprompt_if(doprompt, doprompt);
12863         needprompt = 0;
12864         return list(1);
12865 }
12866
12867 /*
12868  * Input any here documents.
12869  */
12870 static void
12871 parseheredoc(void)
12872 {
12873         struct heredoc *here;
12874         union node *n;
12875
12876         here = heredoclist;
12877         heredoclist = NULL;
12878
12879         while (here) {
12880                 setprompt_if(needprompt, 2);
12881                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12882                                 here->eofmark, here->striptabs);
12883                 n = stzalloc(sizeof(struct narg));
12884                 n->narg.type = NARG;
12885                 /*n->narg.next = NULL; - stzalloc did it */
12886                 n->narg.text = wordtext;
12887                 n->narg.backquote = backquotelist;
12888                 here->here->nhere.doc = n;
12889                 here = here->next;
12890         }
12891 }
12892
12893
12894 static const char *
12895 expandstr(const char *ps, int syntax_type)
12896 {
12897         union node n;
12898         int saveprompt;
12899
12900         /* XXX Fix (char *) cast. */
12901         setinputstring((char *)ps);
12902
12903         saveprompt = doprompt;
12904         doprompt = 0;
12905
12906         /* readtoken1() might die horribly.
12907          * Try a prompt with syntactically wrong command:
12908          * PS1='$(date "+%H:%M:%S) > '
12909          */
12910         {
12911                 volatile int saveint;
12912                 struct jmploc *volatile savehandler = exception_handler;
12913                 struct jmploc jmploc;
12914                 SAVE_INT(saveint);
12915                 if (setjmp(jmploc.loc) == 0) {
12916                         exception_handler = &jmploc;
12917                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12918                 }
12919                 exception_handler = savehandler;
12920                 RESTORE_INT(saveint);
12921         }
12922
12923         doprompt = saveprompt;
12924
12925         popfile();
12926
12927         n.narg.type = NARG;
12928         n.narg.next = NULL;
12929         n.narg.text = wordtext;
12930         n.narg.backquote = backquotelist;
12931
12932         expandarg(&n, NULL, EXP_QUOTED);
12933         return stackblock();
12934 }
12935
12936 static inline int
12937 parser_eof(void)
12938 {
12939         return tokpushback && lasttoken == TEOF;
12940 }
12941
12942 /*
12943  * Execute a command or commands contained in a string.
12944  */
12945 static int
12946 evalstring(char *s, int flags)
12947 {
12948         struct jmploc *volatile savehandler;
12949         struct jmploc jmploc;
12950         int ex;
12951
12952         union node *n;
12953         struct stackmark smark;
12954         int status;
12955
12956         s = sstrdup(s);
12957         setinputstring(s);
12958         setstackmark(&smark);
12959
12960         status = 0;
12961         /* On exception inside execution loop, we must popfile().
12962          * Try interactively:
12963          *      readonly a=a
12964          *      command eval "a=b"  # throws "is read only" error
12965          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12966          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12967          */
12968         savehandler = exception_handler;
12969         ex = setjmp(jmploc.loc);
12970         if (ex)
12971                 goto out;
12972         exception_handler = &jmploc;
12973
12974         while ((n = parsecmd(0)) != NODE_EOF) {
12975                 int i;
12976
12977                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12978                 if (n)
12979                         status = i;
12980                 popstackmark(&smark);
12981                 if (evalskip)
12982                         break;
12983         }
12984  out:
12985         popstackmark(&smark);
12986         popfile();
12987         stunalloc(s);
12988
12989         exception_handler = savehandler;
12990         if (ex)
12991                 longjmp(exception_handler->loc, ex);
12992
12993         return status;
12994 }
12995
12996 /*
12997  * The eval command.
12998  */
12999 static int FAST_FUNC
13000 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13001 {
13002         char *p;
13003         char *concat;
13004
13005         if (argv[1]) {
13006                 p = argv[1];
13007                 argv += 2;
13008                 if (argv[0]) {
13009                         STARTSTACKSTR(concat);
13010                         for (;;) {
13011                                 concat = stack_putstr(p, concat);
13012                                 p = *argv++;
13013                                 if (p == NULL)
13014                                         break;
13015                                 STPUTC(' ', concat);
13016                         }
13017                         STPUTC('\0', concat);
13018                         p = grabstackstr(concat);
13019                 }
13020                 return evalstring(p, flags & EV_TESTED);
13021         }
13022         return 0;
13023 }
13024
13025 /*
13026  * Read and execute commands.
13027  * "Top" is nonzero for the top level command loop;
13028  * it turns on prompting if the shell is interactive.
13029  */
13030 static int
13031 cmdloop(int top)
13032 {
13033         union node *n;
13034         struct stackmark smark;
13035         int inter;
13036         int status = 0;
13037         int numeof = 0;
13038
13039         TRACE(("cmdloop(%d) called\n", top));
13040         for (;;) {
13041                 int skip;
13042
13043                 setstackmark(&smark);
13044 #if JOBS
13045                 if (doing_jobctl)
13046                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13047 #endif
13048                 inter = 0;
13049                 if (iflag && top) {
13050                         inter++;
13051                         chkmail();
13052                 }
13053                 n = parsecmd(inter);
13054 #if DEBUG
13055                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13056                         showtree(n);
13057 #endif
13058                 if (n == NODE_EOF) {
13059                         if (!top || numeof >= 50)
13060                                 break;
13061                         if (!stoppedjobs()) {
13062                                 if (!Iflag)
13063                                         break;
13064                                 out2str("\nUse \"exit\" to leave shell.\n");
13065                         }
13066                         numeof++;
13067                 } else if (nflag == 0) {
13068                         int i;
13069
13070                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13071                         job_warning >>= 1;
13072                         numeof = 0;
13073                         i = evaltree(n, 0);
13074                         if (n)
13075                                 status = i;
13076                 }
13077                 popstackmark(&smark);
13078                 skip = evalskip;
13079
13080                 if (skip) {
13081                         evalskip &= ~SKIPFUNC;
13082                         break;
13083                 }
13084         }
13085         return status;
13086 }
13087
13088 /*
13089  * Take commands from a file.  To be compatible we should do a path
13090  * search for the file, which is necessary to find sub-commands.
13091  */
13092 static char *
13093 find_dot_file(char *name)
13094 {
13095         char *fullname;
13096         const char *path = pathval();
13097         struct stat statb;
13098
13099         /* don't try this for absolute or relative paths */
13100         if (strchr(name, '/'))
13101                 return name;
13102
13103         while ((fullname = path_advance(&path, name)) != NULL) {
13104                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13105                         /*
13106                          * Don't bother freeing here, since it will
13107                          * be freed by the caller.
13108                          */
13109                         return fullname;
13110                 }
13111                 if (fullname != name)
13112                         stunalloc(fullname);
13113         }
13114         /* not found in PATH */
13115
13116 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13117         return name;
13118 #else
13119         ash_msg_and_raise_error("%s: not found", name);
13120         /* NOTREACHED */
13121 #endif
13122 }
13123
13124 static int FAST_FUNC
13125 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13126 {
13127         /* "false; . empty_file; echo $?" should print 0, not 1: */
13128         int status = 0;
13129         char *fullname;
13130         char **argv;
13131         char *args_need_save;
13132         volatile struct shparam saveparam;
13133
13134 //???
13135 //      struct strlist *sp;
13136 //      for (sp = cmdenviron; sp; sp = sp->next)
13137 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13138
13139         nextopt(nullstr); /* handle possible "--" */
13140         argv = argptr;
13141
13142         if (!argv[0]) {
13143                 /* bash says: "bash: .: filename argument required" */
13144                 return 2; /* bash compat */
13145         }
13146
13147         /* This aborts if file isn't found, which is POSIXly correct.
13148          * bash returns exitcode 1 instead.
13149          */
13150         fullname = find_dot_file(argv[0]);
13151         argv++;
13152         args_need_save = argv[0];
13153         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13154                 int argc;
13155                 saveparam = shellparam;
13156                 shellparam.malloced = 0;
13157                 argc = 1;
13158                 while (argv[argc])
13159                         argc++;
13160                 shellparam.nparam = argc;
13161                 shellparam.p = argv;
13162         };
13163
13164         /* This aborts if file can't be opened, which is POSIXly correct.
13165          * bash returns exitcode 1 instead.
13166          */
13167         setinputfile(fullname, INPUT_PUSH_FILE);
13168         commandname = fullname;
13169         status = cmdloop(0);
13170         popfile();
13171
13172         if (args_need_save) {
13173                 freeparam(&shellparam);
13174                 shellparam = saveparam;
13175         };
13176
13177         return status;
13178 }
13179
13180 static int FAST_FUNC
13181 exitcmd(int argc UNUSED_PARAM, char **argv)
13182 {
13183         if (stoppedjobs())
13184                 return 0;
13185         if (argv[1])
13186                 exitstatus = number(argv[1]);
13187         raise_exception(EXEXIT);
13188         /* NOTREACHED */
13189 }
13190
13191 /*
13192  * Read a file containing shell functions.
13193  */
13194 static void
13195 readcmdfile(char *name)
13196 {
13197         setinputfile(name, INPUT_PUSH_FILE);
13198         cmdloop(0);
13199         popfile();
13200 }
13201
13202
13203 /* ============ find_command inplementation */
13204
13205 /*
13206  * Resolve a command name.  If you change this routine, you may have to
13207  * change the shellexec routine as well.
13208  */
13209 static void
13210 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13211 {
13212         struct tblentry *cmdp;
13213         int idx;
13214         int prev;
13215         char *fullname;
13216         struct stat statb;
13217         int e;
13218         int updatetbl;
13219         struct builtincmd *bcmd;
13220
13221         /* If name contains a slash, don't use PATH or hash table */
13222         if (strchr(name, '/') != NULL) {
13223                 entry->u.index = -1;
13224                 if (act & DO_ABS) {
13225                         while (stat(name, &statb) < 0) {
13226 #ifdef SYSV
13227                                 if (errno == EINTR)
13228                                         continue;
13229 #endif
13230                                 entry->cmdtype = CMDUNKNOWN;
13231                                 return;
13232                         }
13233                 }
13234                 entry->cmdtype = CMDNORMAL;
13235                 return;
13236         }
13237
13238 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13239
13240         updatetbl = (path == pathval());
13241         if (!updatetbl) {
13242                 act |= DO_ALTPATH;
13243                 if (strstr(path, "%builtin") != NULL)
13244                         act |= DO_ALTBLTIN;
13245         }
13246
13247         /* If name is in the table, check answer will be ok */
13248         cmdp = cmdlookup(name, 0);
13249         if (cmdp != NULL) {
13250                 int bit;
13251
13252                 switch (cmdp->cmdtype) {
13253                 default:
13254 #if DEBUG
13255                         abort();
13256 #endif
13257                 case CMDNORMAL:
13258                         bit = DO_ALTPATH;
13259                         break;
13260                 case CMDFUNCTION:
13261                         bit = DO_NOFUNC;
13262                         break;
13263                 case CMDBUILTIN:
13264                         bit = DO_ALTBLTIN;
13265                         break;
13266                 }
13267                 if (act & bit) {
13268                         updatetbl = 0;
13269                         cmdp = NULL;
13270                 } else if (cmdp->rehash == 0)
13271                         /* if not invalidated by cd, we're done */
13272                         goto success;
13273         }
13274
13275         /* If %builtin not in path, check for builtin next */
13276         bcmd = find_builtin(name);
13277         if (bcmd) {
13278                 if (IS_BUILTIN_REGULAR(bcmd))
13279                         goto builtin_success;
13280                 if (act & DO_ALTPATH) {
13281                         if (!(act & DO_ALTBLTIN))
13282                                 goto builtin_success;
13283                 } else if (builtinloc <= 0) {
13284                         goto builtin_success;
13285                 }
13286         }
13287
13288 #if ENABLE_FEATURE_SH_STANDALONE
13289         {
13290                 int applet_no = find_applet_by_name(name);
13291                 if (applet_no >= 0) {
13292                         entry->cmdtype = CMDNORMAL;
13293                         entry->u.index = -2 - applet_no;
13294                         return;
13295                 }
13296         }
13297 #endif
13298
13299         /* We have to search path. */
13300         prev = -1;              /* where to start */
13301         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13302                 if (cmdp->cmdtype == CMDBUILTIN)
13303                         prev = builtinloc;
13304                 else
13305                         prev = cmdp->param.index;
13306         }
13307
13308         e = ENOENT;
13309         idx = -1;
13310  loop:
13311         while ((fullname = path_advance(&path, name)) != NULL) {
13312                 stunalloc(fullname);
13313                 /* NB: code below will still use fullname
13314                  * despite it being "unallocated" */
13315                 idx++;
13316                 if (pathopt) {
13317                         if (prefix(pathopt, "builtin")) {
13318                                 if (bcmd)
13319                                         goto builtin_success;
13320                                 continue;
13321                         }
13322                         if ((act & DO_NOFUNC)
13323                          || !prefix(pathopt, "func")
13324                         ) {     /* ignore unimplemented options */
13325                                 continue;
13326                         }
13327                 }
13328                 /* if rehash, don't redo absolute path names */
13329                 if (fullname[0] == '/' && idx <= prev) {
13330                         if (idx < prev)
13331                                 continue;
13332                         TRACE(("searchexec \"%s\": no change\n", name));
13333                         goto success;
13334                 }
13335                 while (stat(fullname, &statb) < 0) {
13336 #ifdef SYSV
13337                         if (errno == EINTR)
13338                                 continue;
13339 #endif
13340                         if (errno != ENOENT && errno != ENOTDIR)
13341                                 e = errno;
13342                         goto loop;
13343                 }
13344                 e = EACCES;     /* if we fail, this will be the error */
13345                 if (!S_ISREG(statb.st_mode))
13346                         continue;
13347                 if (pathopt) {          /* this is a %func directory */
13348                         stalloc(strlen(fullname) + 1);
13349                         /* NB: stalloc will return space pointed by fullname
13350                          * (because we don't have any intervening allocations
13351                          * between stunalloc above and this stalloc) */
13352                         readcmdfile(fullname);
13353                         cmdp = cmdlookup(name, 0);
13354                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13355                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13356                         stunalloc(fullname);
13357                         goto success;
13358                 }
13359                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13360                 if (!updatetbl) {
13361                         entry->cmdtype = CMDNORMAL;
13362                         entry->u.index = idx;
13363                         return;
13364                 }
13365                 INT_OFF;
13366                 cmdp = cmdlookup(name, 1);
13367                 cmdp->cmdtype = CMDNORMAL;
13368                 cmdp->param.index = idx;
13369                 INT_ON;
13370                 goto success;
13371         }
13372
13373         /* We failed.  If there was an entry for this command, delete it */
13374         if (cmdp && updatetbl)
13375                 delete_cmd_entry();
13376         if (act & DO_ERR) {
13377 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13378                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13379                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13380                         char *argv[3];
13381                         argv[0] = (char*) "command_not_found_handle";
13382                         argv[1] = name;
13383                         argv[2] = NULL;
13384                         evalfun(hookp->param.func, 2, argv, 0);
13385                         entry->cmdtype = CMDUNKNOWN;
13386                         return;
13387                 }
13388 #endif
13389                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13390         }
13391         entry->cmdtype = CMDUNKNOWN;
13392         return;
13393
13394  builtin_success:
13395         if (!updatetbl) {
13396                 entry->cmdtype = CMDBUILTIN;
13397                 entry->u.cmd = bcmd;
13398                 return;
13399         }
13400         INT_OFF;
13401         cmdp = cmdlookup(name, 1);
13402         cmdp->cmdtype = CMDBUILTIN;
13403         cmdp->param.cmd = bcmd;
13404         INT_ON;
13405  success:
13406         cmdp->rehash = 0;
13407         entry->cmdtype = cmdp->cmdtype;
13408         entry->u = cmdp->param;
13409 }
13410
13411
13412 /*
13413  * The trap builtin.
13414  */
13415 static int FAST_FUNC
13416 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13417 {
13418         char *action;
13419         char **ap;
13420         int signo, exitcode;
13421
13422         nextopt(nullstr);
13423         ap = argptr;
13424         if (!*ap) {
13425                 for (signo = 0; signo < NSIG; signo++) {
13426                         char *tr = trap_ptr[signo];
13427                         if (tr) {
13428                                 /* note: bash adds "SIG", but only if invoked
13429                                  * as "bash". If called as "sh", or if set -o posix,
13430                                  * then it prints short signal names.
13431                                  * We are printing short names: */
13432                                 out1fmt("trap -- %s %s\n",
13433                                                 single_quote(tr),
13434                                                 get_signame(signo));
13435                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13436                  * In this case, we will exit very soon, no need to free(). */
13437                                 /* if (trap_ptr != trap && tp[0]) */
13438                                 /*      free(tr); */
13439                         }
13440                 }
13441                 /*
13442                 if (trap_ptr != trap) {
13443                         free(trap_ptr);
13444                         trap_ptr = trap;
13445                 }
13446                 */
13447                 return 0;
13448         }
13449
13450         /* Why the second check?
13451          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13452          * In this case, NUM is signal no, not an action.
13453          */
13454         action = NULL;
13455         if (ap[1] && !is_number(ap[0]))
13456                 action = *ap++;
13457
13458         exitcode = 0;
13459         while (*ap) {
13460                 signo = get_signum(*ap);
13461                 if (signo < 0) {
13462                         /* Mimic bash message exactly */
13463                         ash_msg("%s: invalid signal specification", *ap);
13464                         exitcode = 1;
13465                         goto next;
13466                 }
13467                 INT_OFF;
13468                 if (action) {
13469                         if (LONE_DASH(action))
13470                                 action = NULL;
13471                         else {
13472                                 if (action[0]) /* not NULL and not "" and not "-" */
13473                                         may_have_traps = 1;
13474                                 action = ckstrdup(action);
13475                         }
13476                 }
13477                 free(trap[signo]);
13478                 trap[signo] = action;
13479                 if (signo != 0)
13480                         setsignal(signo);
13481                 INT_ON;
13482  next:
13483                 ap++;
13484         }
13485         return exitcode;
13486 }
13487
13488
13489 /* ============ Builtins */
13490
13491 #if ENABLE_ASH_HELP
13492 static int FAST_FUNC
13493 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13494 {
13495         unsigned col;
13496         unsigned i;
13497
13498         out1fmt(
13499                 "Built-in commands:\n"
13500                 "------------------\n");
13501         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13502                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13503                                         builtintab[i].name + 1);
13504                 if (col > 60) {
13505                         out1fmt("\n");
13506                         col = 0;
13507                 }
13508         }
13509 # if ENABLE_FEATURE_SH_STANDALONE
13510         {
13511                 const char *a = applet_names;
13512                 while (*a) {
13513                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13514                         if (col > 60) {
13515                                 out1fmt("\n");
13516                                 col = 0;
13517                         }
13518                         while (*a++ != '\0')
13519                                 continue;
13520                 }
13521         }
13522 # endif
13523         newline_and_flush(stdout);
13524         return EXIT_SUCCESS;
13525 }
13526 #endif
13527
13528 #if MAX_HISTORY
13529 static int FAST_FUNC
13530 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13531 {
13532         show_history(line_input_state);
13533         return EXIT_SUCCESS;
13534 }
13535 #endif
13536
13537 /*
13538  * The export and readonly commands.
13539  */
13540 static int FAST_FUNC
13541 exportcmd(int argc UNUSED_PARAM, char **argv)
13542 {
13543         struct var *vp;
13544         char *name;
13545         const char *p;
13546         char **aptr;
13547         char opt;
13548         int flag;
13549         int flag_off;
13550
13551         /* "readonly" in bash accepts, but ignores -n.
13552          * We do the same: it saves a conditional in nextopt's param.
13553          */
13554         flag_off = 0;
13555         while ((opt = nextopt("np")) != '\0') {
13556                 if (opt == 'n')
13557                         flag_off = VEXPORT;
13558         }
13559         flag = VEXPORT;
13560         if (argv[0][0] == 'r') {
13561                 flag = VREADONLY;
13562                 flag_off = 0; /* readonly ignores -n */
13563         }
13564         flag_off = ~flag_off;
13565
13566         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13567         {
13568                 aptr = argptr;
13569                 name = *aptr;
13570                 if (name) {
13571                         do {
13572                                 p = strchr(name, '=');
13573                                 if (p != NULL) {
13574                                         p++;
13575                                 } else {
13576                                         vp = *findvar(hashvar(name), name);
13577                                         if (vp) {
13578                                                 vp->flags = ((vp->flags | flag) & flag_off);
13579                                                 continue;
13580                                         }
13581                                 }
13582                                 setvar(name, p, (flag & flag_off));
13583                         } while ((name = *++aptr) != NULL);
13584                         return 0;
13585                 }
13586         }
13587
13588         /* No arguments. Show the list of exported or readonly vars.
13589          * -n is ignored.
13590          */
13591         showvars(argv[0], flag, 0);
13592         return 0;
13593 }
13594
13595 /*
13596  * Delete a function if it exists.
13597  */
13598 static void
13599 unsetfunc(const char *name)
13600 {
13601         struct tblentry *cmdp;
13602
13603         cmdp = cmdlookup(name, 0);
13604         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13605                 delete_cmd_entry();
13606 }
13607
13608 /*
13609  * The unset builtin command.  We unset the function before we unset the
13610  * variable to allow a function to be unset when there is a readonly variable
13611  * with the same name.
13612  */
13613 static int FAST_FUNC
13614 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13615 {
13616         char **ap;
13617         int i;
13618         int flag = 0;
13619
13620         while ((i = nextopt("vf")) != 0) {
13621                 flag = i;
13622         }
13623
13624         for (ap = argptr; *ap; ap++) {
13625                 if (flag != 'f') {
13626                         unsetvar(*ap);
13627                         continue;
13628                 }
13629                 if (flag != 'v')
13630                         unsetfunc(*ap);
13631         }
13632         return 0;
13633 }
13634
13635 static const unsigned char timescmd_str[] ALIGN1 = {
13636         ' ',  offsetof(struct tms, tms_utime),
13637         '\n', offsetof(struct tms, tms_stime),
13638         ' ',  offsetof(struct tms, tms_cutime),
13639         '\n', offsetof(struct tms, tms_cstime),
13640         0
13641 };
13642 static int FAST_FUNC
13643 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13644 {
13645         unsigned clk_tck;
13646         const unsigned char *p;
13647         struct tms buf;
13648
13649         clk_tck = bb_clk_tck();
13650
13651         times(&buf);
13652         p = timescmd_str;
13653         do {
13654                 unsigned sec, frac;
13655                 unsigned long t;
13656                 t = *(clock_t *)(((char *) &buf) + p[1]);
13657                 sec = t / clk_tck;
13658                 frac = t % clk_tck;
13659                 out1fmt("%um%u.%03us%c",
13660                         sec / 60, sec % 60,
13661                         (frac * 1000) / clk_tck,
13662                         p[0]);
13663                 p += 2;
13664         } while (*p);
13665
13666         return 0;
13667 }
13668
13669 #if ENABLE_FEATURE_SH_MATH
13670 /*
13671  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13672  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13673  *
13674  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13675  */
13676 static int FAST_FUNC
13677 letcmd(int argc UNUSED_PARAM, char **argv)
13678 {
13679         arith_t i;
13680
13681         argv++;
13682         if (!*argv)
13683                 ash_msg_and_raise_error("expression expected");
13684         do {
13685                 i = ash_arith(*argv);
13686         } while (*++argv);
13687
13688         return !i;
13689 }
13690 #endif
13691
13692 /*
13693  * The read builtin. Options:
13694  *      -r              Do not interpret '\' specially
13695  *      -s              Turn off echo (tty only)
13696  *      -n NCHARS       Read NCHARS max
13697  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13698  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13699  *      -u FD           Read from given FD instead of fd 0
13700  *      -d DELIM        End on DELIM char, not newline
13701  * This uses unbuffered input, which may be avoidable in some cases.
13702  * TODO: bash also has:
13703  *      -a ARRAY        Read into array[0],[1],etc
13704  *      -e              Use line editing (tty only)
13705  */
13706 static int FAST_FUNC
13707 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13708 {
13709         char *opt_n = NULL;
13710         char *opt_p = NULL;
13711         char *opt_t = NULL;
13712         char *opt_u = NULL;
13713         char *opt_d = NULL; /* optimized out if !BASH */
13714         int read_flags = 0;
13715         const char *r;
13716         int i;
13717
13718         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13719                 switch (i) {
13720                 case 'p':
13721                         opt_p = optionarg;
13722                         break;
13723                 case 'n':
13724                         opt_n = optionarg;
13725                         break;
13726                 case 's':
13727                         read_flags |= BUILTIN_READ_SILENT;
13728                         break;
13729                 case 't':
13730                         opt_t = optionarg;
13731                         break;
13732                 case 'r':
13733                         read_flags |= BUILTIN_READ_RAW;
13734                         break;
13735                 case 'u':
13736                         opt_u = optionarg;
13737                         break;
13738 #if BASH_READ_D
13739                 case 'd':
13740                         opt_d = optionarg;
13741                         break;
13742 #endif
13743                 default:
13744                         break;
13745                 }
13746         }
13747
13748         /* "read -s" needs to save/restore termios, can't allow ^C
13749          * to jump out of it.
13750          */
13751  again:
13752         INT_OFF;
13753         r = shell_builtin_read(setvar0,
13754                 argptr,
13755                 bltinlookup("IFS"), /* can be NULL */
13756                 read_flags,
13757                 opt_n,
13758                 opt_p,
13759                 opt_t,
13760                 opt_u,
13761                 opt_d
13762         );
13763         INT_ON;
13764
13765         if ((uintptr_t)r == 1 && errno == EINTR) {
13766                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13767                  * Correct behavior is to not exit "read"
13768                  */
13769                 if (pending_sig == 0)
13770                         goto again;
13771         }
13772
13773         if ((uintptr_t)r > 1)
13774                 ash_msg_and_raise_error(r);
13775
13776         return (uintptr_t)r;
13777 }
13778
13779 static int FAST_FUNC
13780 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13781 {
13782         static const char permuser[3] ALIGN1 = "ogu";
13783
13784         mode_t mask;
13785         int symbolic_mode = 0;
13786
13787         while (nextopt("S") != '\0') {
13788                 symbolic_mode = 1;
13789         }
13790
13791         INT_OFF;
13792         mask = umask(0);
13793         umask(mask);
13794         INT_ON;
13795
13796         if (*argptr == NULL) {
13797                 if (symbolic_mode) {
13798                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13799                         char *p = buf;
13800                         int i;
13801
13802                         i = 2;
13803                         for (;;) {
13804                                 *p++ = ',';
13805                                 *p++ = permuser[i];
13806                                 *p++ = '=';
13807                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13808                                 if (!(mask & 0400)) *p++ = 'r';
13809                                 if (!(mask & 0200)) *p++ = 'w';
13810                                 if (!(mask & 0100)) *p++ = 'x';
13811                                 mask <<= 3;
13812                                 if (--i < 0)
13813                                         break;
13814                         }
13815                         *p = '\0';
13816                         puts(buf + 1);
13817                 } else {
13818                         out1fmt("%04o\n", mask);
13819                 }
13820         } else {
13821                 char *modestr = *argptr;
13822                 /* numeric umasks are taken as-is */
13823                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13824                 if (!isdigit(modestr[0]))
13825                         mask ^= 0777;
13826                 mask = bb_parse_mode(modestr, mask);
13827                 if ((unsigned)mask > 0777) {
13828                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13829                 }
13830                 if (!isdigit(modestr[0]))
13831                         mask ^= 0777;
13832                 umask(mask);
13833         }
13834         return 0;
13835 }
13836
13837 static int FAST_FUNC
13838 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13839 {
13840         return shell_builtin_ulimit(argv);
13841 }
13842
13843 /* ============ main() and helpers */
13844
13845 /*
13846  * Called to exit the shell.
13847  */
13848 static void
13849 exitshell(void)
13850 {
13851         struct jmploc loc;
13852         char *p;
13853         int status;
13854
13855 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13856         save_history(line_input_state);
13857 #endif
13858         status = exitstatus;
13859         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13860         if (setjmp(loc.loc)) {
13861                 if (exception_type == EXEXIT)
13862                         status = exitstatus;
13863                 goto out;
13864         }
13865         exception_handler = &loc;
13866         p = trap[0];
13867         if (p) {
13868                 trap[0] = NULL;
13869                 evalskip = 0;
13870                 evalstring(p, 0);
13871                 /*free(p); - we'll exit soon */
13872         }
13873  out:
13874         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13875          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13876          */
13877         setjobctl(0);
13878         flush_stdout_stderr();
13879         _exit(status);
13880         /* NOTREACHED */
13881 }
13882
13883 /* Don't inline: conserve stack of caller from having our locals too */
13884 static NOINLINE void
13885 init(void)
13886 {
13887         /* we will never free this */
13888         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13889         basepf.linno = 1;
13890
13891         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13892         setsignal(SIGCHLD);
13893
13894         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13895          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13896          */
13897         signal(SIGHUP, SIG_DFL);
13898
13899         {
13900                 char **envp;
13901                 const char *p;
13902
13903                 initvar();
13904                 for (envp = environ; envp && *envp; envp++) {
13905 /* Used to have
13906  *                      p = endofname(*envp);
13907  *                      if (p != *envp && *p == '=') {
13908  * here to weed out badly-named variables, but this breaks
13909  * scenarios where people do want them passed to children:
13910  * import os
13911  * os.environ["test-test"]="test"
13912  * if os.fork() == 0:
13913  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13914  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13915  */
13916                         if (strchr(*envp, '=')) {
13917                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13918                         }
13919                 }
13920
13921                 setvareq((char*)defoptindvar, VTEXTFIXED);
13922
13923                 setvar0("PPID", utoa(getppid()));
13924 #if BASH_SHLVL_VAR
13925                 p = lookupvar("SHLVL");
13926                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13927 #endif
13928 #if BASH_HOSTNAME_VAR
13929                 if (!lookupvar("HOSTNAME")) {
13930                         struct utsname uts;
13931                         uname(&uts);
13932                         setvar0("HOSTNAME", uts.nodename);
13933                 }
13934 #endif
13935                 p = lookupvar("PWD");
13936                 if (p) {
13937                         struct stat st1, st2;
13938                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13939                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13940                         ) {
13941                                 p = NULL;
13942                         }
13943                 }
13944                 setpwd(p, 0);
13945         }
13946 }
13947
13948
13949 //usage:#define ash_trivial_usage
13950 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
13951 //usage:#define ash_full_usage "\n\n"
13952 //usage:        "Unix shell interpreter"
13953
13954 /*
13955  * Process the shell command line arguments.
13956  */
13957 static int
13958 procargs(char **argv)
13959 {
13960         int i;
13961         const char *xminusc;
13962         char **xargv;
13963         int login_sh;
13964
13965         xargv = argv;
13966         login_sh = xargv[0] && xargv[0][0] == '-';
13967         arg0 = xargv[0];
13968         /* if (xargv[0]) - mmm, this is always true! */
13969                 xargv++;
13970         for (i = 0; i < NOPTS; i++)
13971                 optlist[i] = 2;
13972         argptr = xargv;
13973         if (options(/*cmdline:*/ 1, &login_sh)) {
13974                 /* it already printed err message */
13975                 raise_exception(EXERROR);
13976         }
13977         xargv = argptr;
13978         xminusc = minusc;
13979         if (*xargv == NULL) {
13980                 if (xminusc)
13981                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13982                 sflag = 1;
13983         }
13984         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13985                 iflag = 1;
13986         if (mflag == 2)
13987                 mflag = iflag;
13988         for (i = 0; i < NOPTS; i++)
13989                 if (optlist[i] == 2)
13990                         optlist[i] = 0;
13991 #if DEBUG == 2
13992         debug = 1;
13993 #endif
13994         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13995         if (xminusc) {
13996                 minusc = *xargv++;
13997                 if (*xargv)
13998                         goto setarg0;
13999         } else if (!sflag) {
14000                 setinputfile(*xargv, 0);
14001  setarg0:
14002                 arg0 = *xargv++;
14003                 commandname = arg0;
14004         }
14005
14006         shellparam.p = xargv;
14007 #if ENABLE_ASH_GETOPTS
14008         shellparam.optind = 1;
14009         shellparam.optoff = -1;
14010 #endif
14011         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14012         while (*xargv) {
14013                 shellparam.nparam++;
14014                 xargv++;
14015         }
14016         optschanged();
14017
14018         return login_sh;
14019 }
14020
14021 /*
14022  * Read /etc/profile, ~/.profile, $ENV.
14023  */
14024 static void
14025 read_profile(const char *name)
14026 {
14027         name = expandstr(name, DQSYNTAX);
14028         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14029                 return;
14030         cmdloop(0);
14031         popfile();
14032 }
14033
14034 /*
14035  * This routine is called when an error or an interrupt occurs in an
14036  * interactive shell and control is returned to the main command loop.
14037  * (In dash, this function is auto-generated by build machinery).
14038  */
14039 static void
14040 reset(void)
14041 {
14042         /* from eval.c: */
14043         evalskip = 0;
14044         loopnest = 0;
14045
14046         /* from expand.c: */
14047         ifsfree();
14048
14049         /* from input.c: */
14050         g_parsefile->left_in_buffer = 0;
14051         g_parsefile->left_in_line = 0;      /* clear input buffer */
14052         popallfiles();
14053
14054         /* from redir.c: */
14055         unwindredir(NULL);
14056
14057         /* from var.c: */
14058         unwindlocalvars(NULL);
14059 }
14060
14061 #if PROFILE
14062 static short profile_buf[16384];
14063 extern int etext();
14064 #endif
14065
14066 /*
14067  * Main routine.  We initialize things, parse the arguments, execute
14068  * profiles if we're a login shell, and then call cmdloop to execute
14069  * commands.  The setjmp call sets up the location to jump to when an
14070  * exception occurs.  When an exception occurs the variable "state"
14071  * is used to figure out how far we had gotten.
14072  */
14073 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14074 int ash_main(int argc UNUSED_PARAM, char **argv)
14075 {
14076         volatile smallint state;
14077         struct jmploc jmploc;
14078         struct stackmark smark;
14079         int login_sh;
14080
14081         /* Initialize global data */
14082         INIT_G_misc();
14083         INIT_G_memstack();
14084         INIT_G_var();
14085 #if ENABLE_ASH_ALIAS
14086         INIT_G_alias();
14087 #endif
14088         INIT_G_cmdtable();
14089
14090 #if PROFILE
14091         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14092 #endif
14093
14094 #if ENABLE_FEATURE_EDITING
14095         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14096 #endif
14097         state = 0;
14098         if (setjmp(jmploc.loc)) {
14099                 smallint e;
14100                 smallint s;
14101
14102                 reset();
14103
14104                 e = exception_type;
14105                 s = state;
14106                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14107                         exitshell();
14108                 }
14109                 if (e == EXINT) {
14110                         newline_and_flush(stderr);
14111                 }
14112
14113                 popstackmark(&smark);
14114                 FORCE_INT_ON; /* enable interrupts */
14115                 if (s == 1)
14116                         goto state1;
14117                 if (s == 2)
14118                         goto state2;
14119                 if (s == 3)
14120                         goto state3;
14121                 goto state4;
14122         }
14123         exception_handler = &jmploc;
14124         rootpid = getpid();
14125
14126         init();
14127         setstackmark(&smark);
14128         login_sh = procargs(argv);
14129 #if DEBUG
14130         TRACE(("Shell args: "));
14131         trace_puts_args(argv);
14132 #endif
14133
14134         if (login_sh) {
14135                 const char *hp;
14136
14137                 state = 1;
14138                 read_profile("/etc/profile");
14139  state1:
14140                 state = 2;
14141                 hp = lookupvar("HOME");
14142                 if (hp)
14143                         read_profile("$HOME/.profile");
14144         }
14145  state2:
14146         state = 3;
14147         if (
14148 #ifndef linux
14149          getuid() == geteuid() && getgid() == getegid() &&
14150 #endif
14151          iflag
14152         ) {
14153                 const char *shinit = lookupvar("ENV");
14154                 if (shinit != NULL && *shinit != '\0')
14155                         read_profile(shinit);
14156         }
14157         popstackmark(&smark);
14158  state3:
14159         state = 4;
14160         if (minusc) {
14161                 /* evalstring pushes parsefile stack.
14162                  * Ensure we don't falsely claim that 0 (stdin)
14163                  * is one of stacked source fds.
14164                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14165                 // if (!sflag) g_parsefile->pf_fd = -1;
14166                 // ^^ not necessary since now we special-case fd 0
14167                 // in save_fd_on_redirect()
14168                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14169         }
14170
14171         if (sflag || minusc == NULL) {
14172 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14173                 if (iflag) {
14174                         const char *hp = lookupvar("HISTFILE");
14175                         if (!hp) {
14176                                 hp = lookupvar("HOME");
14177                                 if (hp) {
14178                                         INT_OFF;
14179                                         hp = concat_path_file(hp, ".ash_history");
14180                                         setvar0("HISTFILE", hp);
14181                                         free((char*)hp);
14182                                         INT_ON;
14183                                         hp = lookupvar("HISTFILE");
14184                                 }
14185                         }
14186                         if (hp)
14187                                 line_input_state->hist_file = hp;
14188 # if ENABLE_FEATURE_SH_HISTFILESIZE
14189                         hp = lookupvar("HISTFILESIZE");
14190                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14191 # endif
14192                 }
14193 #endif
14194  state4: /* XXX ??? - why isn't this before the "if" statement */
14195                 cmdloop(1);
14196         }
14197 #if PROFILE
14198         monitor(0);
14199 #endif
14200 #ifdef GPROF
14201         {
14202                 extern void _mcleanup(void);
14203                 _mcleanup();
14204         }
14205 #endif
14206         TRACE(("End of main reached\n"));
14207         exitshell();
14208         /* NOTREACHED */
14209 }
14210
14211
14212 /*-
14213  * Copyright (c) 1989, 1991, 1993, 1994
14214  *      The Regents of the University of California.  All rights reserved.
14215  *
14216  * This code is derived from software contributed to Berkeley by
14217  * Kenneth Almquist.
14218  *
14219  * Redistribution and use in source and binary forms, with or without
14220  * modification, are permitted provided that the following conditions
14221  * are met:
14222  * 1. Redistributions of source code must retain the above copyright
14223  *    notice, this list of conditions and the following disclaimer.
14224  * 2. Redistributions in binary form must reproduce the above copyright
14225  *    notice, this list of conditions and the following disclaimer in the
14226  *    documentation and/or other materials provided with the distribution.
14227  * 3. Neither the name of the University nor the names of its contributors
14228  *    may be used to endorse or promote products derived from this software
14229  *    without specific prior written permission.
14230  *
14231  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14232  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14233  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14234  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14235  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14236  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14237  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14238  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14239  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14240  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14241  * SUCH DAMAGE.
14242  */