ash: make it possible to disable "const global ptr" optimization
[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 <setjmp.h>
181 #include <fnmatch.h>
182 #include <sys/times.h>
183 #include <sys/utsname.h> /* for setting $HOSTNAME */
184 #include "busybox.h" /* for applet_names */
185
186 /* So far, all bash compat is controlled by one config option */
187 /* Separate defines document which part of code implements what */
188 /* function keyword */
189 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
190 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
191 /* &>file */
192 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
193 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
194 /* $'...' */
195 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
196 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
197 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
198 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
199 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
200 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
201 /* [[ EXPR ]] */
202 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
203 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
204 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
205 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
206 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
207 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
208 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
209 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
210
211 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
212 /* Bionic at least up to version 24 has no glob() */
213 # undef  ENABLE_ASH_INTERNAL_GLOB
214 # define ENABLE_ASH_INTERNAL_GLOB 1
215 #endif
216
217 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
218 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
219 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
220 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
221 # error glob() should unbackslash them and match. uClibc does not unbackslash,
222 # error fails to match dirname, subsequently not expanding <pattern> in it.
223 // Testcase:
224 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
225 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
226 #endif
227
228 #if !ENABLE_ASH_INTERNAL_GLOB
229 # include <glob.h>
230 #endif
231
232 #include "unicode.h"
233 #include "shell_common.h"
234 #if ENABLE_FEATURE_SH_MATH
235 # include "math.h"
236 #else
237 typedef long arith_t;
238 # define ARITH_FMT "%ld"
239 #endif
240 #if ENABLE_ASH_RANDOM_SUPPORT
241 # include "random.h"
242 #else
243 # define CLEAR_RANDOM_T(rnd) ((void)0)
244 #endif
245
246 #include "NUM_APPLETS.h"
247 #if NUM_APPLETS == 1
248 /* STANDALONE does not make sense, and won't compile */
249 # undef CONFIG_FEATURE_SH_STANDALONE
250 # undef ENABLE_FEATURE_SH_STANDALONE
251 # undef IF_FEATURE_SH_STANDALONE
252 # undef IF_NOT_FEATURE_SH_STANDALONE
253 # define ENABLE_FEATURE_SH_STANDALONE 0
254 # define IF_FEATURE_SH_STANDALONE(...)
255 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
256 #endif
257
258 #ifndef PIPE_BUF
259 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
260 #endif
261
262 #if !BB_MMU
263 # error "Do not even bother, ash will not run on NOMMU machine"
264 #endif
265
266 /* We use a trick to have more optimized code (fewer pointer reloads):
267  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
268  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
269  * This way, compiler in ash.c knows the pointer can not change.
270  *
271  * However, this may break on weird arches or toolchains. In this case,
272  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
273  * this optimization.
274  */
275 #ifndef BB_GLOBAL_CONST
276 # define BB_GLOBAL_CONST const
277 #endif
278
279
280 /* ============ Hash table sizes. Configurable. */
281
282 #define VTABSIZE 39
283 #define ATABSIZE 39
284 #define CMDTABLESIZE 31         /* should be prime */
285
286
287 /* ============ Shell options */
288
289 static const char *const optletters_optnames[] = {
290         "e"   "errexit",
291         "f"   "noglob",
292         "I"   "ignoreeof",
293         "i"   "interactive",
294         "m"   "monitor",
295         "n"   "noexec",
296         "s"   "stdin",
297         "x"   "xtrace",
298         "v"   "verbose",
299         "C"   "noclobber",
300         "a"   "allexport",
301         "b"   "notify",
302         "u"   "nounset",
303         "\0"  "vi"
304 #if BASH_PIPEFAIL
305         ,"\0"  "pipefail"
306 #endif
307 #if DEBUG
308         ,"\0"  "nolog"
309         ,"\0"  "debug"
310 #endif
311 };
312
313 #define optletters(n)  optletters_optnames[n][0]
314 #define optnames(n)   (optletters_optnames[n] + 1)
315
316 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
317
318
319 /* ============ Misc data */
320
321 #define msg_illnum "Illegal number: %s"
322
323 /*
324  * We enclose jmp_buf in a structure so that we can declare pointers to
325  * jump locations.  The global variable handler contains the location to
326  * jump to when an exception occurs, and the global variable exception_type
327  * contains a code identifying the exception.  To implement nested
328  * exception handlers, the user should save the value of handler on entry
329  * to an inner scope, set handler to point to a jmploc structure for the
330  * inner scope, and restore handler on exit from the scope.
331  */
332 struct jmploc {
333         jmp_buf loc;
334 };
335
336 struct globals_misc {
337         uint8_t exitstatus;     /* exit status of last command */
338         uint8_t back_exitstatus;/* exit status of backquoted command */
339         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
340         int rootpid;            /* pid of main shell */
341         /* shell level: 0 for the main shell, 1 for its children, and so on */
342         int shlvl;
343 #define rootshell (!shlvl)
344         int errlinno;
345
346         char *minusc;  /* argument to -c option */
347
348         char *curdir; // = nullstr;     /* current working directory */
349         char *physdir; // = nullstr;    /* physical working directory */
350
351         char *arg0; /* value of $0 */
352
353         struct jmploc *exception_handler;
354
355         volatile int suppress_int; /* counter */
356         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
357         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
358         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
359         smallint exception_type; /* kind of exception (0..5) */
360         /* exceptions */
361 #define EXINT 0         /* SIGINT received */
362 #define EXERROR 1       /* a generic error */
363 #define EXEXIT 4        /* exit the shell */
364
365         char nullstr[1];        /* zero length string */
366
367         char optlist[NOPTS];
368 #define eflag optlist[0]
369 #define fflag optlist[1]
370 #define Iflag optlist[2]
371 #define iflag optlist[3]
372 #define mflag optlist[4]
373 #define nflag optlist[5]
374 #define sflag optlist[6]
375 #define xflag optlist[7]
376 #define vflag optlist[8]
377 #define Cflag optlist[9]
378 #define aflag optlist[10]
379 #define bflag optlist[11]
380 #define uflag optlist[12]
381 #define viflag optlist[13]
382 #if BASH_PIPEFAIL
383 # define pipefail optlist[14]
384 #else
385 # define pipefail 0
386 #endif
387 #if DEBUG
388 # define nolog optlist[14 + BASH_PIPEFAIL]
389 # define debug optlist[15 + BASH_PIPEFAIL]
390 #endif
391
392         /* trap handler commands */
393         /*
394          * Sigmode records the current value of the signal handlers for the various
395          * modes.  A value of zero means that the current handler is not known.
396          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
397          */
398         char sigmode[NSIG - 1];
399 #define S_DFL      1            /* default signal handling (SIG_DFL) */
400 #define S_CATCH    2            /* signal is caught */
401 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
402 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
403
404         /* indicates specified signal received */
405         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
406         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
407         char *trap[NSIG];
408         char **trap_ptr;        /* used only by "trap hack" */
409
410         /* Rarely referenced stuff */
411 #if ENABLE_ASH_RANDOM_SUPPORT
412         random_t random_gen;
413 #endif
414         pid_t backgndpid;        /* pid of last background process */
415 };
416 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
417 #define G_misc (*ash_ptr_to_globals_misc)
418 #define exitstatus        (G_misc.exitstatus )
419 #define back_exitstatus   (G_misc.back_exitstatus )
420 #define job_warning       (G_misc.job_warning)
421 #define rootpid     (G_misc.rootpid    )
422 #define shlvl       (G_misc.shlvl      )
423 #define errlinno    (G_misc.errlinno   )
424 #define minusc      (G_misc.minusc     )
425 #define curdir      (G_misc.curdir     )
426 #define physdir     (G_misc.physdir    )
427 #define arg0        (G_misc.arg0       )
428 #define exception_handler (G_misc.exception_handler)
429 #define exception_type    (G_misc.exception_type   )
430 #define suppress_int      (G_misc.suppress_int     )
431 #define pending_int       (G_misc.pending_int      )
432 #define got_sigchld       (G_misc.got_sigchld      )
433 #define pending_sig       (G_misc.pending_sig      )
434 #define nullstr     (G_misc.nullstr    )
435 #define optlist     (G_misc.optlist    )
436 #define sigmode     (G_misc.sigmode    )
437 #define gotsig      (G_misc.gotsig     )
438 #define may_have_traps    (G_misc.may_have_traps   )
439 #define trap        (G_misc.trap       )
440 #define trap_ptr    (G_misc.trap_ptr   )
441 #define random_gen  (G_misc.random_gen )
442 #define backgndpid  (G_misc.backgndpid )
443 #define INIT_G_misc() do { \
444         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
445         barrier(); \
446         curdir = nullstr; \
447         physdir = nullstr; \
448         trap_ptr = trap; \
449 } while (0)
450
451
452 /* ============ DEBUG */
453 #if DEBUG
454 static void trace_printf(const char *fmt, ...);
455 static void trace_vprintf(const char *fmt, va_list va);
456 # define TRACE(param)    trace_printf param
457 # define TRACEV(param)   trace_vprintf param
458 # define close(fd) do { \
459         int dfd = (fd); \
460         if (close(dfd) < 0) \
461                 bb_error_msg("bug on %d: closing %d(0x%x)", \
462                         __LINE__, dfd, dfd); \
463 } while (0)
464 #else
465 # define TRACE(param)
466 # define TRACEV(param)
467 #endif
468
469
470 /* ============ Utility functions */
471 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
472 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
473
474 static int
475 isdigit_str9(const char *str)
476 {
477         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
478         while (--maxlen && isdigit(*str))
479                 str++;
480         return (*str == '\0');
481 }
482
483 static const char *
484 var_end(const char *var)
485 {
486         while (*var)
487                 if (*var++ == '=')
488                         break;
489         return var;
490 }
491
492
493 /* ============ Interrupts / exceptions */
494
495 static void exitshell(void) NORETURN;
496
497 /*
498  * These macros allow the user to suspend the handling of interrupt signals
499  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
500  * much more efficient and portable.  (But hacking the kernel is so much
501  * more fun than worrying about efficiency and portability. :-))
502  */
503 #if DEBUG_INTONOFF
504 # define INT_OFF do { \
505         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
506         suppress_int++; \
507         barrier(); \
508 } while (0)
509 #else
510 # define INT_OFF do { \
511         suppress_int++; \
512         barrier(); \
513 } while (0)
514 #endif
515
516 /*
517  * Called to raise an exception.  Since C doesn't include exceptions, we
518  * just do a longjmp to the exception handler.  The type of exception is
519  * stored in the global variable "exception_type".
520  */
521 static void raise_exception(int) NORETURN;
522 static void
523 raise_exception(int e)
524 {
525 #if DEBUG
526         if (exception_handler == NULL)
527                 abort();
528 #endif
529         INT_OFF;
530         exception_type = e;
531         longjmp(exception_handler->loc, 1);
532 }
533 #if DEBUG
534 #define raise_exception(e) do { \
535         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
536         raise_exception(e); \
537 } while (0)
538 #endif
539
540 /*
541  * Called when a SIGINT is received.  (If the user specifies
542  * that SIGINT is to be trapped or ignored using the trap builtin, then
543  * this routine is not called.)  Suppressint is nonzero when interrupts
544  * are held using the INT_OFF macro.  (The test for iflag is just
545  * defensive programming.)
546  */
547 static void raise_interrupt(void) NORETURN;
548 static void
549 raise_interrupt(void)
550 {
551         pending_int = 0;
552         /* Signal is not automatically unmasked after it is raised,
553          * do it ourself - unmask all signals */
554         sigprocmask_allsigs(SIG_UNBLOCK);
555         /* pending_sig = 0; - now done in signal_handler() */
556
557         if (!(rootshell && iflag)) {
558                 /* Kill ourself with SIGINT */
559                 signal(SIGINT, SIG_DFL);
560                 raise(SIGINT);
561         }
562         /* bash: ^C even on empty command line sets $? */
563         exitstatus = SIGINT + 128;
564         raise_exception(EXINT);
565         /* NOTREACHED */
566 }
567 #if DEBUG
568 #define raise_interrupt() do { \
569         TRACE(("raising interrupt on line %d\n", __LINE__)); \
570         raise_interrupt(); \
571 } while (0)
572 #endif
573
574 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
575 int_on(void)
576 {
577         barrier();
578         if (--suppress_int == 0 && pending_int) {
579                 raise_interrupt();
580         }
581 }
582 #if DEBUG_INTONOFF
583 # define INT_ON do { \
584         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
585         int_on(); \
586 } while (0)
587 #else
588 # define INT_ON int_on()
589 #endif
590 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
591 force_int_on(void)
592 {
593         barrier();
594         suppress_int = 0;
595         if (pending_int)
596                 raise_interrupt();
597 }
598 #define FORCE_INT_ON force_int_on()
599
600 #define SAVE_INT(v) ((v) = suppress_int)
601
602 #define RESTORE_INT(v) do { \
603         barrier(); \
604         suppress_int = (v); \
605         if (suppress_int == 0 && pending_int) \
606                 raise_interrupt(); \
607 } while (0)
608
609
610 /* ============ Stdout/stderr output */
611
612 static void
613 outstr(const char *p, FILE *file)
614 {
615         INT_OFF;
616         fputs(p, file);
617         INT_ON;
618 }
619
620 static void
621 flush_stdout_stderr(void)
622 {
623         INT_OFF;
624         fflush_all();
625         INT_ON;
626 }
627
628 /* Was called outcslow(c,FILE*), but c was always '\n' */
629 static void
630 newline_and_flush(FILE *dest)
631 {
632         INT_OFF;
633         putc('\n', dest);
634         fflush(dest);
635         INT_ON;
636 }
637
638 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
639 static int
640 out1fmt(const char *fmt, ...)
641 {
642         va_list ap;
643         int r;
644
645         INT_OFF;
646         va_start(ap, fmt);
647         r = vprintf(fmt, ap);
648         va_end(ap);
649         INT_ON;
650         return r;
651 }
652
653 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
654 static int
655 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
656 {
657         va_list ap;
658         int ret;
659
660         INT_OFF;
661         va_start(ap, fmt);
662         ret = vsnprintf(outbuf, length, fmt, ap);
663         va_end(ap);
664         INT_ON;
665         return ret;
666 }
667
668 static void
669 out1str(const char *p)
670 {
671         outstr(p, stdout);
672 }
673
674 static void
675 out2str(const char *p)
676 {
677         outstr(p, stderr);
678         flush_stdout_stderr();
679 }
680
681
682 /* ============ Parser structures */
683
684 /* control characters in argument strings */
685 #define CTL_FIRST CTLESC
686 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
687 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
688 #define CTLENDVAR    ((unsigned char)'\203')
689 #define CTLBACKQ     ((unsigned char)'\204')
690 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
691 #define CTLENDARI    ((unsigned char)'\207')
692 #define CTLQUOTEMARK ((unsigned char)'\210')
693 #define CTL_LAST CTLQUOTEMARK
694
695 /* variable substitution byte (follows CTLVAR) */
696 #define VSTYPE  0x0f            /* type of variable substitution */
697 #define VSNUL   0x10            /* colon--treat the empty string as unset */
698
699 /* values of VSTYPE field */
700 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
701 #define VSMINUS         0x2     /* ${var-text} */
702 #define VSPLUS          0x3     /* ${var+text} */
703 #define VSQUESTION      0x4     /* ${var?message} */
704 #define VSASSIGN        0x5     /* ${var=text} */
705 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
706 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
707 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
708 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
709 #define VSLENGTH        0xa     /* ${#var} */
710 #if BASH_SUBSTR
711 #define VSSUBSTR        0xc     /* ${var:position:length} */
712 #endif
713 #if BASH_PATTERN_SUBST
714 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
715 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
716 #endif
717
718 static const char dolatstr[] ALIGN1 = {
719         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
720 };
721 #define DOLATSTRLEN 6
722
723 #define NCMD      0
724 #define NPIPE     1
725 #define NREDIR    2
726 #define NBACKGND  3
727 #define NSUBSHELL 4
728 #define NAND      5
729 #define NOR       6
730 #define NSEMI     7
731 #define NIF       8
732 #define NWHILE    9
733 #define NUNTIL   10
734 #define NFOR     11
735 #define NCASE    12
736 #define NCLIST   13
737 #define NDEFUN   14
738 #define NARG     15
739 #define NTO      16
740 #if BASH_REDIR_OUTPUT
741 #define NTO2     17
742 #endif
743 #define NCLOBBER 18
744 #define NFROM    19
745 #define NFROMTO  20
746 #define NAPPEND  21
747 #define NTOFD    22
748 #define NFROMFD  23
749 #define NHERE    24
750 #define NXHERE   25
751 #define NNOT     26
752 #define N_NUMBER 27
753
754 union node;
755
756 struct ncmd {
757         smallint type; /* Nxxxx */
758         int linno;
759         union node *assign;
760         union node *args;
761         union node *redirect;
762 };
763
764 struct npipe {
765         smallint type;
766         smallint pipe_backgnd;
767         struct nodelist *cmdlist;
768 };
769
770 struct nredir {
771         smallint type;
772         int linno;
773         union node *n;
774         union node *redirect;
775 };
776
777 struct nbinary {
778         smallint type;
779         union node *ch1;
780         union node *ch2;
781 };
782
783 struct nif {
784         smallint type;
785         union node *test;
786         union node *ifpart;
787         union node *elsepart;
788 };
789
790 struct nfor {
791         smallint type;
792         int linno;
793         union node *args;
794         union node *body;
795         char *var;
796 };
797
798 struct ncase {
799         smallint type;
800         int linno;
801         union node *expr;
802         union node *cases;
803 };
804
805 struct nclist {
806         smallint type;
807         union node *next;
808         union node *pattern;
809         union node *body;
810 };
811
812 struct ndefun {
813         smallint type;
814         int linno;
815         char *text;
816         union node *body;
817 };
818
819 struct narg {
820         smallint type;
821         union node *next;
822         char *text;
823         struct nodelist *backquote;
824 };
825
826 /* nfile and ndup layout must match!
827  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
828  * that it is actually NTO2 (>&file), and change its type.
829  */
830 struct nfile {
831         smallint type;
832         union node *next;
833         int fd;
834         int _unused_dupfd;
835         union node *fname;
836         char *expfname;
837 };
838
839 struct ndup {
840         smallint type;
841         union node *next;
842         int fd;
843         int dupfd;
844         union node *vname;
845         char *_unused_expfname;
846 };
847
848 struct nhere {
849         smallint type;
850         union node *next;
851         int fd;
852         union node *doc;
853 };
854
855 struct nnot {
856         smallint type;
857         union node *com;
858 };
859
860 union node {
861         smallint type;
862         struct ncmd ncmd;
863         struct npipe npipe;
864         struct nredir nredir;
865         struct nbinary nbinary;
866         struct nif nif;
867         struct nfor nfor;
868         struct ncase ncase;
869         struct nclist nclist;
870         struct ndefun ndefun;
871         struct narg narg;
872         struct nfile nfile;
873         struct ndup ndup;
874         struct nhere nhere;
875         struct nnot nnot;
876 };
877
878 /*
879  * NODE_EOF is returned by parsecmd when it encounters an end of file.
880  * It must be distinct from NULL.
881  */
882 #define NODE_EOF ((union node *) -1L)
883
884 struct nodelist {
885         struct nodelist *next;
886         union node *n;
887 };
888
889 struct funcnode {
890         int count;
891         union node n;
892 };
893
894 /*
895  * Free a parse tree.
896  */
897 static void
898 freefunc(struct funcnode *f)
899 {
900         if (f && --f->count < 0)
901                 free(f);
902 }
903
904
905 /* ============ Debugging output */
906
907 #if DEBUG
908
909 static FILE *tracefile;
910
911 static void
912 trace_printf(const char *fmt, ...)
913 {
914         va_list va;
915
916         if (debug != 1)
917                 return;
918         if (DEBUG_TIME)
919                 fprintf(tracefile, "%u ", (int) time(NULL));
920         if (DEBUG_PID)
921                 fprintf(tracefile, "[%u] ", (int) getpid());
922         if (DEBUG_SIG)
923                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
924         va_start(va, fmt);
925         vfprintf(tracefile, fmt, va);
926         va_end(va);
927 }
928
929 static void
930 trace_vprintf(const char *fmt, va_list va)
931 {
932         if (debug != 1)
933                 return;
934         vfprintf(tracefile, fmt, va);
935         fprintf(tracefile, "\n");
936 }
937
938 static void
939 trace_puts(const char *s)
940 {
941         if (debug != 1)
942                 return;
943         fputs(s, tracefile);
944 }
945
946 static void
947 trace_puts_quoted(char *s)
948 {
949         char *p;
950         char c;
951
952         if (debug != 1)
953                 return;
954         putc('"', tracefile);
955         for (p = s; *p; p++) {
956                 switch ((unsigned char)*p) {
957                 case '\n': c = 'n'; goto backslash;
958                 case '\t': c = 't'; goto backslash;
959                 case '\r': c = 'r'; goto backslash;
960                 case '\"': c = '\"'; goto backslash;
961                 case '\\': c = '\\'; goto backslash;
962                 case CTLESC: c = 'e'; goto backslash;
963                 case CTLVAR: c = 'v'; goto backslash;
964                 case CTLBACKQ: c = 'q'; goto backslash;
965  backslash:
966                         putc('\\', tracefile);
967                         putc(c, tracefile);
968                         break;
969                 default:
970                         if (*p >= ' ' && *p <= '~')
971                                 putc(*p, tracefile);
972                         else {
973                                 putc('\\', tracefile);
974                                 putc((*p >> 6) & 03, tracefile);
975                                 putc((*p >> 3) & 07, tracefile);
976                                 putc(*p & 07, tracefile);
977                         }
978                         break;
979                 }
980         }
981         putc('"', tracefile);
982 }
983
984 static void
985 trace_puts_args(char **ap)
986 {
987         if (debug != 1)
988                 return;
989         if (!*ap)
990                 return;
991         while (1) {
992                 trace_puts_quoted(*ap);
993                 if (!*++ap) {
994                         putc('\n', tracefile);
995                         break;
996                 }
997                 putc(' ', tracefile);
998         }
999 }
1000
1001 static void
1002 opentrace(void)
1003 {
1004         char s[100];
1005 #ifdef O_APPEND
1006         int flags;
1007 #endif
1008
1009         if (debug != 1) {
1010                 if (tracefile)
1011                         fflush(tracefile);
1012                 /* leave open because libedit might be using it */
1013                 return;
1014         }
1015         strcpy(s, "./trace");
1016         if (tracefile) {
1017                 if (!freopen(s, "a", tracefile)) {
1018                         fprintf(stderr, "Can't re-open %s\n", s);
1019                         debug = 0;
1020                         return;
1021                 }
1022         } else {
1023                 tracefile = fopen(s, "a");
1024                 if (tracefile == NULL) {
1025                         fprintf(stderr, "Can't open %s\n", s);
1026                         debug = 0;
1027                         return;
1028                 }
1029         }
1030 #ifdef O_APPEND
1031         flags = fcntl(fileno(tracefile), F_GETFL);
1032         if (flags >= 0)
1033                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1034 #endif
1035         setlinebuf(tracefile);
1036         fputs("\nTracing started.\n", tracefile);
1037 }
1038
1039 static void
1040 indent(int amount, char *pfx, FILE *fp)
1041 {
1042         int i;
1043
1044         for (i = 0; i < amount; i++) {
1045                 if (pfx && i == amount - 1)
1046                         fputs(pfx, fp);
1047                 putc('\t', fp);
1048         }
1049 }
1050
1051 /* little circular references here... */
1052 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1053
1054 static void
1055 sharg(union node *arg, FILE *fp)
1056 {
1057         char *p;
1058         struct nodelist *bqlist;
1059         unsigned char subtype;
1060
1061         if (arg->type != NARG) {
1062                 out1fmt("<node type %d>\n", arg->type);
1063                 abort();
1064         }
1065         bqlist = arg->narg.backquote;
1066         for (p = arg->narg.text; *p; p++) {
1067                 switch ((unsigned char)*p) {
1068                 case CTLESC:
1069                         p++;
1070                         putc(*p, fp);
1071                         break;
1072                 case CTLVAR:
1073                         putc('$', fp);
1074                         putc('{', fp);
1075                         subtype = *++p;
1076                         if (subtype == VSLENGTH)
1077                                 putc('#', fp);
1078
1079                         while (*p != '=') {
1080                                 putc(*p, fp);
1081                                 p++;
1082                         }
1083
1084                         if (subtype & VSNUL)
1085                                 putc(':', fp);
1086
1087                         switch (subtype & VSTYPE) {
1088                         case VSNORMAL:
1089                                 putc('}', fp);
1090                                 break;
1091                         case VSMINUS:
1092                                 putc('-', fp);
1093                                 break;
1094                         case VSPLUS:
1095                                 putc('+', fp);
1096                                 break;
1097                         case VSQUESTION:
1098                                 putc('?', fp);
1099                                 break;
1100                         case VSASSIGN:
1101                                 putc('=', fp);
1102                                 break;
1103                         case VSTRIMLEFT:
1104                                 putc('#', fp);
1105                                 break;
1106                         case VSTRIMLEFTMAX:
1107                                 putc('#', fp);
1108                                 putc('#', fp);
1109                                 break;
1110                         case VSTRIMRIGHT:
1111                                 putc('%', fp);
1112                                 break;
1113                         case VSTRIMRIGHTMAX:
1114                                 putc('%', fp);
1115                                 putc('%', fp);
1116                                 break;
1117                         case VSLENGTH:
1118                                 break;
1119                         default:
1120                                 out1fmt("<subtype %d>", subtype);
1121                         }
1122                         break;
1123                 case CTLENDVAR:
1124                         putc('}', fp);
1125                         break;
1126                 case CTLBACKQ:
1127                         putc('$', fp);
1128                         putc('(', fp);
1129                         shtree(bqlist->n, -1, NULL, fp);
1130                         putc(')', fp);
1131                         break;
1132                 default:
1133                         putc(*p, fp);
1134                         break;
1135                 }
1136         }
1137 }
1138
1139 static void
1140 shcmd(union node *cmd, FILE *fp)
1141 {
1142         union node *np;
1143         int first;
1144         const char *s;
1145         int dftfd;
1146
1147         first = 1;
1148         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1149                 if (!first)
1150                         putc(' ', fp);
1151                 sharg(np, fp);
1152                 first = 0;
1153         }
1154         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1155                 if (!first)
1156                         putc(' ', fp);
1157                 dftfd = 0;
1158                 switch (np->nfile.type) {
1159                 case NTO:      s = ">>"+1; dftfd = 1; break;
1160                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1161                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1162 #if BASH_REDIR_OUTPUT
1163                 case NTO2:
1164 #endif
1165                 case NTOFD:    s = ">&"; dftfd = 1; break;
1166                 case NFROM:    s = "<"; break;
1167                 case NFROMFD:  s = "<&"; break;
1168                 case NFROMTO:  s = "<>"; break;
1169                 default:       s = "*error*"; break;
1170                 }
1171                 if (np->nfile.fd != dftfd)
1172                         fprintf(fp, "%d", np->nfile.fd);
1173                 fputs(s, fp);
1174                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1175                         fprintf(fp, "%d", np->ndup.dupfd);
1176                 } else {
1177                         sharg(np->nfile.fname, fp);
1178                 }
1179                 first = 0;
1180         }
1181 }
1182
1183 static void
1184 shtree(union node *n, int ind, char *pfx, FILE *fp)
1185 {
1186         struct nodelist *lp;
1187         const char *s;
1188
1189         if (n == NULL)
1190                 return;
1191
1192         indent(ind, pfx, fp);
1193
1194         if (n == NODE_EOF) {
1195                 fputs("<EOF>", fp);
1196                 return;
1197         }
1198
1199         switch (n->type) {
1200         case NSEMI:
1201                 s = "; ";
1202                 goto binop;
1203         case NAND:
1204                 s = " && ";
1205                 goto binop;
1206         case NOR:
1207                 s = " || ";
1208  binop:
1209                 shtree(n->nbinary.ch1, ind, NULL, fp);
1210                 /* if (ind < 0) */
1211                         fputs(s, fp);
1212                 shtree(n->nbinary.ch2, ind, NULL, fp);
1213                 break;
1214         case NCMD:
1215                 shcmd(n, fp);
1216                 if (ind >= 0)
1217                         putc('\n', fp);
1218                 break;
1219         case NPIPE:
1220                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1221                         shtree(lp->n, 0, NULL, fp);
1222                         if (lp->next)
1223                                 fputs(" | ", fp);
1224                 }
1225                 if (n->npipe.pipe_backgnd)
1226                         fputs(" &", fp);
1227                 if (ind >= 0)
1228                         putc('\n', fp);
1229                 break;
1230         default:
1231                 fprintf(fp, "<node type %d>", n->type);
1232                 if (ind >= 0)
1233                         putc('\n', fp);
1234                 break;
1235         }
1236 }
1237
1238 static void
1239 showtree(union node *n)
1240 {
1241         trace_puts("showtree called\n");
1242         shtree(n, 1, NULL, stderr);
1243 }
1244
1245 #endif /* DEBUG */
1246
1247
1248 /* ============ Parser data */
1249
1250 /*
1251  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1252  */
1253 struct strlist {
1254         struct strlist *next;
1255         char *text;
1256 };
1257
1258 struct alias;
1259
1260 struct strpush {
1261         struct strpush *prev;   /* preceding string on stack */
1262         char *prev_string;
1263         int prev_left_in_line;
1264 #if ENABLE_ASH_ALIAS
1265         struct alias *ap;       /* if push was associated with an alias */
1266 #endif
1267         char *string;           /* remember the string since it may change */
1268
1269         /* Remember last two characters for pungetc. */
1270         int lastc[2];
1271
1272         /* Number of outstanding calls to pungetc. */
1273         int unget;
1274 };
1275
1276 /*
1277  * The parsefile structure pointed to by the global variable parsefile
1278  * contains information about the current file being read.
1279  */
1280 struct parsefile {
1281         struct parsefile *prev; /* preceding file on stack */
1282         int linno;              /* current line */
1283         int pf_fd;              /* file descriptor (or -1 if string) */
1284         int left_in_line;       /* number of chars left in this line */
1285         int left_in_buffer;     /* number of chars left in this buffer past the line */
1286         char *next_to_pgetc;    /* next char in buffer */
1287         char *buf;              /* input buffer */
1288         struct strpush *strpush; /* for pushing strings at this level */
1289         struct strpush basestrpush; /* so pushing one is fast */
1290
1291         /* Remember last two characters for pungetc. */
1292         int lastc[2];
1293
1294         /* Number of outstanding calls to pungetc. */
1295         int unget;
1296 };
1297
1298 static struct parsefile basepf;        /* top level input file */
1299 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1300 static char *commandname;              /* currently executing command */
1301
1302
1303 /* ============ Message printing */
1304
1305 static void
1306 ash_vmsg(const char *msg, va_list ap)
1307 {
1308         fprintf(stderr, "%s: ", arg0);
1309         if (commandname) {
1310                 if (strcmp(arg0, commandname))
1311                         fprintf(stderr, "%s: ", commandname);
1312                 if (!iflag || g_parsefile->pf_fd > 0)
1313                         fprintf(stderr, "line %d: ", errlinno);
1314         }
1315         vfprintf(stderr, msg, ap);
1316         newline_and_flush(stderr);
1317 }
1318
1319 /*
1320  * Exverror is called to raise the error exception.  If the second argument
1321  * is not NULL then error prints an error message using printf style
1322  * formatting.  It then raises the error exception.
1323  */
1324 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1325 static void
1326 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1327 {
1328 #if DEBUG
1329         if (msg) {
1330                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1331                 TRACEV((msg, ap));
1332         } else
1333                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1334         if (msg)
1335 #endif
1336                 ash_vmsg(msg, ap);
1337
1338         flush_stdout_stderr();
1339         raise_exception(cond);
1340         /* NOTREACHED */
1341 }
1342
1343 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1344 static void
1345 ash_msg_and_raise_error(const char *msg, ...)
1346 {
1347         va_list ap;
1348
1349         exitstatus = 2;
1350
1351         va_start(ap, msg);
1352         ash_vmsg_and_raise(EXERROR, msg, ap);
1353         /* NOTREACHED */
1354         va_end(ap);
1355 }
1356
1357 /*
1358  * 'fmt' must be a string literal.
1359  */
1360 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1361
1362 static void raise_error_syntax(const char *) NORETURN;
1363 static void
1364 raise_error_syntax(const char *msg)
1365 {
1366         errlinno = g_parsefile->linno;
1367         ash_msg_and_raise_error("syntax error: %s", msg);
1368         /* NOTREACHED */
1369 }
1370
1371 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1372 static void
1373 ash_msg_and_raise(int cond, const char *msg, ...)
1374 {
1375         va_list ap;
1376
1377         va_start(ap, msg);
1378         ash_vmsg_and_raise(cond, msg, ap);
1379         /* NOTREACHED */
1380         va_end(ap);
1381 }
1382
1383 /*
1384  * error/warning routines for external builtins
1385  */
1386 static void
1387 ash_msg(const char *fmt, ...)
1388 {
1389         va_list ap;
1390
1391         va_start(ap, fmt);
1392         ash_vmsg(fmt, ap);
1393         va_end(ap);
1394 }
1395
1396 /*
1397  * Return a string describing an error.  The returned string may be a
1398  * pointer to a static buffer that will be overwritten on the next call.
1399  * Action describes the operation that got the error.
1400  */
1401 static const char *
1402 errmsg(int e, const char *em)
1403 {
1404         if (e == ENOENT || e == ENOTDIR) {
1405                 return em;
1406         }
1407         return strerror(e);
1408 }
1409
1410
1411 /* ============ Memory allocation */
1412
1413 #if 0
1414 /* I consider these wrappers nearly useless:
1415  * ok, they return you to nearest exception handler, but
1416  * how much memory do you leak in the process, making
1417  * memory starvation worse?
1418  */
1419 static void *
1420 ckrealloc(void * p, size_t nbytes)
1421 {
1422         p = realloc(p, nbytes);
1423         if (!p)
1424                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1425         return p;
1426 }
1427
1428 static void *
1429 ckmalloc(size_t nbytes)
1430 {
1431         return ckrealloc(NULL, nbytes);
1432 }
1433
1434 static void *
1435 ckzalloc(size_t nbytes)
1436 {
1437         return memset(ckmalloc(nbytes), 0, nbytes);
1438 }
1439
1440 static char *
1441 ckstrdup(const char *s)
1442 {
1443         char *p = strdup(s);
1444         if (!p)
1445                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1446         return p;
1447 }
1448 #else
1449 /* Using bbox equivalents. They exit if out of memory */
1450 # define ckrealloc xrealloc
1451 # define ckmalloc  xmalloc
1452 # define ckzalloc  xzalloc
1453 # define ckstrdup  xstrdup
1454 #endif
1455
1456 /*
1457  * It appears that grabstackstr() will barf with such alignments
1458  * because stalloc() will return a string allocated in a new stackblock.
1459  */
1460 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1461 enum {
1462         /* Most machines require the value returned from malloc to be aligned
1463          * in some way.  The following macro will get this right
1464          * on many machines.  */
1465         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1466         /* Minimum size of a block */
1467         MINSIZE = SHELL_ALIGN(504),
1468 };
1469
1470 struct stack_block {
1471         struct stack_block *prev;
1472         char space[MINSIZE];
1473 };
1474
1475 struct stackmark {
1476         struct stack_block *stackp;
1477         char *stacknxt;
1478         size_t stacknleft;
1479 };
1480
1481
1482 struct globals_memstack {
1483         struct stack_block *g_stackp; // = &stackbase;
1484         char *g_stacknxt; // = stackbase.space;
1485         char *sstrend; // = stackbase.space + MINSIZE;
1486         size_t g_stacknleft; // = MINSIZE;
1487         struct stack_block stackbase;
1488 };
1489 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1490 #define G_memstack (*ash_ptr_to_globals_memstack)
1491 #define g_stackp     (G_memstack.g_stackp    )
1492 #define g_stacknxt   (G_memstack.g_stacknxt  )
1493 #define sstrend      (G_memstack.sstrend     )
1494 #define g_stacknleft (G_memstack.g_stacknleft)
1495 #define stackbase    (G_memstack.stackbase   )
1496 #define INIT_G_memstack() do { \
1497         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1498         barrier(); \
1499         g_stackp = &stackbase; \
1500         g_stacknxt = stackbase.space; \
1501         g_stacknleft = MINSIZE; \
1502         sstrend = stackbase.space + MINSIZE; \
1503 } while (0)
1504
1505
1506 #define stackblock()     ((void *)g_stacknxt)
1507 #define stackblocksize() g_stacknleft
1508
1509 /*
1510  * Parse trees for commands are allocated in lifo order, so we use a stack
1511  * to make this more efficient, and also to avoid all sorts of exception
1512  * handling code to handle interrupts in the middle of a parse.
1513  *
1514  * The size 504 was chosen because the Ultrix malloc handles that size
1515  * well.
1516  */
1517 static void *
1518 stalloc(size_t nbytes)
1519 {
1520         char *p;
1521         size_t aligned;
1522
1523         aligned = SHELL_ALIGN(nbytes);
1524         if (aligned > g_stacknleft) {
1525                 size_t len;
1526                 size_t blocksize;
1527                 struct stack_block *sp;
1528
1529                 blocksize = aligned;
1530                 if (blocksize < MINSIZE)
1531                         blocksize = MINSIZE;
1532                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1533                 if (len < blocksize)
1534                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1535                 INT_OFF;
1536                 sp = ckmalloc(len);
1537                 sp->prev = g_stackp;
1538                 g_stacknxt = sp->space;
1539                 g_stacknleft = blocksize;
1540                 sstrend = g_stacknxt + blocksize;
1541                 g_stackp = sp;
1542                 INT_ON;
1543         }
1544         p = g_stacknxt;
1545         g_stacknxt += aligned;
1546         g_stacknleft -= aligned;
1547         return p;
1548 }
1549
1550 static void *
1551 stzalloc(size_t nbytes)
1552 {
1553         return memset(stalloc(nbytes), 0, nbytes);
1554 }
1555
1556 static void
1557 stunalloc(void *p)
1558 {
1559 #if DEBUG
1560         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1561                 write(STDERR_FILENO, "stunalloc\n", 10);
1562                 abort();
1563         }
1564 #endif
1565         g_stacknleft += g_stacknxt - (char *)p;
1566         g_stacknxt = p;
1567 }
1568
1569 /*
1570  * Like strdup but works with the ash stack.
1571  */
1572 static char *
1573 sstrdup(const char *p)
1574 {
1575         size_t len = strlen(p) + 1;
1576         return memcpy(stalloc(len), p, len);
1577 }
1578
1579 static ALWAYS_INLINE void
1580 grabstackblock(size_t len)
1581 {
1582         stalloc(len);
1583 }
1584
1585 static void
1586 pushstackmark(struct stackmark *mark, size_t len)
1587 {
1588         mark->stackp = g_stackp;
1589         mark->stacknxt = g_stacknxt;
1590         mark->stacknleft = g_stacknleft;
1591         grabstackblock(len);
1592 }
1593
1594 static void
1595 setstackmark(struct stackmark *mark)
1596 {
1597         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1598 }
1599
1600 static void
1601 popstackmark(struct stackmark *mark)
1602 {
1603         struct stack_block *sp;
1604
1605         if (!mark->stackp)
1606                 return;
1607
1608         INT_OFF;
1609         while (g_stackp != mark->stackp) {
1610                 sp = g_stackp;
1611                 g_stackp = sp->prev;
1612                 free(sp);
1613         }
1614         g_stacknxt = mark->stacknxt;
1615         g_stacknleft = mark->stacknleft;
1616         sstrend = mark->stacknxt + mark->stacknleft;
1617         INT_ON;
1618 }
1619
1620 /*
1621  * When the parser reads in a string, it wants to stick the string on the
1622  * stack and only adjust the stack pointer when it knows how big the
1623  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1624  * of space on top of the stack and stackblocklen returns the length of
1625  * this block.  Growstackblock will grow this space by at least one byte,
1626  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1627  * part of the block that has been used.
1628  */
1629 static void
1630 growstackblock(void)
1631 {
1632         size_t newlen;
1633
1634         newlen = g_stacknleft * 2;
1635         if (newlen < g_stacknleft)
1636                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1637         if (newlen < 128)
1638                 newlen += 128;
1639
1640         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1641                 struct stack_block *sp;
1642                 struct stack_block *prevstackp;
1643                 size_t grosslen;
1644
1645                 INT_OFF;
1646                 sp = g_stackp;
1647                 prevstackp = sp->prev;
1648                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1649                 sp = ckrealloc(sp, grosslen);
1650                 sp->prev = prevstackp;
1651                 g_stackp = sp;
1652                 g_stacknxt = sp->space;
1653                 g_stacknleft = newlen;
1654                 sstrend = sp->space + newlen;
1655                 INT_ON;
1656         } else {
1657                 char *oldspace = g_stacknxt;
1658                 size_t oldlen = g_stacknleft;
1659                 char *p = stalloc(newlen);
1660
1661                 /* free the space we just allocated */
1662                 g_stacknxt = memcpy(p, oldspace, oldlen);
1663                 g_stacknleft += newlen;
1664         }
1665 }
1666
1667 /*
1668  * The following routines are somewhat easier to use than the above.
1669  * The user declares a variable of type STACKSTR, which may be declared
1670  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1671  * the user uses the macro STPUTC to add characters to the string.  In
1672  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1673  * grown as necessary.  When the user is done, she can just leave the
1674  * string there and refer to it using stackblock().  Or she can allocate
1675  * the space for it using grabstackstr().  If it is necessary to allow
1676  * someone else to use the stack temporarily and then continue to grow
1677  * the string, the user should use grabstack to allocate the space, and
1678  * then call ungrabstr(p) to return to the previous mode of operation.
1679  *
1680  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1681  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1682  * is space for at least one character.
1683  */
1684 static void *
1685 growstackstr(void)
1686 {
1687         size_t len = stackblocksize();
1688         growstackblock();
1689         return (char *)stackblock() + len;
1690 }
1691
1692 /*
1693  * Called from CHECKSTRSPACE.
1694  */
1695 static char *
1696 makestrspace(size_t newlen, char *p)
1697 {
1698         size_t len = p - g_stacknxt;
1699         size_t size;
1700
1701         for (;;) {
1702                 size_t nleft;
1703
1704                 size = stackblocksize();
1705                 nleft = size - len;
1706                 if (nleft >= newlen)
1707                         break;
1708                 growstackblock();
1709         }
1710         return (char *)stackblock() + len;
1711 }
1712
1713 static char *
1714 stack_nputstr(const char *s, size_t n, char *p)
1715 {
1716         p = makestrspace(n, p);
1717         p = (char *)mempcpy(p, s, n);
1718         return p;
1719 }
1720
1721 static char *
1722 stack_putstr(const char *s, char *p)
1723 {
1724         return stack_nputstr(s, strlen(s), p);
1725 }
1726
1727 static char *
1728 _STPUTC(int c, char *p)
1729 {
1730         if (p == sstrend)
1731                 p = growstackstr();
1732         *p++ = c;
1733         return p;
1734 }
1735
1736 #define STARTSTACKSTR(p)        ((p) = stackblock())
1737 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1738 #define CHECKSTRSPACE(n, p) do { \
1739         char *q = (p); \
1740         size_t l = (n); \
1741         size_t m = sstrend - q; \
1742         if (l > m) \
1743                 (p) = makestrspace(l, q); \
1744 } while (0)
1745 #define USTPUTC(c, p)           (*(p)++ = (c))
1746 #define STACKSTRNUL(p) do { \
1747         if ((p) == sstrend) \
1748                 (p) = growstackstr(); \
1749         *(p) = '\0'; \
1750 } while (0)
1751 #define STUNPUTC(p)             (--(p))
1752 #define STTOPC(p)               ((p)[-1])
1753 #define STADJUST(amount, p)     ((p) += (amount))
1754
1755 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1756 #define ungrabstackstr(s, p)    stunalloc(s)
1757 #define stackstrend()           ((void *)sstrend)
1758
1759
1760 /* ============ String helpers */
1761
1762 /*
1763  * prefix -- see if pfx is a prefix of string.
1764  */
1765 static char *
1766 prefix(const char *string, const char *pfx)
1767 {
1768         while (*pfx) {
1769                 if (*pfx++ != *string++)
1770                         return NULL;
1771         }
1772         return (char *) string;
1773 }
1774
1775 /*
1776  * Check for a valid number.  This should be elsewhere.
1777  */
1778 static int
1779 is_number(const char *p)
1780 {
1781         do {
1782                 if (!isdigit(*p))
1783                         return 0;
1784         } while (*++p != '\0');
1785         return 1;
1786 }
1787
1788 /*
1789  * Convert a string of digits to an integer, printing an error message on
1790  * failure.
1791  */
1792 static int
1793 number(const char *s)
1794 {
1795         if (!is_number(s))
1796                 ash_msg_and_raise_error(msg_illnum, s);
1797         return atoi(s);
1798 }
1799
1800 /*
1801  * Produce a single quoted string suitable as input to the shell.
1802  * The return string is allocated on the stack.
1803  */
1804 static char *
1805 single_quote(const char *s)
1806 {
1807         char *p;
1808
1809         STARTSTACKSTR(p);
1810
1811         do {
1812                 char *q;
1813                 size_t len;
1814
1815                 len = strchrnul(s, '\'') - s;
1816
1817                 q = p = makestrspace(len + 3, p);
1818
1819                 *q++ = '\'';
1820                 q = (char *)mempcpy(q, s, len);
1821                 *q++ = '\'';
1822                 s += len;
1823
1824                 STADJUST(q - p, p);
1825
1826                 if (*s != '\'')
1827                         break;
1828                 len = 0;
1829                 do len++; while (*++s == '\'');
1830
1831                 q = p = makestrspace(len + 3, p);
1832
1833                 *q++ = '"';
1834                 q = (char *)mempcpy(q, s - len, len);
1835                 *q++ = '"';
1836
1837                 STADJUST(q - p, p);
1838         } while (*s);
1839
1840         USTPUTC('\0', p);
1841
1842         return stackblock();
1843 }
1844
1845 /*
1846  * Produce a possibly single quoted string suitable as input to the shell.
1847  * If quoting was done, the return string is allocated on the stack,
1848  * otherwise a pointer to the original string is returned.
1849  */
1850 static const char *
1851 maybe_single_quote(const char *s)
1852 {
1853         const char *p = s;
1854
1855         while (*p) {
1856                 /* Assuming ACSII */
1857                 /* quote ctrl_chars space !"#$%&'()* */
1858                 if (*p < '+')
1859                         goto need_quoting;
1860                 /* quote ;<=>? */
1861                 if (*p >= ';' && *p <= '?')
1862                         goto need_quoting;
1863                 /* quote `[\ */
1864                 if (*p == '`')
1865                         goto need_quoting;
1866                 if (*p == '[')
1867                         goto need_quoting;
1868                 if (*p == '\\')
1869                         goto need_quoting;
1870                 /* quote {|}~ DEL and high bytes */
1871                 if (*p > 'z')
1872                         goto need_quoting;
1873                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1874                 /* TODO: maybe avoid quoting % */
1875                 p++;
1876         }
1877         return s;
1878
1879  need_quoting:
1880         return single_quote(s);
1881 }
1882
1883
1884 /* ============ nextopt */
1885
1886 static char **argptr;                  /* argument list for builtin commands */
1887 static char *optionarg;                /* set by nextopt (like getopt) */
1888 static char *optptr;                   /* used by nextopt */
1889
1890 /*
1891  * XXX - should get rid of. Have all builtins use getopt(3).
1892  * The library getopt must have the BSD extension static variable
1893  * "optreset", otherwise it can't be used within the shell safely.
1894  *
1895  * Standard option processing (a la getopt) for builtin routines.
1896  * The only argument that is passed to nextopt is the option string;
1897  * the other arguments are unnecessary. It returns the character,
1898  * or '\0' on end of input.
1899  */
1900 static int
1901 nextopt(const char *optstring)
1902 {
1903         char *p;
1904         const char *q;
1905         char c;
1906
1907         p = optptr;
1908         if (p == NULL || *p == '\0') {
1909                 /* We ate entire "-param", take next one */
1910                 p = *argptr;
1911                 if (p == NULL)
1912                         return '\0';
1913                 if (*p != '-')
1914                         return '\0';
1915                 if (*++p == '\0') /* just "-" ? */
1916                         return '\0';
1917                 argptr++;
1918                 if (LONE_DASH(p)) /* "--" ? */
1919                         return '\0';
1920                 /* p => next "-param" */
1921         }
1922         /* p => some option char in the middle of a "-param" */
1923         c = *p++;
1924         for (q = optstring; *q != c;) {
1925                 if (*q == '\0')
1926                         ash_msg_and_raise_error("illegal option -%c", c);
1927                 if (*++q == ':')
1928                         q++;
1929         }
1930         if (*++q == ':') {
1931                 if (*p == '\0') {
1932                         p = *argptr++;
1933                         if (p == NULL)
1934                                 ash_msg_and_raise_error("no arg for -%c option", c);
1935                 }
1936                 optionarg = p;
1937                 p = NULL;
1938         }
1939         optptr = p;
1940         return c;
1941 }
1942
1943
1944 /* ============ Shell variables */
1945
1946 struct shparam {
1947         int nparam;             /* # of positional parameters (without $0) */
1948 #if ENABLE_ASH_GETOPTS
1949         int optind;             /* next parameter to be processed by getopts */
1950         int optoff;             /* used by getopts */
1951 #endif
1952         unsigned char malloced; /* if parameter list dynamically allocated */
1953         char **p;               /* parameter list */
1954 };
1955
1956 /*
1957  * Free the list of positional parameters.
1958  */
1959 static void
1960 freeparam(volatile struct shparam *param)
1961 {
1962         if (param->malloced) {
1963                 char **ap, **ap1;
1964                 ap = ap1 = param->p;
1965                 while (*ap)
1966                         free(*ap++);
1967                 free(ap1);
1968         }
1969 }
1970
1971 #if ENABLE_ASH_GETOPTS
1972 static void FAST_FUNC getoptsreset(const char *value);
1973 #endif
1974
1975 struct var {
1976         struct var *next;               /* next entry in hash list */
1977         int flags;                      /* flags are defined above */
1978         const char *var_text;           /* name=value */
1979         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1980                                         /* the variable gets set/unset */
1981 };
1982
1983 struct localvar {
1984         struct localvar *next;          /* next local variable in list */
1985         struct var *vp;                 /* the variable that was made local */
1986         int flags;                      /* saved flags */
1987         const char *text;               /* saved text */
1988 };
1989
1990 /* flags */
1991 #define VEXPORT         0x01    /* variable is exported */
1992 #define VREADONLY       0x02    /* variable cannot be modified */
1993 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1994 #define VTEXTFIXED      0x08    /* text is statically allocated */
1995 #define VSTACK          0x10    /* text is allocated on the stack */
1996 #define VUNSET          0x20    /* the variable is not set */
1997 #define VNOFUNC         0x40    /* don't call the callback function */
1998 #define VNOSET          0x80    /* do not set variable - just readonly test */
1999 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2000 #if ENABLE_ASH_RANDOM_SUPPORT
2001 # define VDYNAMIC       0x200   /* dynamic variable */
2002 #else
2003 # define VDYNAMIC       0
2004 #endif
2005
2006
2007 /* Need to be before varinit_data[] */
2008 #if ENABLE_LOCALE_SUPPORT
2009 static void FAST_FUNC
2010 change_lc_all(const char *value)
2011 {
2012         if (value && *value != '\0')
2013                 setlocale(LC_ALL, value);
2014 }
2015 static void FAST_FUNC
2016 change_lc_ctype(const char *value)
2017 {
2018         if (value && *value != '\0')
2019                 setlocale(LC_CTYPE, value);
2020 }
2021 #endif
2022 #if ENABLE_ASH_MAIL
2023 static void chkmail(void);
2024 static void changemail(const char *var_value) FAST_FUNC;
2025 #else
2026 # define chkmail()  ((void)0)
2027 #endif
2028 static void changepath(const char *) FAST_FUNC;
2029 #if ENABLE_ASH_RANDOM_SUPPORT
2030 static void change_random(const char *) FAST_FUNC;
2031 #endif
2032
2033 static const struct {
2034         int flags;
2035         const char *var_text;
2036         void (*var_func)(const char *) FAST_FUNC;
2037 } varinit_data[] = {
2038         /*
2039          * Note: VEXPORT would not work correctly here for NOFORK applets:
2040          * some environment strings may be constant.
2041          */
2042         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2043 #if ENABLE_ASH_MAIL
2044         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2045         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2046 #endif
2047         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2048         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2049         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2050         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2051 #if ENABLE_ASH_GETOPTS
2052         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2053 #endif
2054         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2055 #if ENABLE_ASH_RANDOM_SUPPORT
2056         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2057 #endif
2058 #if ENABLE_LOCALE_SUPPORT
2059         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2060         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2061 #endif
2062 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2063         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2064 #endif
2065 };
2066
2067 struct redirtab;
2068
2069 struct globals_var {
2070         struct shparam shellparam;      /* $@ current positional parameters */
2071         struct redirtab *redirlist;
2072         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2073         struct var *vartab[VTABSIZE];
2074         struct var varinit[ARRAY_SIZE(varinit_data)];
2075         int lineno;
2076         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2077 };
2078 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2079 #define G_var (*ash_ptr_to_globals_var)
2080 #define shellparam    (G_var.shellparam   )
2081 //#define redirlist     (G_var.redirlist    )
2082 #define preverrout_fd (G_var.preverrout_fd)
2083 #define vartab        (G_var.vartab       )
2084 #define varinit       (G_var.varinit      )
2085 #define lineno        (G_var.lineno       )
2086 #define linenovar     (G_var.linenovar    )
2087 #define vifs      varinit[0]
2088 #if ENABLE_ASH_MAIL
2089 # define vmail    (&vifs)[1]
2090 # define vmpath   (&vmail)[1]
2091 # define vpath    (&vmpath)[1]
2092 #else
2093 # define vpath    (&vifs)[1]
2094 #endif
2095 #define vps1      (&vpath)[1]
2096 #define vps2      (&vps1)[1]
2097 #define vps4      (&vps2)[1]
2098 #if ENABLE_ASH_GETOPTS
2099 # define voptind  (&vps4)[1]
2100 # define vlineno  (&voptind)[1]
2101 # if ENABLE_ASH_RANDOM_SUPPORT
2102 #  define vrandom (&vlineno)[1]
2103 # endif
2104 #else
2105 # define vlineno  (&vps4)[1]
2106 # if ENABLE_ASH_RANDOM_SUPPORT
2107 #  define vrandom (&vlineno)[1]
2108 # endif
2109 #endif
2110 #define INIT_G_var() do { \
2111         unsigned i; \
2112         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2113         barrier(); \
2114         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2115                 varinit[i].flags    = varinit_data[i].flags; \
2116                 varinit[i].var_text = varinit_data[i].var_text; \
2117                 varinit[i].var_func = varinit_data[i].var_func; \
2118         } \
2119         strcpy(linenovar, "LINENO="); \
2120         vlineno.var_text = linenovar; \
2121 } while (0)
2122
2123 /*
2124  * The following macros access the values of the above variables.
2125  * They have to skip over the name.  They return the null string
2126  * for unset variables.
2127  */
2128 #define ifsval()        (vifs.var_text + 4)
2129 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2130 #if ENABLE_ASH_MAIL
2131 # define mailval()      (vmail.var_text + 5)
2132 # define mpathval()     (vmpath.var_text + 9)
2133 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2134 #endif
2135 #define pathval()       (vpath.var_text + 5)
2136 #define ps1val()        (vps1.var_text + 4)
2137 #define ps2val()        (vps2.var_text + 4)
2138 #define ps4val()        (vps4.var_text + 4)
2139 #if ENABLE_ASH_GETOPTS
2140 # define optindval()    (voptind.var_text + 7)
2141 #endif
2142
2143 #if ENABLE_ASH_GETOPTS
2144 static void FAST_FUNC
2145 getoptsreset(const char *value)
2146 {
2147         shellparam.optind = 1;
2148         if (is_number(value))
2149                 shellparam.optind = number(value) ?: 1;
2150         shellparam.optoff = -1;
2151 }
2152 #endif
2153
2154 /*
2155  * Compares two strings up to the first = or '\0'.  The first
2156  * string must be terminated by '='; the second may be terminated by
2157  * either '=' or '\0'.
2158  */
2159 static int
2160 varcmp(const char *p, const char *q)
2161 {
2162         int c, d;
2163
2164         while ((c = *p) == (d = *q)) {
2165                 if (c == '\0' || c == '=')
2166                         goto out;
2167                 p++;
2168                 q++;
2169         }
2170         if (c == '=')
2171                 c = '\0';
2172         if (d == '=')
2173                 d = '\0';
2174  out:
2175         return c - d;
2176 }
2177
2178 /*
2179  * Find the appropriate entry in the hash table from the name.
2180  */
2181 static struct var **
2182 hashvar(const char *p)
2183 {
2184         unsigned hashval;
2185
2186         hashval = ((unsigned char) *p) << 4;
2187         while (*p && *p != '=')
2188                 hashval += (unsigned char) *p++;
2189         return &vartab[hashval % VTABSIZE];
2190 }
2191
2192 static int
2193 vpcmp(const void *a, const void *b)
2194 {
2195         return varcmp(*(const char **)a, *(const char **)b);
2196 }
2197
2198 /*
2199  * This routine initializes the builtin variables.
2200  */
2201 static void
2202 initvar(void)
2203 {
2204         struct var *vp;
2205         struct var *end;
2206         struct var **vpp;
2207
2208         /*
2209          * PS1 depends on uid
2210          */
2211 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2212         vps1.var_text = "PS1=\\w \\$ ";
2213 #else
2214         if (!geteuid())
2215                 vps1.var_text = "PS1=# ";
2216 #endif
2217         vp = varinit;
2218         end = vp + ARRAY_SIZE(varinit);
2219         do {
2220                 vpp = hashvar(vp->var_text);
2221                 vp->next = *vpp;
2222                 *vpp = vp;
2223         } while (++vp < end);
2224 }
2225
2226 static struct var **
2227 findvar(struct var **vpp, const char *name)
2228 {
2229         for (; *vpp; vpp = &(*vpp)->next) {
2230                 if (varcmp((*vpp)->var_text, name) == 0) {
2231                         break;
2232                 }
2233         }
2234         return vpp;
2235 }
2236
2237 /*
2238  * Find the value of a variable.  Returns NULL if not set.
2239  */
2240 static const char* FAST_FUNC
2241 lookupvar(const char *name)
2242 {
2243         struct var *v;
2244
2245         v = *findvar(hashvar(name), name);
2246         if (v) {
2247 #if ENABLE_ASH_RANDOM_SUPPORT
2248         /*
2249          * Dynamic variables are implemented roughly the same way they are
2250          * in bash. Namely, they're "special" so long as they aren't unset.
2251          * As soon as they're unset, they're no longer dynamic, and dynamic
2252          * lookup will no longer happen at that point. -- PFM.
2253          */
2254                 if (v->flags & VDYNAMIC)
2255                         v->var_func(NULL);
2256 #endif
2257                 if (!(v->flags & VUNSET)) {
2258                         if (v == &vlineno && v->var_text == linenovar) {
2259                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2260                         }
2261                         return var_end(v->var_text);
2262                 }
2263         }
2264         return NULL;
2265 }
2266
2267 #if ENABLE_UNICODE_SUPPORT
2268 static void
2269 reinit_unicode_for_ash(void)
2270 {
2271         /* Unicode support should be activated even if LANG is set
2272          * _during_ shell execution, not only if it was set when
2273          * shell was started. Therefore, re-check LANG every time:
2274          */
2275         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2276          || ENABLE_UNICODE_USING_LOCALE
2277         ) {
2278                 const char *s = lookupvar("LC_ALL");
2279                 if (!s) s = lookupvar("LC_CTYPE");
2280                 if (!s) s = lookupvar("LANG");
2281                 reinit_unicode(s);
2282         }
2283 }
2284 #else
2285 # define reinit_unicode_for_ash() ((void)0)
2286 #endif
2287
2288 /*
2289  * Search the environment of a builtin command.
2290  */
2291 static ALWAYS_INLINE const char *
2292 bltinlookup(const char *name)
2293 {
2294         return lookupvar(name);
2295 }
2296
2297 /*
2298  * Same as setvar except that the variable and value are passed in
2299  * the first argument as name=value.  Since the first argument will
2300  * be actually stored in the table, it should not be a string that
2301  * will go away.
2302  * Called with interrupts off.
2303  */
2304 static struct var *
2305 setvareq(char *s, int flags)
2306 {
2307         struct var *vp, **vpp;
2308
2309         vpp = hashvar(s);
2310         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2311         vpp = findvar(vpp, s);
2312         vp = *vpp;
2313         if (vp) {
2314                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2315                         const char *n;
2316
2317                         if (flags & VNOSAVE)
2318                                 free(s);
2319                         n = vp->var_text;
2320                         exitstatus = 1;
2321                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2322                 }
2323
2324                 if (flags & VNOSET)
2325                         goto out;
2326
2327                 if (vp->var_func && !(flags & VNOFUNC))
2328                         vp->var_func(var_end(s));
2329
2330                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2331                         free((char*)vp->var_text);
2332
2333                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2334                         *vpp = vp->next;
2335                         free(vp);
2336  out_free:
2337                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2338                                 free(s);
2339                         goto out;
2340                 }
2341
2342                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2343         } else {
2344                 /* variable s is not found */
2345                 if (flags & VNOSET)
2346                         goto out;
2347                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2348                         goto out_free;
2349                 vp = ckzalloc(sizeof(*vp));
2350                 vp->next = *vpp;
2351                 /*vp->func = NULL; - ckzalloc did it */
2352                 *vpp = vp;
2353         }
2354         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2355                 s = ckstrdup(s);
2356         vp->var_text = s;
2357         vp->flags = flags;
2358
2359  out:
2360         return vp;
2361 }
2362
2363 /*
2364  * Set the value of a variable.  The flags argument is ored with the
2365  * flags of the variable.  If val is NULL, the variable is unset.
2366  */
2367 static struct var *
2368 setvar(const char *name, const char *val, int flags)
2369 {
2370         const char *q;
2371         char *p;
2372         char *nameeq;
2373         size_t namelen;
2374         size_t vallen;
2375         struct var *vp;
2376
2377         q = endofname(name);
2378         p = strchrnul(q, '=');
2379         namelen = p - name;
2380         if (!namelen || p != q)
2381                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2382         vallen = 0;
2383         if (val == NULL) {
2384                 flags |= VUNSET;
2385         } else {
2386                 vallen = strlen(val);
2387         }
2388
2389         INT_OFF;
2390         nameeq = ckmalloc(namelen + vallen + 2);
2391         p = mempcpy(nameeq, name, namelen);
2392         if (val) {
2393                 *p++ = '=';
2394                 p = mempcpy(p, val, vallen);
2395         }
2396         *p = '\0';
2397         vp = setvareq(nameeq, flags | VNOSAVE);
2398         INT_ON;
2399
2400         return vp;
2401 }
2402
2403 static void FAST_FUNC
2404 setvar0(const char *name, const char *val)
2405 {
2406         setvar(name, val, 0);
2407 }
2408
2409 /*
2410  * Unset the specified variable.
2411  */
2412 static void
2413 unsetvar(const char *s)
2414 {
2415         setvar(s, NULL, 0);
2416 }
2417
2418 /*
2419  * Process a linked list of variable assignments.
2420  */
2421 static void
2422 listsetvar(struct strlist *list_set_var, int flags)
2423 {
2424         struct strlist *lp = list_set_var;
2425
2426         if (!lp)
2427                 return;
2428         INT_OFF;
2429         do {
2430                 setvareq(lp->text, flags);
2431                 lp = lp->next;
2432         } while (lp);
2433         INT_ON;
2434 }
2435
2436 /*
2437  * Generate a list of variables satisfying the given conditions.
2438  */
2439 #if !ENABLE_FEATURE_SH_NOFORK
2440 # define listvars(on, off, lp, end) listvars(on, off, end)
2441 #endif
2442 static char **
2443 listvars(int on, int off, struct strlist *lp, char ***end)
2444 {
2445         struct var **vpp;
2446         struct var *vp;
2447         char **ep;
2448         int mask;
2449
2450         STARTSTACKSTR(ep);
2451         vpp = vartab;
2452         mask = on | off;
2453         do {
2454                 for (vp = *vpp; vp; vp = vp->next) {
2455                         if ((vp->flags & mask) == on) {
2456 #if ENABLE_FEATURE_SH_NOFORK
2457                                 /* If variable with the same name is both
2458                                  * exported and temporarily set for a command:
2459                                  *  export ZVAR=5
2460                                  *  ZVAR=6 printenv
2461                                  * then "ZVAR=6" will be both in vartab and
2462                                  * lp lists. Do not pass it twice to printenv.
2463                                  */
2464                                 struct strlist *lp1 = lp;
2465                                 while (lp1) {
2466                                         if (strcmp(lp1->text, vp->var_text) == 0)
2467                                                 goto skip;
2468                                         lp1 = lp1->next;
2469                                 }
2470 #endif
2471                                 if (ep == stackstrend())
2472                                         ep = growstackstr();
2473                                 *ep++ = (char*)vp->var_text;
2474 #if ENABLE_FEATURE_SH_NOFORK
2475  skip: ;
2476 #endif
2477                         }
2478                 }
2479         } while (++vpp < vartab + VTABSIZE);
2480
2481 #if ENABLE_FEATURE_SH_NOFORK
2482         while (lp) {
2483                 if (ep == stackstrend())
2484                         ep = growstackstr();
2485                 *ep++ = lp->text;
2486                 lp = lp->next;
2487         }
2488 #endif
2489
2490         if (ep == stackstrend())
2491                 ep = growstackstr();
2492         if (end)
2493                 *end = ep;
2494         *ep++ = NULL;
2495         return grabstackstr(ep);
2496 }
2497
2498
2499 /* ============ Path search helper
2500  *
2501  * The variable path (passed by reference) should be set to the start
2502  * of the path before the first call; path_advance will update
2503  * this value as it proceeds.  Successive calls to path_advance will return
2504  * the possible path expansions in sequence.  If an option (indicated by
2505  * a percent sign) appears in the path entry then the global variable
2506  * pathopt will be set to point to it; otherwise pathopt will be set to
2507  * NULL.
2508  */
2509 static const char *pathopt;     /* set by path_advance */
2510
2511 static char *
2512 path_advance(const char **path, const char *name)
2513 {
2514         const char *p;
2515         char *q;
2516         const char *start;
2517         size_t len;
2518
2519         if (*path == NULL)
2520                 return NULL;
2521         start = *path;
2522         for (p = start; *p && *p != ':' && *p != '%'; p++)
2523                 continue;
2524         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2525         while (stackblocksize() < len)
2526                 growstackblock();
2527         q = stackblock();
2528         if (p != start) {
2529                 q = mempcpy(q, start, p - start);
2530                 *q++ = '/';
2531         }
2532         strcpy(q, name);
2533         pathopt = NULL;
2534         if (*p == '%') {
2535                 pathopt = ++p;
2536                 while (*p && *p != ':')
2537                         p++;
2538         }
2539         if (*p == ':')
2540                 *path = p + 1;
2541         else
2542                 *path = NULL;
2543         return stalloc(len);
2544 }
2545
2546
2547 /* ============ Prompt */
2548
2549 static smallint doprompt;                   /* if set, prompt the user */
2550 static smallint needprompt;                 /* true if interactive and at start of line */
2551
2552 #if ENABLE_FEATURE_EDITING
2553 static line_input_t *line_input_state;
2554 static const char *cmdedit_prompt;
2555 static void
2556 putprompt(const char *s)
2557 {
2558         if (ENABLE_ASH_EXPAND_PRMT) {
2559                 free((char*)cmdedit_prompt);
2560                 cmdedit_prompt = ckstrdup(s);
2561                 return;
2562         }
2563         cmdedit_prompt = s;
2564 }
2565 #else
2566 static void
2567 putprompt(const char *s)
2568 {
2569         out2str(s);
2570 }
2571 #endif
2572
2573 /* expandstr() needs parsing machinery, so it is far away ahead... */
2574 static const char *expandstr(const char *ps, int syntax_type);
2575 /* Values for syntax param */
2576 #define BASESYNTAX 0    /* not in quotes */
2577 #define DQSYNTAX   1    /* in double quotes */
2578 #define SQSYNTAX   2    /* in single quotes */
2579 #define ARISYNTAX  3    /* in arithmetic */
2580 #if ENABLE_ASH_EXPAND_PRMT
2581 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2582 #endif
2583 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2584
2585 /*
2586  * called by editline -- any expansions to the prompt should be added here.
2587  */
2588 static void
2589 setprompt_if(smallint do_set, int whichprompt)
2590 {
2591         const char *prompt;
2592         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2593
2594         if (!do_set)
2595                 return;
2596
2597         needprompt = 0;
2598
2599         switch (whichprompt) {
2600         case 1:
2601                 prompt = ps1val();
2602                 break;
2603         case 2:
2604                 prompt = ps2val();
2605                 break;
2606         default:                        /* 0 */
2607                 prompt = nullstr;
2608         }
2609 #if ENABLE_ASH_EXPAND_PRMT
2610         pushstackmark(&smark, stackblocksize());
2611         putprompt(expandstr(prompt, PSSYNTAX));
2612         popstackmark(&smark);
2613 #else
2614         putprompt(prompt);
2615 #endif
2616 }
2617
2618
2619 /* ============ The cd and pwd commands */
2620
2621 #define CD_PHYSICAL 1
2622 #define CD_PRINT 2
2623
2624 static int
2625 cdopt(void)
2626 {
2627         int flags = 0;
2628         int i, j;
2629
2630         j = 'L';
2631         while ((i = nextopt("LP")) != '\0') {
2632                 if (i != j) {
2633                         flags ^= CD_PHYSICAL;
2634                         j = i;
2635                 }
2636         }
2637
2638         return flags;
2639 }
2640
2641 /*
2642  * Update curdir (the name of the current directory) in response to a
2643  * cd command.
2644  */
2645 static const char *
2646 updatepwd(const char *dir)
2647 {
2648         char *new;
2649         char *p;
2650         char *cdcomppath;
2651         const char *lim;
2652
2653         cdcomppath = sstrdup(dir);
2654         STARTSTACKSTR(new);
2655         if (*dir != '/') {
2656                 if (curdir == nullstr)
2657                         return 0;
2658                 new = stack_putstr(curdir, new);
2659         }
2660         new = makestrspace(strlen(dir) + 2, new);
2661         lim = (char *)stackblock() + 1;
2662         if (*dir != '/') {
2663                 if (new[-1] != '/')
2664                         USTPUTC('/', new);
2665                 if (new > lim && *lim == '/')
2666                         lim++;
2667         } else {
2668                 USTPUTC('/', new);
2669                 cdcomppath++;
2670                 if (dir[1] == '/' && dir[2] != '/') {
2671                         USTPUTC('/', new);
2672                         cdcomppath++;
2673                         lim++;
2674                 }
2675         }
2676         p = strtok(cdcomppath, "/");
2677         while (p) {
2678                 switch (*p) {
2679                 case '.':
2680                         if (p[1] == '.' && p[2] == '\0') {
2681                                 while (new > lim) {
2682                                         STUNPUTC(new);
2683                                         if (new[-1] == '/')
2684                                                 break;
2685                                 }
2686                                 break;
2687                         }
2688                         if (p[1] == '\0')
2689                                 break;
2690                         /* fall through */
2691                 default:
2692                         new = stack_putstr(p, new);
2693                         USTPUTC('/', new);
2694                 }
2695                 p = strtok(NULL, "/");
2696         }
2697         if (new > lim)
2698                 STUNPUTC(new);
2699         *new = 0;
2700         return stackblock();
2701 }
2702
2703 /*
2704  * Find out what the current directory is. If we already know the current
2705  * directory, this routine returns immediately.
2706  */
2707 static char *
2708 getpwd(void)
2709 {
2710         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2711         return dir ? dir : nullstr;
2712 }
2713
2714 static void
2715 setpwd(const char *val, int setold)
2716 {
2717         char *oldcur, *dir;
2718
2719         oldcur = dir = curdir;
2720
2721         if (setold) {
2722                 setvar("OLDPWD", oldcur, VEXPORT);
2723         }
2724         INT_OFF;
2725         if (physdir != nullstr) {
2726                 if (physdir != oldcur)
2727                         free(physdir);
2728                 physdir = nullstr;
2729         }
2730         if (oldcur == val || !val) {
2731                 char *s = getpwd();
2732                 physdir = s;
2733                 if (!val)
2734                         dir = s;
2735         } else
2736                 dir = ckstrdup(val);
2737         if (oldcur != dir && oldcur != nullstr) {
2738                 free(oldcur);
2739         }
2740         curdir = dir;
2741         INT_ON;
2742         setvar("PWD", dir, VEXPORT);
2743 }
2744
2745 static void hashcd(void);
2746
2747 /*
2748  * Actually do the chdir.  We also call hashcd to let other routines
2749  * know that the current directory has changed.
2750  */
2751 static int
2752 docd(const char *dest, int flags)
2753 {
2754         const char *dir = NULL;
2755         int err;
2756
2757         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2758
2759         INT_OFF;
2760         if (!(flags & CD_PHYSICAL)) {
2761                 dir = updatepwd(dest);
2762                 if (dir)
2763                         dest = dir;
2764         }
2765         err = chdir(dest);
2766         if (err)
2767                 goto out;
2768         setpwd(dir, 1);
2769         hashcd();
2770  out:
2771         INT_ON;
2772         return err;
2773 }
2774
2775 static int FAST_FUNC
2776 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2777 {
2778         const char *dest;
2779         const char *path;
2780         const char *p;
2781         char c;
2782         struct stat statb;
2783         int flags;
2784
2785         flags = cdopt();
2786         dest = *argptr;
2787         if (!dest)
2788                 dest = bltinlookup("HOME");
2789         else if (LONE_DASH(dest)) {
2790                 dest = bltinlookup("OLDPWD");
2791                 flags |= CD_PRINT;
2792         }
2793         if (!dest)
2794                 dest = nullstr;
2795         if (*dest == '/')
2796                 goto step6;
2797         if (*dest == '.') {
2798                 c = dest[1];
2799  dotdot:
2800                 switch (c) {
2801                 case '\0':
2802                 case '/':
2803                         goto step6;
2804                 case '.':
2805                         c = dest[2];
2806                         if (c != '.')
2807                                 goto dotdot;
2808                 }
2809         }
2810         if (!*dest)
2811                 dest = ".";
2812         path = bltinlookup("CDPATH");
2813         while (path) {
2814                 c = *path;
2815                 p = path_advance(&path, dest);
2816                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2817                         if (c && c != ':')
2818                                 flags |= CD_PRINT;
2819  docd:
2820                         if (!docd(p, flags))
2821                                 goto out;
2822                         goto err;
2823                 }
2824         }
2825
2826  step6:
2827         p = dest;
2828         goto docd;
2829
2830  err:
2831         ash_msg_and_raise_perror("can't cd to %s", dest);
2832         /* NOTREACHED */
2833  out:
2834         if (flags & CD_PRINT)
2835                 out1fmt("%s\n", curdir);
2836         return 0;
2837 }
2838
2839 static int FAST_FUNC
2840 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2841 {
2842         int flags;
2843         const char *dir = curdir;
2844
2845         flags = cdopt();
2846         if (flags) {
2847                 if (physdir == nullstr)
2848                         setpwd(dir, 0);
2849                 dir = physdir;
2850         }
2851         out1fmt("%s\n", dir);
2852         return 0;
2853 }
2854
2855
2856 /* ============ ... */
2857
2858
2859 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2860
2861 /* Syntax classes */
2862 #define CWORD     0             /* character is nothing special */
2863 #define CNL       1             /* newline character */
2864 #define CBACK     2             /* a backslash character */
2865 #define CSQUOTE   3             /* single quote */
2866 #define CDQUOTE   4             /* double quote */
2867 #define CENDQUOTE 5             /* a terminating quote */
2868 #define CBQUOTE   6             /* backwards single quote */
2869 #define CVAR      7             /* a dollar sign */
2870 #define CENDVAR   8             /* a '}' character */
2871 #define CLP       9             /* a left paren in arithmetic */
2872 #define CRP      10             /* a right paren in arithmetic */
2873 #define CENDFILE 11             /* end of file */
2874 #define CCTL     12             /* like CWORD, except it must be escaped */
2875 #define CSPCL    13             /* these terminate a word */
2876 #define CIGN     14             /* character should be ignored */
2877
2878 #define PEOF     256
2879 #if ENABLE_ASH_ALIAS
2880 # define PEOA    257
2881 #endif
2882
2883 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2884
2885 #if ENABLE_FEATURE_SH_MATH
2886 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2887 #else
2888 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2889 #endif
2890 static const uint16_t S_I_T[] ALIGN2 = {
2891 #if ENABLE_ASH_ALIAS
2892         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2893 #endif
2894         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2895         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2896         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2897         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2898         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2899         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2900         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2901         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2902         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2903         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2904         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2905 #if !USE_SIT_FUNCTION
2906         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2907         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2908         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2909 #endif
2910 #undef SIT_ITEM
2911 };
2912 /* Constants below must match table above */
2913 enum {
2914 #if ENABLE_ASH_ALIAS
2915         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2916 #endif
2917         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2918         CNL_CNL_CNL_CNL                    , /*  2 */
2919         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2920         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2921         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2922         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2923         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2924         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2925         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2926         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2927         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2928         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2929         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2930         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2931 };
2932
2933 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2934  * caller must ensure proper cast on it if c is *char_ptr!
2935  */
2936 #if USE_SIT_FUNCTION
2937
2938 static int
2939 SIT(int c, int syntax)
2940 {
2941         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2942         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2943         /*
2944          * This causes '/' to be prepended with CTLESC in dquoted string,
2945          * making "./file"* treated incorrectly because we feed
2946          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2947          * The "homegrown" glob implementation is okay with that,
2948          * but glibc one isn't. With '/' always treated as CWORD,
2949          * both work fine.
2950          */
2951 # if ENABLE_ASH_ALIAS
2952         static const uint8_t syntax_index_table[] ALIGN1 = {
2953                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2954                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2955                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2956                 11, 3                           /* "}~" */
2957         };
2958 # else
2959         static const uint8_t syntax_index_table[] ALIGN1 = {
2960                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2961                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2962                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2963                 10, 2                           /* "}~" */
2964         };
2965 # endif
2966         const char *s;
2967         int indx;
2968
2969         if (c == PEOF)
2970                 return CENDFILE;
2971 # if ENABLE_ASH_ALIAS
2972         if (c == PEOA)
2973                 indx = 0;
2974         else
2975 # endif
2976         {
2977                 /* Cast is purely for paranoia here,
2978                  * just in case someone passed signed char to us */
2979                 if ((unsigned char)c >= CTL_FIRST
2980                  && (unsigned char)c <= CTL_LAST
2981                 ) {
2982                         return CCTL;
2983                 }
2984                 s = strchrnul(spec_symbls, c);
2985                 if (*s == '\0')
2986                         return CWORD;
2987                 indx = syntax_index_table[s - spec_symbls];
2988         }
2989         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2990 }
2991
2992 #else   /* !USE_SIT_FUNCTION */
2993
2994 static const uint8_t syntax_index_table[] ALIGN1 = {
2995         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2996         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2997         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2998         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2999         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3000         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3001         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3002         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3003         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3004         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3005         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3006         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3007         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3008         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3009         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3010         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3011         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3012         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3013         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3014         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3015         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3016         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3017         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3018         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3019         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3020         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3021         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3022         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3023         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3024         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3025         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3026         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3027         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3028         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3029         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3030         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3031         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3032         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3033         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3034         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3035         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3036         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3037         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3038         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3039         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3040         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3041         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3042         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3043 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3044         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3045         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3046         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3047         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3048         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3049         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3050         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3051         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3052         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3053         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3054         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3055         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3056         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3057         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3058         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3059         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3060         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3061         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3062         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3063         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3064         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3065         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3066         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3067         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3068         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3069         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3070         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3071         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3072         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3073         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3074         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3075         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3076         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3077         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3078         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3079         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3080         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3081         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3082         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3083         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3084         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3085         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3086         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3087         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3088         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3089         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3090         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3091         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3092         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3093         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3094         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3095         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3096         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3097         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3098         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3099         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3100         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3101         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3102         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3103         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3104         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3105         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3106         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3107         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3108         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3109         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3110         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3111         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3112         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3113         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3114         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3115         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3116         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3117         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3118         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3119         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3120         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3121         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3122         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3123         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3124         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3125         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3126         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3127         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3128         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3129         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3130         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3131         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3132         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3133         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3134         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3253         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3254 # if ENABLE_ASH_ALIAS
3255         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3256 # endif
3257 };
3258
3259 #if 1
3260 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3261 #else /* debug version, caught one signed char bug */
3262 # define SIT(c, syntax) \
3263         ({ \
3264                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3265                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3266                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3267                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3268                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3269         })
3270 #endif
3271
3272 #endif  /* !USE_SIT_FUNCTION */
3273
3274
3275 /* ============ Alias handling */
3276
3277 #if ENABLE_ASH_ALIAS
3278
3279 #define ALIASINUSE 1
3280 #define ALIASDEAD  2
3281
3282 struct alias {
3283         struct alias *next;
3284         char *name;
3285         char *val;
3286         int flag;
3287 };
3288
3289
3290 static struct alias **atab; // [ATABSIZE];
3291 #define INIT_G_alias() do { \
3292         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3293 } while (0)
3294
3295
3296 static struct alias **
3297 __lookupalias(const char *name)
3298 {
3299         unsigned int hashval;
3300         struct alias **app;
3301         const char *p;
3302         unsigned int ch;
3303
3304         p = name;
3305
3306         ch = (unsigned char)*p;
3307         hashval = ch << 4;
3308         while (ch) {
3309                 hashval += ch;
3310                 ch = (unsigned char)*++p;
3311         }
3312         app = &atab[hashval % ATABSIZE];
3313
3314         for (; *app; app = &(*app)->next) {
3315                 if (strcmp(name, (*app)->name) == 0) {
3316                         break;
3317                 }
3318         }
3319
3320         return app;
3321 }
3322
3323 static struct alias *
3324 lookupalias(const char *name, int check)
3325 {
3326         struct alias *ap = *__lookupalias(name);
3327
3328         if (check && ap && (ap->flag & ALIASINUSE))
3329                 return NULL;
3330         return ap;
3331 }
3332
3333 static struct alias *
3334 freealias(struct alias *ap)
3335 {
3336         struct alias *next;
3337
3338         if (ap->flag & ALIASINUSE) {
3339                 ap->flag |= ALIASDEAD;
3340                 return ap;
3341         }
3342
3343         next = ap->next;
3344         free(ap->name);
3345         free(ap->val);
3346         free(ap);
3347         return next;
3348 }
3349
3350 static void
3351 setalias(const char *name, const char *val)
3352 {
3353         struct alias *ap, **app;
3354
3355         app = __lookupalias(name);
3356         ap = *app;
3357         INT_OFF;
3358         if (ap) {
3359                 if (!(ap->flag & ALIASINUSE)) {
3360                         free(ap->val);
3361                 }
3362                 ap->val = ckstrdup(val);
3363                 ap->flag &= ~ALIASDEAD;
3364         } else {
3365                 /* not found */
3366                 ap = ckzalloc(sizeof(struct alias));
3367                 ap->name = ckstrdup(name);
3368                 ap->val = ckstrdup(val);
3369                 /*ap->flag = 0; - ckzalloc did it */
3370                 /*ap->next = NULL;*/
3371                 *app = ap;
3372         }
3373         INT_ON;
3374 }
3375
3376 static int
3377 unalias(const char *name)
3378 {
3379         struct alias **app;
3380
3381         app = __lookupalias(name);
3382
3383         if (*app) {
3384                 INT_OFF;
3385                 *app = freealias(*app);
3386                 INT_ON;
3387                 return 0;
3388         }
3389
3390         return 1;
3391 }
3392
3393 static void
3394 rmaliases(void)
3395 {
3396         struct alias *ap, **app;
3397         int i;
3398
3399         INT_OFF;
3400         for (i = 0; i < ATABSIZE; i++) {
3401                 app = &atab[i];
3402                 for (ap = *app; ap; ap = *app) {
3403                         *app = freealias(*app);
3404                         if (ap == *app) {
3405                                 app = &ap->next;
3406                         }
3407                 }
3408         }
3409         INT_ON;
3410 }
3411
3412 static void
3413 printalias(const struct alias *ap)
3414 {
3415         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3416 }
3417
3418 /*
3419  * TODO - sort output
3420  */
3421 static int FAST_FUNC
3422 aliascmd(int argc UNUSED_PARAM, char **argv)
3423 {
3424         char *n, *v;
3425         int ret = 0;
3426         struct alias *ap;
3427
3428         if (!argv[1]) {
3429                 int i;
3430
3431                 for (i = 0; i < ATABSIZE; i++) {
3432                         for (ap = atab[i]; ap; ap = ap->next) {
3433                                 printalias(ap);
3434                         }
3435                 }
3436                 return 0;
3437         }
3438         while ((n = *++argv) != NULL) {
3439                 v = strchr(n+1, '=');
3440                 if (v == NULL) { /* n+1: funny ksh stuff */
3441                         ap = *__lookupalias(n);
3442                         if (ap == NULL) {
3443                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3444                                 ret = 1;
3445                         } else
3446                                 printalias(ap);
3447                 } else {
3448                         *v++ = '\0';
3449                         setalias(n, v);
3450                 }
3451         }
3452
3453         return ret;
3454 }
3455
3456 static int FAST_FUNC
3457 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3458 {
3459         int i;
3460
3461         while (nextopt("a") != '\0') {
3462                 rmaliases();
3463                 return 0;
3464         }
3465         for (i = 0; *argptr; argptr++) {
3466                 if (unalias(*argptr)) {
3467                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3468                         i = 1;
3469                 }
3470         }
3471
3472         return i;
3473 }
3474
3475 #endif /* ASH_ALIAS */
3476
3477
3478 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3479 #define FORK_FG    0
3480 #define FORK_BG    1
3481 #define FORK_NOJOB 2
3482
3483 /* mode flags for showjob(s) */
3484 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3485 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3486 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3487 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3488
3489 /*
3490  * A job structure contains information about a job.  A job is either a
3491  * single process or a set of processes contained in a pipeline.  In the
3492  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3493  * array of pids.
3494  */
3495 struct procstat {
3496         pid_t   ps_pid;         /* process id */
3497         int     ps_status;      /* last process status from wait() */
3498         char    *ps_cmd;        /* text of command being run */
3499 };
3500
3501 struct job {
3502         struct procstat ps0;    /* status of process */
3503         struct procstat *ps;    /* status or processes when more than one */
3504 #if JOBS
3505         int stopstatus;         /* status of a stopped job */
3506 #endif
3507         unsigned nprocs;        /* number of processes */
3508
3509 #define JOBRUNNING      0       /* at least one proc running */
3510 #define JOBSTOPPED      1       /* all procs are stopped */
3511 #define JOBDONE         2       /* all procs are completed */
3512         unsigned
3513                 state: 8,
3514 #if JOBS
3515                 sigint: 1,      /* job was killed by SIGINT */
3516                 jobctl: 1,      /* job running under job control */
3517 #endif
3518                 waited: 1,      /* true if this entry has been waited for */
3519                 used: 1,        /* true if this entry is in used */
3520                 changed: 1;     /* true if status has changed */
3521         struct job *prev_job;   /* previous job */
3522 };
3523
3524 static struct job *makejob(/*union node *,*/ int);
3525 static int forkshell(struct job *, union node *, int);
3526 static int waitforjob(struct job *);
3527
3528 #if !JOBS
3529 enum { doing_jobctl = 0 };
3530 #define setjobctl(on) do {} while (0)
3531 #else
3532 static smallint doing_jobctl; //references:8
3533 static void setjobctl(int);
3534 #endif
3535
3536 /*
3537  * Ignore a signal.
3538  */
3539 static void
3540 ignoresig(int signo)
3541 {
3542         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3543         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3544                 /* No, need to do it */
3545                 signal(signo, SIG_IGN);
3546         }
3547         sigmode[signo - 1] = S_HARD_IGN;
3548 }
3549
3550 /*
3551  * Only one usage site - in setsignal()
3552  */
3553 static void
3554 signal_handler(int signo)
3555 {
3556         if (signo == SIGCHLD) {
3557                 got_sigchld = 1;
3558                 if (!trap[SIGCHLD])
3559                         return;
3560         }
3561
3562         gotsig[signo - 1] = 1;
3563         pending_sig = signo;
3564
3565         if (signo == SIGINT && !trap[SIGINT]) {
3566                 if (!suppress_int) {
3567                         pending_sig = 0;
3568                         raise_interrupt(); /* does not return */
3569                 }
3570                 pending_int = 1;
3571         }
3572 }
3573
3574 /*
3575  * Set the signal handler for the specified signal.  The routine figures
3576  * out what it should be set to.
3577  */
3578 static void
3579 setsignal(int signo)
3580 {
3581         char *t;
3582         char cur_act, new_act;
3583         struct sigaction act;
3584
3585         t = trap[signo];
3586         new_act = S_DFL;
3587         if (t != NULL) { /* trap for this sig is set */
3588                 new_act = S_CATCH;
3589                 if (t[0] == '\0') /* trap is "": ignore this sig */
3590                         new_act = S_IGN;
3591         }
3592
3593         if (rootshell && new_act == S_DFL) {
3594                 switch (signo) {
3595                 case SIGINT:
3596                         if (iflag || minusc || sflag == 0)
3597                                 new_act = S_CATCH;
3598                         break;
3599                 case SIGQUIT:
3600 #if DEBUG
3601                         if (debug)
3602                                 break;
3603 #endif
3604                         /* man bash:
3605                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3606                          * commands run by bash have signal handlers
3607                          * set to the values inherited by the shell
3608                          * from its parent". */
3609                         new_act = S_IGN;
3610                         break;
3611                 case SIGTERM:
3612                         if (iflag)
3613                                 new_act = S_IGN;
3614                         break;
3615 #if JOBS
3616                 case SIGTSTP:
3617                 case SIGTTOU:
3618                         if (mflag)
3619                                 new_act = S_IGN;
3620                         break;
3621 #endif
3622                 }
3623         }
3624         /* if !rootshell, we reset SIGQUIT to DFL,
3625          * whereas we have to restore it to what shell got on entry.
3626          * This is handled by the fact that if signal was IGNored on entry,
3627          * then cur_act is S_HARD_IGN and we never change its sigaction
3628          * (see code below).
3629          */
3630
3631         if (signo == SIGCHLD)
3632                 new_act = S_CATCH;
3633
3634         t = &sigmode[signo - 1];
3635         cur_act = *t;
3636         if (cur_act == 0) {
3637                 /* current setting is not yet known */
3638                 if (sigaction(signo, NULL, &act)) {
3639                         /* pretend it worked; maybe we should give a warning,
3640                          * but other shells don't. We don't alter sigmode,
3641                          * so we retry every time.
3642                          * btw, in Linux it never fails. --vda */
3643                         return;
3644                 }
3645                 if (act.sa_handler == SIG_IGN) {
3646                         cur_act = S_HARD_IGN;
3647                         if (mflag
3648                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3649                         ) {
3650                                 cur_act = S_IGN;   /* don't hard ignore these */
3651                         }
3652                 }
3653                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3654                         /* installing SIG_DFL over SIG_DFL is a no-op */
3655                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3656                         *t = S_DFL;
3657                         return;
3658                 }
3659         }
3660         if (cur_act == S_HARD_IGN || cur_act == new_act)
3661                 return;
3662
3663         *t = new_act;
3664
3665         act.sa_handler = SIG_DFL;
3666         switch (new_act) {
3667         case S_CATCH:
3668                 act.sa_handler = signal_handler;
3669                 break;
3670         case S_IGN:
3671                 act.sa_handler = SIG_IGN;
3672                 break;
3673         }
3674         /* flags and mask matter only if !DFL and !IGN, but we do it
3675          * for all cases for more deterministic behavior:
3676          */
3677         act.sa_flags = 0; //TODO: why not SA_RESTART?
3678         sigfillset(&act.sa_mask);
3679
3680         sigaction_set(signo, &act);
3681 }
3682
3683 /* mode flags for set_curjob */
3684 #define CUR_DELETE 2
3685 #define CUR_RUNNING 1
3686 #define CUR_STOPPED 0
3687
3688 #if JOBS
3689 /* pgrp of shell on invocation */
3690 static int initialpgrp; //references:2
3691 static int ttyfd = -1; //5
3692 #endif
3693 /* array of jobs */
3694 static struct job *jobtab; //5
3695 /* size of array */
3696 static unsigned njobs; //4
3697 /* current job */
3698 static struct job *curjob; //lots
3699 /* number of presumed living untracked jobs */
3700 static int jobless; //4
3701
3702 #if 0
3703 /* Bash has a feature: it restores termios after a successful wait for
3704  * a foreground job which had at least one stopped or sigkilled member.
3705  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3706  * properly restoring tty state. Should we do this too?
3707  * A reproducer: ^Z an interactive python:
3708  *
3709  * # python
3710  * Python 2.7.12 (...)
3711  * >>> ^Z
3712  *      { python leaves tty in -icanon -echo state. We do survive that... }
3713  *  [1]+  Stopped                    python
3714  *      { ...however, next program (python #2) does not survive it well: }
3715  * # python
3716  * Python 2.7.12 (...)
3717  * >>> Traceback (most recent call last):
3718  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3719  *   File "<stdin>", line 1, in <module>
3720  * NameError: name 'qwerty' is not defined
3721  *
3722  * The implementation below is modeled on bash code and seems to work.
3723  * However, I'm not sure we should do this. For one: what if I'd fg
3724  * the stopped python instead? It'll be confused by "restored" tty state.
3725  */
3726 static struct termios shell_tty_info;
3727 static void
3728 get_tty_state(void)
3729 {
3730         if (rootshell && ttyfd >= 0)
3731                 tcgetattr(ttyfd, &shell_tty_info);
3732 }
3733 static void
3734 set_tty_state(void)
3735 {
3736         /* if (rootshell) - caller ensures this */
3737         if (ttyfd >= 0)
3738                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3739 }
3740 static int
3741 job_signal_status(struct job *jp)
3742 {
3743         int status;
3744         unsigned i;
3745         struct procstat *ps = jp->ps;
3746         for (i = 0; i < jp->nprocs; i++) {
3747                 status = ps[i].ps_status;
3748                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3749                         return status;
3750         }
3751         return 0;
3752 }
3753 static void
3754 restore_tty_if_stopped_or_signaled(struct job *jp)
3755 {
3756 //TODO: check what happens if we come from waitforjob() in expbackq()
3757         if (rootshell) {
3758                 int s = job_signal_status(jp);
3759                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3760                         set_tty_state();
3761         }
3762 }
3763 #else
3764 # define get_tty_state() ((void)0)
3765 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3766 #endif
3767
3768 static void
3769 set_curjob(struct job *jp, unsigned mode)
3770 {
3771         struct job *jp1;
3772         struct job **jpp, **curp;
3773
3774         /* first remove from list */
3775         jpp = curp = &curjob;
3776         while (1) {
3777                 jp1 = *jpp;
3778                 if (jp1 == jp)
3779                         break;
3780                 jpp = &jp1->prev_job;
3781         }
3782         *jpp = jp1->prev_job;
3783
3784         /* Then re-insert in correct position */
3785         jpp = curp;
3786         switch (mode) {
3787         default:
3788 #if DEBUG
3789                 abort();
3790 #endif
3791         case CUR_DELETE:
3792                 /* job being deleted */
3793                 break;
3794         case CUR_RUNNING:
3795                 /* newly created job or backgrounded job,
3796                  * put after all stopped jobs.
3797                  */
3798                 while (1) {
3799                         jp1 = *jpp;
3800 #if JOBS
3801                         if (!jp1 || jp1->state != JOBSTOPPED)
3802 #endif
3803                                 break;
3804                         jpp = &jp1->prev_job;
3805                 }
3806                 /* FALLTHROUGH */
3807 #if JOBS
3808         case CUR_STOPPED:
3809 #endif
3810                 /* newly stopped job - becomes curjob */
3811                 jp->prev_job = *jpp;
3812                 *jpp = jp;
3813                 break;
3814         }
3815 }
3816
3817 #if JOBS || DEBUG
3818 static int
3819 jobno(const struct job *jp)
3820 {
3821         return jp - jobtab + 1;
3822 }
3823 #endif
3824
3825 /*
3826  * Convert a job name to a job structure.
3827  */
3828 #if !JOBS
3829 #define getjob(name, getctl) getjob(name)
3830 #endif
3831 static struct job *
3832 getjob(const char *name, int getctl)
3833 {
3834         struct job *jp;
3835         struct job *found;
3836         const char *err_msg = "%s: no such job";
3837         unsigned num;
3838         int c;
3839         const char *p;
3840         char *(*match)(const char *, const char *);
3841
3842         jp = curjob;
3843         p = name;
3844         if (!p)
3845                 goto currentjob;
3846
3847         if (*p != '%')
3848                 goto err;
3849
3850         c = *++p;
3851         if (!c)
3852                 goto currentjob;
3853
3854         if (!p[1]) {
3855                 if (c == '+' || c == '%') {
3856  currentjob:
3857                         err_msg = "No current job";
3858                         goto check;
3859                 }
3860                 if (c == '-') {
3861                         if (jp)
3862                                 jp = jp->prev_job;
3863                         err_msg = "No previous job";
3864  check:
3865                         if (!jp)
3866                                 goto err;
3867                         goto gotit;
3868                 }
3869         }
3870
3871         if (is_number(p)) {
3872                 num = atoi(p);
3873                 if (num > 0 && num <= njobs) {
3874                         jp = jobtab + num - 1;
3875                         if (jp->used)
3876                                 goto gotit;
3877                         goto err;
3878                 }
3879         }
3880
3881         match = prefix;
3882         if (*p == '?') {
3883                 match = strstr;
3884                 p++;
3885         }
3886
3887         found = NULL;
3888         while (jp) {
3889                 if (match(jp->ps[0].ps_cmd, p)) {
3890                         if (found)
3891                                 goto err;
3892                         found = jp;
3893                         err_msg = "%s: ambiguous";
3894                 }
3895                 jp = jp->prev_job;
3896         }
3897         if (!found)
3898                 goto err;
3899         jp = found;
3900
3901  gotit:
3902 #if JOBS
3903         err_msg = "job %s not created under job control";
3904         if (getctl && jp->jobctl == 0)
3905                 goto err;
3906 #endif
3907         return jp;
3908  err:
3909         ash_msg_and_raise_error(err_msg, name);
3910 }
3911
3912 /*
3913  * Mark a job structure as unused.
3914  */
3915 static void
3916 freejob(struct job *jp)
3917 {
3918         struct procstat *ps;
3919         int i;
3920
3921         INT_OFF;
3922         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3923                 if (ps->ps_cmd != nullstr)
3924                         free(ps->ps_cmd);
3925         }
3926         if (jp->ps != &jp->ps0)
3927                 free(jp->ps);
3928         jp->used = 0;
3929         set_curjob(jp, CUR_DELETE);
3930         INT_ON;
3931 }
3932
3933 #if JOBS
3934 static void
3935 xtcsetpgrp(int fd, pid_t pgrp)
3936 {
3937         if (tcsetpgrp(fd, pgrp))
3938                 ash_msg_and_raise_perror("can't set tty process group");
3939 }
3940
3941 /*
3942  * Turn job control on and off.
3943  *
3944  * Note:  This code assumes that the third arg to ioctl is a character
3945  * pointer, which is true on Berkeley systems but not System V.  Since
3946  * System V doesn't have job control yet, this isn't a problem now.
3947  *
3948  * Called with interrupts off.
3949  */
3950 static void
3951 setjobctl(int on)
3952 {
3953         int fd;
3954         int pgrp;
3955
3956         if (on == doing_jobctl || rootshell == 0)
3957                 return;
3958         if (on) {
3959                 int ofd;
3960                 ofd = fd = open(_PATH_TTY, O_RDWR);
3961                 if (fd < 0) {
3962         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3963          * That sometimes helps to acquire controlling tty.
3964          * Obviously, a workaround for bugs when someone
3965          * failed to provide a controlling tty to bash! :) */
3966                         fd = 2;
3967                         while (!isatty(fd))
3968                                 if (--fd < 0)
3969                                         goto out;
3970                 }
3971                 /* fd is a tty at this point */
3972                 fd = fcntl(fd, F_DUPFD, 10);
3973                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3974                         close(ofd);
3975                 if (fd < 0)
3976                         goto out; /* F_DUPFD failed */
3977                 close_on_exec_on(fd);
3978                 while (1) { /* while we are in the background */
3979                         pgrp = tcgetpgrp(fd);
3980                         if (pgrp < 0) {
3981  out:
3982                                 ash_msg("can't access tty; job control turned off");
3983                                 mflag = on = 0;
3984                                 goto close;
3985                         }
3986                         if (pgrp == getpgrp())
3987                                 break;
3988                         killpg(0, SIGTTIN);
3989                 }
3990                 initialpgrp = pgrp;
3991
3992                 setsignal(SIGTSTP);
3993                 setsignal(SIGTTOU);
3994                 setsignal(SIGTTIN);
3995                 pgrp = rootpid;
3996                 setpgid(0, pgrp);
3997                 xtcsetpgrp(fd, pgrp);
3998         } else {
3999                 /* turning job control off */
4000                 fd = ttyfd;
4001                 pgrp = initialpgrp;
4002                 /* was xtcsetpgrp, but this can make exiting ash
4003                  * loop forever if pty is already deleted */
4004                 tcsetpgrp(fd, pgrp);
4005                 setpgid(0, pgrp);
4006                 setsignal(SIGTSTP);
4007                 setsignal(SIGTTOU);
4008                 setsignal(SIGTTIN);
4009  close:
4010                 if (fd >= 0)
4011                         close(fd);
4012                 fd = -1;
4013         }
4014         ttyfd = fd;
4015         doing_jobctl = on;
4016 }
4017
4018 static int FAST_FUNC
4019 killcmd(int argc, char **argv)
4020 {
4021         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4022                 int i = 1;
4023                 do {
4024                         if (argv[i][0] == '%') {
4025                                 /*
4026                                  * "kill %N" - job kill
4027                                  * Converting to pgrp / pid kill
4028                                  */
4029                                 struct job *jp;
4030                                 char *dst;
4031                                 int j, n;
4032
4033                                 jp = getjob(argv[i], 0);
4034                                 /*
4035                                  * In jobs started under job control, we signal
4036                                  * entire process group by kill -PGRP_ID.
4037                                  * This happens, f.e., in interactive shell.
4038                                  *
4039                                  * Otherwise, we signal each child via
4040                                  * kill PID1 PID2 PID3.
4041                                  * Testcases:
4042                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4043                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4044                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4045                                  */
4046                                 n = jp->nprocs; /* can't be 0 (I hope) */
4047                                 if (jp->jobctl)
4048                                         n = 1;
4049                                 dst = alloca(n * sizeof(int)*4);
4050                                 argv[i] = dst;
4051                                 for (j = 0; j < n; j++) {
4052                                         struct procstat *ps = &jp->ps[j];
4053                                         /* Skip non-running and not-stopped members
4054                                          * (i.e. dead members) of the job
4055                                          */
4056                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4057                                                 continue;
4058                                         /*
4059                                          * kill_main has matching code to expect
4060                                          * leading space. Needed to not confuse
4061                                          * negative pids with "kill -SIGNAL_NO" syntax
4062                                          */
4063                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4064                                 }
4065                                 *dst = '\0';
4066                         }
4067                 } while (argv[++i]);
4068         }
4069         return kill_main(argc, argv);
4070 }
4071
4072 static void
4073 showpipe(struct job *jp /*, FILE *out*/)
4074 {
4075         struct procstat *ps;
4076         struct procstat *psend;
4077
4078         psend = jp->ps + jp->nprocs;
4079         for (ps = jp->ps + 1; ps < psend; ps++)
4080                 printf(" | %s", ps->ps_cmd);
4081         newline_and_flush(stdout);
4082         flush_stdout_stderr();
4083 }
4084
4085
4086 static int
4087 restartjob(struct job *jp, int mode)
4088 {
4089         struct procstat *ps;
4090         int i;
4091         int status;
4092         pid_t pgid;
4093
4094         INT_OFF;
4095         if (jp->state == JOBDONE)
4096                 goto out;
4097         jp->state = JOBRUNNING;
4098         pgid = jp->ps[0].ps_pid;
4099         if (mode == FORK_FG) {
4100                 get_tty_state();
4101                 xtcsetpgrp(ttyfd, pgid);
4102         }
4103         killpg(pgid, SIGCONT);
4104         ps = jp->ps;
4105         i = jp->nprocs;
4106         do {
4107                 if (WIFSTOPPED(ps->ps_status)) {
4108                         ps->ps_status = -1;
4109                 }
4110                 ps++;
4111         } while (--i);
4112  out:
4113         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4114         INT_ON;
4115         return status;
4116 }
4117
4118 static int FAST_FUNC
4119 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4120 {
4121         struct job *jp;
4122         int mode;
4123         int retval;
4124
4125         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4126         nextopt(nullstr);
4127         argv = argptr;
4128         do {
4129                 jp = getjob(*argv, 1);
4130                 if (mode == FORK_BG) {
4131                         set_curjob(jp, CUR_RUNNING);
4132                         printf("[%d] ", jobno(jp));
4133                 }
4134                 out1str(jp->ps[0].ps_cmd);
4135                 showpipe(jp /*, stdout*/);
4136                 retval = restartjob(jp, mode);
4137         } while (*argv && *++argv);
4138         return retval;
4139 }
4140 #endif
4141
4142 static int
4143 sprint_status48(char *s, int status, int sigonly)
4144 {
4145         int col;
4146         int st;
4147
4148         col = 0;
4149         if (!WIFEXITED(status)) {
4150 #if JOBS
4151                 if (WIFSTOPPED(status))
4152                         st = WSTOPSIG(status);
4153                 else
4154 #endif
4155                         st = WTERMSIG(status);
4156                 if (sigonly) {
4157                         if (st == SIGINT || st == SIGPIPE)
4158                                 goto out;
4159 #if JOBS
4160                         if (WIFSTOPPED(status))
4161                                 goto out;
4162 #endif
4163                 }
4164                 st &= 0x7f;
4165 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4166                 col = fmtstr(s, 32, strsignal(st));
4167                 if (WCOREDUMP(status)) {
4168                         strcpy(s + col, " (core dumped)");
4169                         col += sizeof(" (core dumped)")-1;
4170                 }
4171         } else if (!sigonly) {
4172                 st = WEXITSTATUS(status);
4173                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4174         }
4175  out:
4176         return col;
4177 }
4178
4179 static int
4180 wait_block_or_sig(int *status)
4181 {
4182         int pid;
4183
4184         do {
4185                 sigset_t mask;
4186
4187                 /* Poll all children for changes in their state */
4188                 got_sigchld = 0;
4189                 /* if job control is active, accept stopped processes too */
4190                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4191                 if (pid != 0)
4192                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4193
4194                 /* Children exist, but none are ready. Sleep until interesting signal */
4195 #if 1
4196                 sigfillset(&mask);
4197                 sigprocmask(SIG_SETMASK, &mask, &mask);
4198                 while (!got_sigchld && !pending_sig)
4199                         sigsuspend(&mask);
4200                 sigprocmask(SIG_SETMASK, &mask, NULL);
4201 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4202                 while (!got_sigchld && !pending_sig)
4203                         pause();
4204 #endif
4205
4206                 /* If it was SIGCHLD, poll children again */
4207         } while (got_sigchld);
4208
4209         return pid;
4210 }
4211
4212 #define DOWAIT_NONBLOCK 0
4213 #define DOWAIT_BLOCK    1
4214 #define DOWAIT_BLOCK_OR_SIG 2
4215
4216 static int
4217 dowait(int block, struct job *job)
4218 {
4219         int pid;
4220         int status;
4221         struct job *jp;
4222         struct job *thisjob = NULL;
4223
4224         TRACE(("dowait(0x%x) called\n", block));
4225
4226         /* It's wrong to call waitpid() outside of INT_OFF region:
4227          * signal can arrive just after syscall return and handler can
4228          * longjmp away, losing stop/exit notification processing.
4229          * Thus, for "jobs" builtin, and for waiting for a fg job,
4230          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4231          *
4232          * However, for "wait" builtin it is wrong to simply call waitpid()
4233          * in INT_OFF region: "wait" needs to wait for any running job
4234          * to change state, but should exit on any trap too.
4235          * In INT_OFF region, a signal just before syscall entry can set
4236          * pending_sig variables, but we can't check them, and we would
4237          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4238          *
4239          * Because of this, we run inside INT_OFF, but use a special routine
4240          * which combines waitpid() and sigsuspend().
4241          * This is the reason why we need to have a handler for SIGCHLD:
4242          * SIG_DFL handler does not wake sigsuspend().
4243          */
4244         INT_OFF;
4245         if (block == DOWAIT_BLOCK_OR_SIG) {
4246                 pid = wait_block_or_sig(&status);
4247         } else {
4248                 int wait_flags = 0;
4249                 if (block == DOWAIT_NONBLOCK)
4250                         wait_flags = WNOHANG;
4251                 /* if job control is active, accept stopped processes too */
4252                 if (doing_jobctl)
4253                         wait_flags |= WUNTRACED;
4254                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4255                 pid = waitpid(-1, &status, wait_flags);
4256         }
4257         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4258                                 pid, status, errno, strerror(errno)));
4259         if (pid <= 0)
4260                 goto out;
4261
4262         thisjob = NULL;
4263         for (jp = curjob; jp; jp = jp->prev_job) {
4264                 int jobstate;
4265                 struct procstat *ps;
4266                 struct procstat *psend;
4267                 if (jp->state == JOBDONE)
4268                         continue;
4269                 jobstate = JOBDONE;
4270                 ps = jp->ps;
4271                 psend = ps + jp->nprocs;
4272                 do {
4273                         if (ps->ps_pid == pid) {
4274                                 TRACE(("Job %d: changing status of proc %d "
4275                                         "from 0x%x to 0x%x\n",
4276                                         jobno(jp), pid, ps->ps_status, status));
4277                                 ps->ps_status = status;
4278                                 thisjob = jp;
4279                         }
4280                         if (ps->ps_status == -1)
4281                                 jobstate = JOBRUNNING;
4282 #if JOBS
4283                         if (jobstate == JOBRUNNING)
4284                                 continue;
4285                         if (WIFSTOPPED(ps->ps_status)) {
4286                                 jp->stopstatus = ps->ps_status;
4287                                 jobstate = JOBSTOPPED;
4288                         }
4289 #endif
4290                 } while (++ps < psend);
4291                 if (!thisjob)
4292                         continue;
4293
4294                 /* Found the job where one of its processes changed its state.
4295                  * Is there at least one live and running process in this job? */
4296                 if (jobstate != JOBRUNNING) {
4297                         /* No. All live processes in the job are stopped
4298                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4299                          */
4300                         thisjob->changed = 1;
4301                         if (thisjob->state != jobstate) {
4302                                 TRACE(("Job %d: changing state from %d to %d\n",
4303                                         jobno(thisjob), thisjob->state, jobstate));
4304                                 thisjob->state = jobstate;
4305 #if JOBS
4306                                 if (jobstate == JOBSTOPPED)
4307                                         set_curjob(thisjob, CUR_STOPPED);
4308 #endif
4309                         }
4310                 }
4311                 goto out;
4312         }
4313         /* The process wasn't found in job list */
4314 #if JOBS
4315         if (!WIFSTOPPED(status))
4316                 jobless--;
4317 #endif
4318  out:
4319         INT_ON;
4320
4321         if (thisjob && thisjob == job) {
4322                 char s[48 + 1];
4323                 int len;
4324
4325                 len = sprint_status48(s, status, 1);
4326                 if (len) {
4327                         s[len] = '\n';
4328                         s[len + 1] = '\0';
4329                         out2str(s);
4330                 }
4331         }
4332         return pid;
4333 }
4334
4335 #if JOBS
4336 static void
4337 showjob(struct job *jp, int mode)
4338 {
4339         struct procstat *ps;
4340         struct procstat *psend;
4341         int col;
4342         int indent_col;
4343         char s[16 + 16 + 48];
4344         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4345
4346         ps = jp->ps;
4347
4348         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4349                 /* just output process (group) id of pipeline */
4350                 fprintf(out, "%d\n", ps->ps_pid);
4351                 return;
4352         }
4353
4354         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4355         indent_col = col;
4356
4357         if (jp == curjob)
4358                 s[col - 3] = '+';
4359         else if (curjob && jp == curjob->prev_job)
4360                 s[col - 3] = '-';
4361
4362         if (mode & SHOW_PIDS)
4363                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4364
4365         psend = ps + jp->nprocs;
4366
4367         if (jp->state == JOBRUNNING) {
4368                 strcpy(s + col, "Running");
4369                 col += sizeof("Running") - 1;
4370         } else {
4371                 int status = psend[-1].ps_status;
4372                 if (jp->state == JOBSTOPPED)
4373                         status = jp->stopstatus;
4374                 col += sprint_status48(s + col, status, 0);
4375         }
4376         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4377
4378         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4379          * or prints several "PID             | <cmdN>" lines,
4380          * depending on SHOW_PIDS bit.
4381          * We do not print status of individual processes
4382          * between PID and <cmdN>. bash does it, but not very well:
4383          * first line shows overall job status, not process status,
4384          * making it impossible to know 1st process status.
4385          */
4386         goto start;
4387         do {
4388                 /* for each process */
4389                 s[0] = '\0';
4390                 col = 33;
4391                 if (mode & SHOW_PIDS)
4392                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4393  start:
4394                 fprintf(out, "%s%*c%s%s",
4395                                 s,
4396                                 33 - col >= 0 ? 33 - col : 0, ' ',
4397                                 ps == jp->ps ? "" : "| ",
4398                                 ps->ps_cmd
4399                 );
4400         } while (++ps != psend);
4401         newline_and_flush(out);
4402
4403         jp->changed = 0;
4404
4405         if (jp->state == JOBDONE) {
4406                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4407                 freejob(jp);
4408         }
4409 }
4410
4411 /*
4412  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4413  * statuses have changed since the last call to showjobs.
4414  */
4415 static void
4416 showjobs(int mode)
4417 {
4418         struct job *jp;
4419
4420         TRACE(("showjobs(0x%x) called\n", mode));
4421
4422         /* Handle all finished jobs */
4423         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4424                 continue;
4425
4426         for (jp = curjob; jp; jp = jp->prev_job) {
4427                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4428                         showjob(jp, mode);
4429                 }
4430         }
4431 }
4432
4433 static int FAST_FUNC
4434 jobscmd(int argc UNUSED_PARAM, char **argv)
4435 {
4436         int mode, m;
4437
4438         mode = 0;
4439         while ((m = nextopt("lp")) != '\0') {
4440                 if (m == 'l')
4441                         mode |= SHOW_PIDS;
4442                 else
4443                         mode |= SHOW_ONLY_PGID;
4444         }
4445
4446         argv = argptr;
4447         if (*argv) {
4448                 do
4449                         showjob(getjob(*argv, 0), mode);
4450                 while (*++argv);
4451         } else {
4452                 showjobs(mode);
4453         }
4454
4455         return 0;
4456 }
4457 #endif /* JOBS */
4458
4459 /* Called only on finished or stopped jobs (no members are running) */
4460 static int
4461 getstatus(struct job *job)
4462 {
4463         int status;
4464         int retval;
4465         struct procstat *ps;
4466
4467         /* Fetch last member's status */
4468         ps = job->ps + job->nprocs - 1;
4469         status = ps->ps_status;
4470         if (pipefail) {
4471                 /* "set -o pipefail" mode: use last _nonzero_ status */
4472                 while (status == 0 && --ps >= job->ps)
4473                         status = ps->ps_status;
4474         }
4475
4476         retval = WEXITSTATUS(status);
4477         if (!WIFEXITED(status)) {
4478 #if JOBS
4479                 retval = WSTOPSIG(status);
4480                 if (!WIFSTOPPED(status))
4481 #endif
4482                 {
4483                         /* XXX: limits number of signals */
4484                         retval = WTERMSIG(status);
4485 #if JOBS
4486                         if (retval == SIGINT)
4487                                 job->sigint = 1;
4488 #endif
4489                 }
4490                 retval += 128;
4491         }
4492         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4493                 jobno(job), job->nprocs, status, retval));
4494         return retval;
4495 }
4496
4497 static int FAST_FUNC
4498 waitcmd(int argc UNUSED_PARAM, char **argv)
4499 {
4500         struct job *job;
4501         int retval;
4502         struct job *jp;
4503
4504         nextopt(nullstr);
4505         retval = 0;
4506
4507         argv = argptr;
4508         if (!*argv) {
4509                 /* wait for all jobs */
4510                 for (;;) {
4511                         jp = curjob;
4512                         while (1) {
4513                                 if (!jp) /* no running procs */
4514                                         goto ret;
4515                                 if (jp->state == JOBRUNNING)
4516                                         break;
4517                                 jp->waited = 1;
4518                                 jp = jp->prev_job;
4519                         }
4520         /* man bash:
4521          * "When bash is waiting for an asynchronous command via
4522          * the wait builtin, the reception of a signal for which a trap
4523          * has been set will cause the wait builtin to return immediately
4524          * with an exit status greater than 128, immediately after which
4525          * the trap is executed."
4526          */
4527                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4528         /* if child sends us a signal *and immediately exits*,
4529          * dowait() returns pid > 0. Check this case,
4530          * not "if (dowait() < 0)"!
4531          */
4532                         if (pending_sig)
4533                                 goto sigout;
4534                 }
4535         }
4536
4537         retval = 127;
4538         do {
4539                 if (**argv != '%') {
4540                         pid_t pid = number(*argv);
4541                         job = curjob;
4542                         while (1) {
4543                                 if (!job)
4544                                         goto repeat;
4545                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4546                                         break;
4547                                 job = job->prev_job;
4548                         }
4549                 } else {
4550                         job = getjob(*argv, 0);
4551                 }
4552                 /* loop until process terminated or stopped */
4553                 while (job->state == JOBRUNNING) {
4554                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4555                         if (pending_sig)
4556                                 goto sigout;
4557                 }
4558                 job->waited = 1;
4559                 retval = getstatus(job);
4560  repeat: ;
4561         } while (*++argv);
4562
4563  ret:
4564         return retval;
4565  sigout:
4566         retval = 128 + pending_sig;
4567         return retval;
4568 }
4569
4570 static struct job *
4571 growjobtab(void)
4572 {
4573         size_t len;
4574         ptrdiff_t offset;
4575         struct job *jp, *jq;
4576
4577         len = njobs * sizeof(*jp);
4578         jq = jobtab;
4579         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4580
4581         offset = (char *)jp - (char *)jq;
4582         if (offset) {
4583                 /* Relocate pointers */
4584                 size_t l = len;
4585
4586                 jq = (struct job *)((char *)jq + l);
4587                 while (l) {
4588                         l -= sizeof(*jp);
4589                         jq--;
4590 #define joff(p) ((struct job *)((char *)(p) + l))
4591 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4592                         if (joff(jp)->ps == &jq->ps0)
4593                                 jmove(joff(jp)->ps);
4594                         if (joff(jp)->prev_job)
4595                                 jmove(joff(jp)->prev_job);
4596                 }
4597                 if (curjob)
4598                         jmove(curjob);
4599 #undef joff
4600 #undef jmove
4601         }
4602
4603         njobs += 4;
4604         jobtab = jp;
4605         jp = (struct job *)((char *)jp + len);
4606         jq = jp + 3;
4607         do {
4608                 jq->used = 0;
4609         } while (--jq >= jp);
4610         return jp;
4611 }
4612
4613 /*
4614  * Return a new job structure.
4615  * Called with interrupts off.
4616  */
4617 static struct job *
4618 makejob(/*union node *node,*/ int nprocs)
4619 {
4620         int i;
4621         struct job *jp;
4622
4623         for (i = njobs, jp = jobtab; ; jp++) {
4624                 if (--i < 0) {
4625                         jp = growjobtab();
4626                         break;
4627                 }
4628                 if (jp->used == 0)
4629                         break;
4630                 if (jp->state != JOBDONE || !jp->waited)
4631                         continue;
4632 #if JOBS
4633                 if (doing_jobctl)
4634                         continue;
4635 #endif
4636                 freejob(jp);
4637                 break;
4638         }
4639         memset(jp, 0, sizeof(*jp));
4640 #if JOBS
4641         /* jp->jobctl is a bitfield.
4642          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4643         if (doing_jobctl)
4644                 jp->jobctl = 1;
4645 #endif
4646         jp->prev_job = curjob;
4647         curjob = jp;
4648         jp->used = 1;
4649         jp->ps = &jp->ps0;
4650         if (nprocs > 1) {
4651                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4652         }
4653         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4654                                 jobno(jp)));
4655         return jp;
4656 }
4657
4658 #if JOBS
4659 /*
4660  * Return a string identifying a command (to be printed by the
4661  * jobs command).
4662  */
4663 static char *cmdnextc;
4664
4665 static void
4666 cmdputs(const char *s)
4667 {
4668         static const char vstype[VSTYPE + 1][3] = {
4669                 "", "}", "-", "+", "?", "=",
4670                 "%", "%%", "#", "##"
4671                 IF_BASH_SUBSTR(, ":")
4672                 IF_BASH_PATTERN_SUBST(, "/", "//")
4673         };
4674
4675         const char *p, *str;
4676         char cc[2];
4677         char *nextc;
4678         unsigned char c;
4679         unsigned char subtype = 0;
4680         int quoted = 0;
4681
4682         cc[1] = '\0';
4683         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4684         p = s;
4685         while ((c = *p++) != '\0') {
4686                 str = NULL;
4687                 switch (c) {
4688                 case CTLESC:
4689                         c = *p++;
4690                         break;
4691                 case CTLVAR:
4692                         subtype = *p++;
4693                         if ((subtype & VSTYPE) == VSLENGTH)
4694                                 str = "${#";
4695                         else
4696                                 str = "${";
4697                         goto dostr;
4698                 case CTLENDVAR:
4699                         str = "\"}" + !(quoted & 1);
4700                         quoted >>= 1;
4701                         subtype = 0;
4702                         goto dostr;
4703                 case CTLBACKQ:
4704                         str = "$(...)";
4705                         goto dostr;
4706 #if ENABLE_FEATURE_SH_MATH
4707                 case CTLARI:
4708                         str = "$((";
4709                         goto dostr;
4710                 case CTLENDARI:
4711                         str = "))";
4712                         goto dostr;
4713 #endif
4714                 case CTLQUOTEMARK:
4715                         quoted ^= 1;
4716                         c = '"';
4717                         break;
4718                 case '=':
4719                         if (subtype == 0)
4720                                 break;
4721                         if ((subtype & VSTYPE) != VSNORMAL)
4722                                 quoted <<= 1;
4723                         str = vstype[subtype & VSTYPE];
4724                         if (subtype & VSNUL)
4725                                 c = ':';
4726                         else
4727                                 goto checkstr;
4728                         break;
4729                 case '\'':
4730                 case '\\':
4731                 case '"':
4732                 case '$':
4733                         /* These can only happen inside quotes */
4734                         cc[0] = c;
4735                         str = cc;
4736 //FIXME:
4737 // $ true $$ &
4738 // $ <cr>
4739 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4740                         c = '\\';
4741                         break;
4742                 default:
4743                         break;
4744                 }
4745                 USTPUTC(c, nextc);
4746  checkstr:
4747                 if (!str)
4748                         continue;
4749  dostr:
4750                 while ((c = *str++) != '\0') {
4751                         USTPUTC(c, nextc);
4752                 }
4753         } /* while *p++ not NUL */
4754
4755         if (quoted & 1) {
4756                 USTPUTC('"', nextc);
4757         }
4758         *nextc = 0;
4759         cmdnextc = nextc;
4760 }
4761
4762 /* cmdtxt() and cmdlist() call each other */
4763 static void cmdtxt(union node *n);
4764
4765 static void
4766 cmdlist(union node *np, int sep)
4767 {
4768         for (; np; np = np->narg.next) {
4769                 if (!sep)
4770                         cmdputs(" ");
4771                 cmdtxt(np);
4772                 if (sep && np->narg.next)
4773                         cmdputs(" ");
4774         }
4775 }
4776
4777 static void
4778 cmdtxt(union node *n)
4779 {
4780         union node *np;
4781         struct nodelist *lp;
4782         const char *p;
4783
4784         if (!n)
4785                 return;
4786         switch (n->type) {
4787         default:
4788 #if DEBUG
4789                 abort();
4790 #endif
4791         case NPIPE:
4792                 lp = n->npipe.cmdlist;
4793                 for (;;) {
4794                         cmdtxt(lp->n);
4795                         lp = lp->next;
4796                         if (!lp)
4797                                 break;
4798                         cmdputs(" | ");
4799                 }
4800                 break;
4801         case NSEMI:
4802                 p = "; ";
4803                 goto binop;
4804         case NAND:
4805                 p = " && ";
4806                 goto binop;
4807         case NOR:
4808                 p = " || ";
4809  binop:
4810                 cmdtxt(n->nbinary.ch1);
4811                 cmdputs(p);
4812                 n = n->nbinary.ch2;
4813                 goto donode;
4814         case NREDIR:
4815         case NBACKGND:
4816                 n = n->nredir.n;
4817                 goto donode;
4818         case NNOT:
4819                 cmdputs("!");
4820                 n = n->nnot.com;
4821  donode:
4822                 cmdtxt(n);
4823                 break;
4824         case NIF:
4825                 cmdputs("if ");
4826                 cmdtxt(n->nif.test);
4827                 cmdputs("; then ");
4828                 if (n->nif.elsepart) {
4829                         cmdtxt(n->nif.ifpart);
4830                         cmdputs("; else ");
4831                         n = n->nif.elsepart;
4832                 } else {
4833                         n = n->nif.ifpart;
4834                 }
4835                 p = "; fi";
4836                 goto dotail;
4837         case NSUBSHELL:
4838                 cmdputs("(");
4839                 n = n->nredir.n;
4840                 p = ")";
4841                 goto dotail;
4842         case NWHILE:
4843                 p = "while ";
4844                 goto until;
4845         case NUNTIL:
4846                 p = "until ";
4847  until:
4848                 cmdputs(p);
4849                 cmdtxt(n->nbinary.ch1);
4850                 n = n->nbinary.ch2;
4851                 p = "; done";
4852  dodo:
4853                 cmdputs("; do ");
4854  dotail:
4855                 cmdtxt(n);
4856                 goto dotail2;
4857         case NFOR:
4858                 cmdputs("for ");
4859                 cmdputs(n->nfor.var);
4860                 cmdputs(" in ");
4861                 cmdlist(n->nfor.args, 1);
4862                 n = n->nfor.body;
4863                 p = "; done";
4864                 goto dodo;
4865         case NDEFUN:
4866                 cmdputs(n->ndefun.text);
4867                 p = "() { ... }";
4868                 goto dotail2;
4869         case NCMD:
4870                 cmdlist(n->ncmd.args, 1);
4871                 cmdlist(n->ncmd.redirect, 0);
4872                 break;
4873         case NARG:
4874                 p = n->narg.text;
4875  dotail2:
4876                 cmdputs(p);
4877                 break;
4878         case NHERE:
4879         case NXHERE:
4880                 p = "<<...";
4881                 goto dotail2;
4882         case NCASE:
4883                 cmdputs("case ");
4884                 cmdputs(n->ncase.expr->narg.text);
4885                 cmdputs(" in ");
4886                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4887                         cmdtxt(np->nclist.pattern);
4888                         cmdputs(") ");
4889                         cmdtxt(np->nclist.body);
4890                         cmdputs(";; ");
4891                 }
4892                 p = "esac";
4893                 goto dotail2;
4894         case NTO:
4895                 p = ">";
4896                 goto redir;
4897         case NCLOBBER:
4898                 p = ">|";
4899                 goto redir;
4900         case NAPPEND:
4901                 p = ">>";
4902                 goto redir;
4903 #if BASH_REDIR_OUTPUT
4904         case NTO2:
4905 #endif
4906         case NTOFD:
4907                 p = ">&";
4908                 goto redir;
4909         case NFROM:
4910                 p = "<";
4911                 goto redir;
4912         case NFROMFD:
4913                 p = "<&";
4914                 goto redir;
4915         case NFROMTO:
4916                 p = "<>";
4917  redir:
4918                 cmdputs(utoa(n->nfile.fd));
4919                 cmdputs(p);
4920                 if (n->type == NTOFD || n->type == NFROMFD) {
4921                         if (n->ndup.dupfd >= 0)
4922                                 cmdputs(utoa(n->ndup.dupfd));
4923                         else
4924                                 cmdputs("-");
4925                         break;
4926                 }
4927                 n = n->nfile.fname;
4928                 goto donode;
4929         }
4930 }
4931
4932 static char *
4933 commandtext(union node *n)
4934 {
4935         char *name;
4936
4937         STARTSTACKSTR(cmdnextc);
4938         cmdtxt(n);
4939         name = stackblock();
4940         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4941         return ckstrdup(name);
4942 }
4943 #endif /* JOBS */
4944
4945 /*
4946  * Fork off a subshell.  If we are doing job control, give the subshell its
4947  * own process group.  Jp is a job structure that the job is to be added to.
4948  * N is the command that will be evaluated by the child.  Both jp and n may
4949  * be NULL.  The mode parameter can be one of the following:
4950  *      FORK_FG - Fork off a foreground process.
4951  *      FORK_BG - Fork off a background process.
4952  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4953  *                   process group even if job control is on.
4954  *
4955  * When job control is turned off, background processes have their standard
4956  * input redirected to /dev/null (except for the second and later processes
4957  * in a pipeline).
4958  *
4959  * Called with interrupts off.
4960  */
4961 /*
4962  * Clear traps on a fork.
4963  */
4964 static void
4965 clear_traps(void)
4966 {
4967         char **tp;
4968
4969         INT_OFF;
4970         for (tp = trap; tp < &trap[NSIG]; tp++) {
4971                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4972                         if (trap_ptr == trap)
4973                                 free(*tp);
4974                         /* else: it "belongs" to trap_ptr vector, don't free */
4975                         *tp = NULL;
4976                         if ((tp - trap) != 0)
4977                                 setsignal(tp - trap);
4978                 }
4979         }
4980         may_have_traps = 0;
4981         INT_ON;
4982 }
4983
4984 /* Lives far away from here, needed for forkchild */
4985 static void closescript(void);
4986
4987 /* Called after fork(), in child */
4988 /* jp and n are NULL when called by openhere() for heredoc support */
4989 static NOINLINE void
4990 forkchild(struct job *jp, union node *n, int mode)
4991 {
4992         int oldlvl;
4993
4994         TRACE(("Child shell %d\n", getpid()));
4995         oldlvl = shlvl;
4996         shlvl++;
4997
4998         /* man bash: "Non-builtin commands run by bash have signal handlers
4999          * set to the values inherited by the shell from its parent".
5000          * Do we do it correctly? */
5001
5002         closescript();
5003
5004         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5005          && n && n->type == NCMD        /* is it single cmd? */
5006         /* && n->ncmd.args->type == NARG - always true? */
5007          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5008          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5009         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5010         ) {
5011                 TRACE(("Trap hack\n"));
5012                 /* Awful hack for `trap` or $(trap).
5013                  *
5014                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5015                  * contains an example where "trap" is executed in a subshell:
5016                  *
5017                  * save_traps=$(trap)
5018                  * ...
5019                  * eval "$save_traps"
5020                  *
5021                  * Standard does not say that "trap" in subshell shall print
5022                  * parent shell's traps. It only says that its output
5023                  * must have suitable form, but then, in the above example
5024                  * (which is not supposed to be normative), it implies that.
5025                  *
5026                  * bash (and probably other shell) does implement it
5027                  * (traps are reset to defaults, but "trap" still shows them),
5028                  * but as a result, "trap" logic is hopelessly messed up:
5029                  *
5030                  * # trap
5031                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5032                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5033                  * # true | trap   <--- trap is in subshell - no output (ditto)
5034                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5035                  * trap -- 'echo Ho' SIGWINCH
5036                  * # echo `(trap)`         <--- in subshell in subshell - output
5037                  * trap -- 'echo Ho' SIGWINCH
5038                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5039                  * trap -- 'echo Ho' SIGWINCH
5040                  *
5041                  * The rules when to forget and when to not forget traps
5042                  * get really complex and nonsensical.
5043                  *
5044                  * Our solution: ONLY bare $(trap) or `trap` is special.
5045                  */
5046                 /* Save trap handler strings for trap builtin to print */
5047                 trap_ptr = xmemdup(trap, sizeof(trap));
5048                 /* Fall through into clearing traps */
5049         }
5050         clear_traps();
5051 #if JOBS
5052         /* do job control only in root shell */
5053         doing_jobctl = 0;
5054         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5055                 pid_t pgrp;
5056
5057                 if (jp->nprocs == 0)
5058                         pgrp = getpid();
5059                 else
5060                         pgrp = jp->ps[0].ps_pid;
5061                 /* this can fail because we are doing it in the parent also */
5062                 setpgid(0, pgrp);
5063                 if (mode == FORK_FG)
5064                         xtcsetpgrp(ttyfd, pgrp);
5065                 setsignal(SIGTSTP);
5066                 setsignal(SIGTTOU);
5067         } else
5068 #endif
5069         if (mode == FORK_BG) {
5070                 /* man bash: "When job control is not in effect,
5071                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5072                 ignoresig(SIGINT);
5073                 ignoresig(SIGQUIT);
5074                 if (jp->nprocs == 0) {
5075                         close(0);
5076                         if (open(bb_dev_null, O_RDONLY) != 0)
5077                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5078                 }
5079         }
5080         if (oldlvl == 0) {
5081                 if (iflag) { /* why if iflag only? */
5082                         setsignal(SIGINT);
5083                         setsignal(SIGTERM);
5084                 }
5085                 /* man bash:
5086                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5087                  * commands run by bash have signal handlers
5088                  * set to the values inherited by the shell
5089                  * from its parent".
5090                  * Take care of the second rule: */
5091                 setsignal(SIGQUIT);
5092         }
5093 #if JOBS
5094         if (n && n->type == NCMD
5095          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5096         ) {
5097                 TRACE(("Job hack\n"));
5098                 /* "jobs": we do not want to clear job list for it,
5099                  * instead we remove only _its_ own_ job from job list.
5100                  * This makes "jobs .... | cat" more useful.
5101                  */
5102                 freejob(curjob);
5103                 return;
5104         }
5105 #endif
5106         for (jp = curjob; jp; jp = jp->prev_job)
5107                 freejob(jp);
5108         jobless = 0;
5109 }
5110
5111 /* Called after fork(), in parent */
5112 #if !JOBS
5113 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5114 #endif
5115 static void
5116 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5117 {
5118         TRACE(("In parent shell: child = %d\n", pid));
5119         if (!jp) {
5120                 /* jp is NULL when called by openhere() for heredoc support */
5121                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5122                         continue;
5123                 jobless++;
5124                 return;
5125         }
5126 #if JOBS
5127         if (mode != FORK_NOJOB && jp->jobctl) {
5128                 int pgrp;
5129
5130                 if (jp->nprocs == 0)
5131                         pgrp = pid;
5132                 else
5133                         pgrp = jp->ps[0].ps_pid;
5134                 /* This can fail because we are doing it in the child also */
5135                 setpgid(pid, pgrp);
5136         }
5137 #endif
5138         if (mode == FORK_BG) {
5139                 backgndpid = pid;               /* set $! */
5140                 set_curjob(jp, CUR_RUNNING);
5141         }
5142         if (jp) {
5143                 struct procstat *ps = &jp->ps[jp->nprocs++];
5144                 ps->ps_pid = pid;
5145                 ps->ps_status = -1;
5146                 ps->ps_cmd = nullstr;
5147 #if JOBS
5148                 if (doing_jobctl && n)
5149                         ps->ps_cmd = commandtext(n);
5150 #endif
5151         }
5152 }
5153
5154 /* jp and n are NULL when called by openhere() for heredoc support */
5155 static int
5156 forkshell(struct job *jp, union node *n, int mode)
5157 {
5158         int pid;
5159
5160         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5161         pid = fork();
5162         if (pid < 0) {
5163                 TRACE(("Fork failed, errno=%d", errno));
5164                 if (jp)
5165                         freejob(jp);
5166                 ash_msg_and_raise_perror("can't fork");
5167         }
5168         if (pid == 0) {
5169                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5170                 forkchild(jp, n, mode);
5171         } else {
5172                 forkparent(jp, n, mode, pid);
5173         }
5174         return pid;
5175 }
5176
5177 /*
5178  * Wait for job to finish.
5179  *
5180  * Under job control we have the problem that while a child process
5181  * is running interrupts generated by the user are sent to the child
5182  * but not to the shell.  This means that an infinite loop started by
5183  * an interactive user may be hard to kill.  With job control turned off,
5184  * an interactive user may place an interactive program inside a loop.
5185  * If the interactive program catches interrupts, the user doesn't want
5186  * these interrupts to also abort the loop.  The approach we take here
5187  * is to have the shell ignore interrupt signals while waiting for a
5188  * foreground process to terminate, and then send itself an interrupt
5189  * signal if the child process was terminated by an interrupt signal.
5190  * Unfortunately, some programs want to do a bit of cleanup and then
5191  * exit on interrupt; unless these processes terminate themselves by
5192  * sending a signal to themselves (instead of calling exit) they will
5193  * confuse this approach.
5194  *
5195  * Called with interrupts off.
5196  */
5197 static int
5198 waitforjob(struct job *jp)
5199 {
5200         int st;
5201
5202         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5203
5204         INT_OFF;
5205         while (jp->state == JOBRUNNING) {
5206                 /* In non-interactive shells, we _can_ get
5207                  * a keyboard signal here and be EINTRed,
5208                  * but we just loop back, waiting for command to complete.
5209                  *
5210                  * man bash:
5211                  * "If bash is waiting for a command to complete and receives
5212                  * a signal for which a trap has been set, the trap
5213                  * will not be executed until the command completes."
5214                  *
5215                  * Reality is that even if trap is not set, bash
5216                  * will not act on the signal until command completes.
5217                  * Try this. sleep5intoff.c:
5218                  * #include <signal.h>
5219                  * #include <unistd.h>
5220                  * int main() {
5221                  *         sigset_t set;
5222                  *         sigemptyset(&set);
5223                  *         sigaddset(&set, SIGINT);
5224                  *         sigaddset(&set, SIGQUIT);
5225                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5226                  *         sleep(5);
5227                  *         return 0;
5228                  * }
5229                  * $ bash -c './sleep5intoff; echo hi'
5230                  * ^C^C^C^C <--- pressing ^C once a second
5231                  * $ _
5232                  * $ bash -c './sleep5intoff; echo hi'
5233                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5234                  * $ _
5235                  */
5236                 dowait(DOWAIT_BLOCK, jp);
5237         }
5238         INT_ON;
5239
5240         st = getstatus(jp);
5241 #if JOBS
5242         if (jp->jobctl) {
5243                 xtcsetpgrp(ttyfd, rootpid);
5244                 restore_tty_if_stopped_or_signaled(jp);
5245
5246                 /*
5247                  * This is truly gross.
5248                  * If we're doing job control, then we did a TIOCSPGRP which
5249                  * caused us (the shell) to no longer be in the controlling
5250                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5251                  * intuit from the subprocess exit status whether a SIGINT
5252                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5253                  */
5254                 if (jp->sigint) /* TODO: do the same with all signals */
5255                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5256         }
5257         if (jp->state == JOBDONE)
5258 #endif
5259                 freejob(jp);
5260         return st;
5261 }
5262
5263 /*
5264  * return 1 if there are stopped jobs, otherwise 0
5265  */
5266 static int
5267 stoppedjobs(void)
5268 {
5269         struct job *jp;
5270         int retval;
5271
5272         retval = 0;
5273         if (job_warning)
5274                 goto out;
5275         jp = curjob;
5276         if (jp && jp->state == JOBSTOPPED) {
5277                 out2str("You have stopped jobs.\n");
5278                 job_warning = 2;
5279                 retval++;
5280         }
5281  out:
5282         return retval;
5283 }
5284
5285
5286 /*
5287  * Code for dealing with input/output redirection.
5288  */
5289
5290 #undef EMPTY
5291 #undef CLOSED
5292 #define EMPTY -2                /* marks an unused slot in redirtab */
5293 #define CLOSED -1               /* marks a slot of previously-closed fd */
5294
5295 /*
5296  * Handle here documents.  Normally we fork off a process to write the
5297  * data to a pipe.  If the document is short, we can stuff the data in
5298  * the pipe without forking.
5299  */
5300 /* openhere needs this forward reference */
5301 static void expandhere(union node *arg, int fd);
5302 static int
5303 openhere(union node *redir)
5304 {
5305         int pip[2];
5306         size_t len = 0;
5307
5308         if (pipe(pip) < 0)
5309                 ash_msg_and_raise_perror("can't create pipe");
5310         if (redir->type == NHERE) {
5311                 len = strlen(redir->nhere.doc->narg.text);
5312                 if (len <= PIPE_BUF) {
5313                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5314                         goto out;
5315                 }
5316         }
5317         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5318                 /* child */
5319                 close(pip[0]);
5320                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5321                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5322                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5323                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5324                 signal(SIGPIPE, SIG_DFL);
5325                 if (redir->type == NHERE)
5326                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5327                 else /* NXHERE */
5328                         expandhere(redir->nhere.doc, pip[1]);
5329                 _exit(EXIT_SUCCESS);
5330         }
5331  out:
5332         close(pip[1]);
5333         return pip[0];
5334 }
5335
5336 static int
5337 openredirect(union node *redir)
5338 {
5339         struct stat sb;
5340         char *fname;
5341         int f;
5342
5343         switch (redir->nfile.type) {
5344 /* Can't happen, our single caller does this itself */
5345 //      case NTOFD:
5346 //      case NFROMFD:
5347 //              return -1;
5348         case NHERE:
5349         case NXHERE:
5350                 return openhere(redir);
5351         }
5352
5353         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5354          * allocated space. Do it only when we know it is safe.
5355          */
5356         fname = redir->nfile.expfname;
5357
5358         switch (redir->nfile.type) {
5359         default:
5360 #if DEBUG
5361                 abort();
5362 #endif
5363         case NFROM:
5364                 f = open(fname, O_RDONLY);
5365                 if (f < 0)
5366                         goto eopen;
5367                 break;
5368         case NFROMTO:
5369                 f = open(fname, O_RDWR|O_CREAT, 0666);
5370                 if (f < 0)
5371                         goto ecreate;
5372                 break;
5373         case NTO:
5374 #if BASH_REDIR_OUTPUT
5375         case NTO2:
5376 #endif
5377                 /* Take care of noclobber mode. */
5378                 if (Cflag) {
5379                         if (stat(fname, &sb) < 0) {
5380                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5381                                 if (f < 0)
5382                                         goto ecreate;
5383                         } else if (!S_ISREG(sb.st_mode)) {
5384                                 f = open(fname, O_WRONLY, 0666);
5385                                 if (f < 0)
5386                                         goto ecreate;
5387                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5388                                         close(f);
5389                                         errno = EEXIST;
5390                                         goto ecreate;
5391                                 }
5392                         } else {
5393                                 errno = EEXIST;
5394                                 goto ecreate;
5395                         }
5396                         break;
5397                 }
5398                 /* FALLTHROUGH */
5399         case NCLOBBER:
5400                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5401                 if (f < 0)
5402                         goto ecreate;
5403                 break;
5404         case NAPPEND:
5405                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5406                 if (f < 0)
5407                         goto ecreate;
5408                 break;
5409         }
5410
5411         return f;
5412  ecreate:
5413         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5414  eopen:
5415         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5416 }
5417
5418 /*
5419  * Copy a file descriptor to be >= 10. Throws exception on error.
5420  */
5421 static int
5422 savefd(int from)
5423 {
5424         int newfd;
5425         int err;
5426
5427         newfd = fcntl(from, F_DUPFD, 10);
5428         err = newfd < 0 ? errno : 0;
5429         if (err != EBADF) {
5430                 if (err)
5431                         ash_msg_and_raise_perror("%d", from);
5432                 close(from);
5433                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5434         }
5435
5436         return newfd;
5437 }
5438 static int
5439 dup2_or_raise(int from, int to)
5440 {
5441         int newfd;
5442
5443         newfd = (from != to) ? dup2(from, to) : to;
5444         if (newfd < 0) {
5445                 /* Happens when source fd is not open: try "echo >&99" */
5446                 ash_msg_and_raise_perror("%d", from);
5447         }
5448         return newfd;
5449 }
5450 static int
5451 fcntl_F_DUPFD(int fd, int avoid_fd)
5452 {
5453         int newfd;
5454  repeat:
5455         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5456         if (newfd < 0) {
5457                 if (errno == EBUSY)
5458                         goto repeat;
5459                 if (errno == EINTR)
5460                         goto repeat;
5461         }
5462         return newfd;
5463 }
5464 static int
5465 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5466 {
5467         int newfd;
5468  repeat:
5469         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5470         if (newfd < 0) {
5471                 if (errno == EBUSY)
5472                         goto repeat;
5473                 if (errno == EINTR)
5474                         goto repeat;
5475                 /* fd was not open? */
5476                 if (errno == EBADF)
5477                         return fd;
5478                 ash_msg_and_raise_perror("%d", newfd);
5479         }
5480         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5481         close(fd);
5482         return newfd;
5483 }
5484
5485 /* Struct def and variable are moved down to the first usage site */
5486 struct squirrel {
5487         int orig_fd;
5488         int moved_to;
5489 };
5490 struct redirtab {
5491         struct redirtab *next;
5492         int pair_count;
5493         struct squirrel two_fd[];
5494 };
5495 #define redirlist (G_var.redirlist)
5496
5497 static void
5498 add_squirrel_closed(struct redirtab *sq, int fd)
5499 {
5500         int i;
5501
5502         if (!sq)
5503                 return;
5504
5505         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5506                 /* If we collide with an already moved fd... */
5507                 if (fd == sq->two_fd[i].orig_fd) {
5508                         /* Examples:
5509                          * "echo 3>FILE 3>&- 3>FILE"
5510                          * "echo 3>&- 3>FILE"
5511                          * No need for last redirect to insert
5512                          * another "need to close 3" indicator.
5513                          */
5514                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5515                         return;
5516                 }
5517         }
5518         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5519         sq->two_fd[i].orig_fd = fd;
5520         sq->two_fd[i].moved_to = CLOSED;
5521 }
5522
5523 static int
5524 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5525 {
5526         int i, new_fd;
5527
5528         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5529                 avoid_fd = 9;
5530
5531 #if JOBS
5532         if (fd == ttyfd) {
5533                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5534                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5535                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5536                 return 1; /* "we closed fd" */
5537         }
5538 #endif
5539         /* Are we called from redirect(0)? E.g. redirect
5540          * in a forked child. No need to save fds,
5541          * we aren't going to use them anymore, ok to trash.
5542          */
5543         if (!sq)
5544                 return 0;
5545
5546         /* If this one of script's fds? */
5547         if (fd != 0) {
5548                 struct parsefile *pf = g_parsefile;
5549                 while (pf) {
5550                         /* We skip fd == 0 case because of the following:
5551                          * $ ash  # running ash interactively
5552                          * $ . ./script.sh
5553                          * and in script.sh: "exec 9>&0".
5554                          * Even though top-level pf_fd _is_ 0,
5555                          * it's still ok to use it: "read" builtin uses it,
5556                          * why should we cripple "exec" builtin?
5557                          */
5558                         if (fd == pf->pf_fd) {
5559                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5560                                 return 1; /* "we closed fd" */
5561                         }
5562                         pf = pf->prev;
5563                 }
5564         }
5565
5566         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5567
5568         /* First: do we collide with some already moved fds? */
5569         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5570                 /* If we collide with an already moved fd... */
5571                 if (fd == sq->two_fd[i].moved_to) {
5572                         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5573                         sq->two_fd[i].moved_to = new_fd;
5574                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5575                         if (new_fd < 0) /* what? */
5576                                 xfunc_die();
5577                         return 0; /* "we did not close fd" */
5578                 }
5579                 if (fd == sq->two_fd[i].orig_fd) {
5580                         /* Example: echo Hello >/dev/null 1>&2 */
5581                         TRACE(("redirect_fd %d: already moved\n", fd));
5582                         return 0; /* "we did not close fd" */
5583                 }
5584         }
5585
5586         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5587         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5588         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5589         if (new_fd < 0) {
5590                 if (errno != EBADF)
5591                         xfunc_die();
5592                 /* new_fd = CLOSED; - already is -1 */
5593         }
5594         sq->two_fd[i].moved_to = new_fd;
5595         sq->two_fd[i].orig_fd = fd;
5596
5597         /* if we move stderr, let "set -x" code know */
5598         if (fd == preverrout_fd)
5599                 preverrout_fd = new_fd;
5600
5601         return 0; /* "we did not close fd" */
5602 }
5603
5604 static int
5605 internally_opened_fd(int fd, struct redirtab *sq)
5606 {
5607         int i;
5608 #if JOBS
5609         if (fd == ttyfd)
5610                 return 1;
5611 #endif
5612         /* If this one of script's fds? */
5613         if (fd != 0) {
5614                 struct parsefile *pf = g_parsefile;
5615                 while (pf) {
5616                         if (fd == pf->pf_fd)
5617                                 return 1;
5618                         pf = pf->prev;
5619                 }
5620         }
5621
5622         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5623                 if (fd == sq->two_fd[i].moved_to)
5624                         return 1;
5625         }
5626         return 0;
5627 }
5628
5629 /*
5630  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5631  * old file descriptors are stashed away so that the redirection can be
5632  * undone by calling popredir.
5633  */
5634 /* flags passed to redirect */
5635 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5636 static void
5637 redirect(union node *redir, int flags)
5638 {
5639         struct redirtab *sv;
5640
5641         if (!redir)
5642                 return;
5643
5644         sv = NULL;
5645         INT_OFF;
5646         if (flags & REDIR_PUSH)
5647                 sv = redirlist;
5648         do {
5649                 int fd;
5650                 int newfd;
5651                 int close_fd;
5652                 int closed;
5653
5654                 fd = redir->nfile.fd;
5655                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5656                         //bb_error_msg("doing %d > %d", fd, newfd);
5657                         newfd = redir->ndup.dupfd;
5658                         close_fd = -1;
5659                 } else {
5660                         newfd = openredirect(redir); /* always >= 0 */
5661                         if (fd == newfd) {
5662                                 /* open() gave us precisely the fd we wanted.
5663                                  * This means that this fd was not busy
5664                                  * (not opened to anywhere).
5665                                  * Remember to close it on restore:
5666                                  */
5667                                 add_squirrel_closed(sv, fd);
5668                                 continue;
5669                         }
5670                         close_fd = newfd;
5671                 }
5672
5673                 if (fd == newfd)
5674                         continue;
5675
5676                 /* if "N>FILE": move newfd to fd */
5677                 /* if "N>&M": dup newfd to fd */
5678                 /* if "N>&-": close fd (newfd is -1) */
5679
5680  IF_BASH_REDIR_OUTPUT(redirect_more:)
5681
5682                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5683                 if (newfd == -1) {
5684                         /* "N>&-" means "close me" */
5685                         if (!closed) {
5686                                 /* ^^^ optimization: saving may already
5687                                  * have closed it. If not... */
5688                                 close(fd);
5689                         }
5690                 } else {
5691                         /* if newfd is a script fd or saved fd, simulate EBADF */
5692                         if (internally_opened_fd(newfd, sv)) {
5693                                 errno = EBADF;
5694                                 ash_msg_and_raise_perror("%d", newfd);
5695                         }
5696                         dup2_or_raise(newfd, fd);
5697                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5698                                 close(close_fd);
5699 #if BASH_REDIR_OUTPUT
5700                         if (redir->nfile.type == NTO2 && fd == 1) {
5701                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5702                                 fd = 2;
5703                                 newfd = 1;
5704                                 close_fd = -1;
5705                                 goto redirect_more;
5706                         }
5707 #endif
5708                 }
5709         } while ((redir = redir->nfile.next) != NULL);
5710         INT_ON;
5711
5712 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5713 #define REDIR_SAVEFD2 0
5714         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5715         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5716         // not only for calls with flags containing REDIR_SAVEFD2.
5717         // We do this unconditionally (see save_fd_on_redirect()).
5718         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5719         //      preverrout_fd = copied_fd2;
5720 }
5721
5722 static int
5723 redirectsafe(union node *redir, int flags)
5724 {
5725         int err;
5726         volatile int saveint;
5727         struct jmploc *volatile savehandler = exception_handler;
5728         struct jmploc jmploc;
5729
5730         SAVE_INT(saveint);
5731         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5732         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5733         if (!err) {
5734                 exception_handler = &jmploc;
5735                 redirect(redir, flags);
5736         }
5737         exception_handler = savehandler;
5738         if (err && exception_type != EXERROR)
5739                 longjmp(exception_handler->loc, 1);
5740         RESTORE_INT(saveint);
5741         return err;
5742 }
5743
5744 static struct redirtab*
5745 pushredir(union node *redir)
5746 {
5747         struct redirtab *sv;
5748         int i;
5749
5750         if (!redir)
5751                 return redirlist;
5752
5753         i = 0;
5754         do {
5755                 i++;
5756 #if BASH_REDIR_OUTPUT
5757                 if (redir->nfile.type == NTO2)
5758                         i++;
5759 #endif
5760                 redir = redir->nfile.next;
5761         } while (redir);
5762
5763         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5764         sv->pair_count = i;
5765         while (--i >= 0)
5766                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5767         sv->next = redirlist;
5768         redirlist = sv;
5769         return sv->next;
5770 }
5771
5772 /*
5773  * Undo the effects of the last redirection.
5774  */
5775 static void
5776 popredir(int drop)
5777 {
5778         struct redirtab *rp;
5779         int i;
5780
5781         if (redirlist == NULL)
5782                 return;
5783         INT_OFF;
5784         rp = redirlist;
5785         for (i = 0; i < rp->pair_count; i++) {
5786                 int fd = rp->two_fd[i].orig_fd;
5787                 int copy = rp->two_fd[i].moved_to;
5788                 if (copy == CLOSED) {
5789                         if (!drop)
5790                                 close(fd);
5791                         continue;
5792                 }
5793                 if (copy != EMPTY) {
5794                         if (!drop) {
5795                                 /*close(fd);*/
5796                                 dup2_or_raise(copy, fd);
5797                         }
5798                         close(copy);
5799                 }
5800         }
5801         redirlist = rp->next;
5802         free(rp);
5803         INT_ON;
5804 }
5805
5806 static void
5807 unwindredir(struct redirtab *stop)
5808 {
5809         while (redirlist != stop)
5810                 popredir(/*drop:*/ 0);
5811 }
5812
5813
5814 /* ============ Routines to expand arguments to commands
5815  *
5816  * We have to deal with backquotes, shell variables, and file metacharacters.
5817  */
5818
5819 #if ENABLE_FEATURE_SH_MATH
5820 static arith_t
5821 ash_arith(const char *s)
5822 {
5823         arith_state_t math_state;
5824         arith_t result;
5825
5826         math_state.lookupvar = lookupvar;
5827         math_state.setvar    = setvar0;
5828         //math_state.endofname = endofname;
5829
5830         INT_OFF;
5831         result = arith(&math_state, s);
5832         if (math_state.errmsg)
5833                 ash_msg_and_raise_error(math_state.errmsg);
5834         INT_ON;
5835
5836         return result;
5837 }
5838 #endif
5839 #if BASH_SUBSTR
5840 # if ENABLE_FEATURE_SH_MATH
5841 static int substr_atoi(const char *s)
5842 {
5843         arith_t t = ash_arith(s);
5844         if (sizeof(t) > sizeof(int)) {
5845                 /* clamp very large or very large negative nums for ${v:N:M}:
5846                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5847                  */
5848                 if (t > INT_MAX)
5849                         t = INT_MAX;
5850                 if (t < INT_MIN)
5851                         t = INT_MIN;
5852         }
5853         return t;
5854 }
5855 # else
5856 #  define substr_atoi(s) number(s)
5857 # endif
5858 #endif
5859
5860 /*
5861  * expandarg flags
5862  */
5863 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5864 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5865 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5866 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5867 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5868  * POSIX says for this case:
5869  *  Pathname expansion shall not be performed on the word by a
5870  *  non-interactive shell; an interactive shell may perform it, but shall
5871  *  do so only when the expansion would result in one word.
5872  * Currently, our code complies to the above rule by never globbing
5873  * redirection filenames.
5874  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5875  * (this means that on a typical Linux distro, bash almost always
5876  * performs globbing, and thus diverges from what we do).
5877  */
5878 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5879 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5880 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5881 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5882 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5883 /*
5884  * rmescape() flags
5885  */
5886 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5887 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5888 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5889 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5890
5891 /* Add CTLESC when necessary. */
5892 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5893 /* Do not skip NUL characters. */
5894 #define QUOTES_KEEPNUL EXP_TILDE
5895
5896 /*
5897  * Structure specifying which parts of the string should be searched
5898  * for IFS characters.
5899  */
5900 struct ifsregion {
5901         struct ifsregion *next; /* next region in list */
5902         int begoff;             /* offset of start of region */
5903         int endoff;             /* offset of end of region */
5904         int nulonly;            /* search for nul bytes only */
5905 };
5906
5907 struct arglist {
5908         struct strlist *list;
5909         struct strlist **lastp;
5910 };
5911
5912 /* output of current string */
5913 static char *expdest;
5914 /* list of back quote expressions */
5915 static struct nodelist *argbackq;
5916 /* first struct in list of ifs regions */
5917 static struct ifsregion ifsfirst;
5918 /* last struct in list */
5919 static struct ifsregion *ifslastp;
5920 /* holds expanded arg list */
5921 static struct arglist exparg;
5922
5923 /*
5924  * Our own itoa().
5925  * cvtnum() is used even if math support is off (to prepare $? values and such).
5926  */
5927 static int
5928 cvtnum(arith_t num)
5929 {
5930         int len;
5931
5932         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5933         len = sizeof(arith_t) * 3;
5934         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5935         if (sizeof(arith_t) < 4) len += 2;
5936
5937         expdest = makestrspace(len, expdest);
5938         len = fmtstr(expdest, len, ARITH_FMT, num);
5939         STADJUST(len, expdest);
5940         return len;
5941 }
5942
5943 /*
5944  * Break the argument string into pieces based upon IFS and add the
5945  * strings to the argument list.  The regions of the string to be
5946  * searched for IFS characters have been stored by recordregion.
5947  */
5948 static void
5949 ifsbreakup(char *string, struct arglist *arglist)
5950 {
5951         struct ifsregion *ifsp;
5952         struct strlist *sp;
5953         char *start;
5954         char *p;
5955         char *q;
5956         const char *ifs, *realifs;
5957         int ifsspc;
5958         int nulonly;
5959
5960         start = string;
5961         if (ifslastp != NULL) {
5962                 ifsspc = 0;
5963                 nulonly = 0;
5964                 realifs = ifsset() ? ifsval() : defifs;
5965                 ifsp = &ifsfirst;
5966                 do {
5967                         p = string + ifsp->begoff;
5968                         nulonly = ifsp->nulonly;
5969                         ifs = nulonly ? nullstr : realifs;
5970                         ifsspc = 0;
5971                         while (p < string + ifsp->endoff) {
5972                                 q = p;
5973                                 if ((unsigned char)*p == CTLESC)
5974                                         p++;
5975                                 if (!strchr(ifs, *p)) {
5976                                         p++;
5977                                         continue;
5978                                 }
5979                                 if (!nulonly)
5980                                         ifsspc = (strchr(defifs, *p) != NULL);
5981                                 /* Ignore IFS whitespace at start */
5982                                 if (q == start && ifsspc) {
5983                                         p++;
5984                                         start = p;
5985                                         continue;
5986                                 }
5987                                 *q = '\0';
5988                                 sp = stzalloc(sizeof(*sp));
5989                                 sp->text = start;
5990                                 *arglist->lastp = sp;
5991                                 arglist->lastp = &sp->next;
5992                                 p++;
5993                                 if (!nulonly) {
5994                                         for (;;) {
5995                                                 if (p >= string + ifsp->endoff) {
5996                                                         break;
5997                                                 }
5998                                                 q = p;
5999                                                 if ((unsigned char)*p == CTLESC)
6000                                                         p++;
6001                                                 if (strchr(ifs, *p) == NULL) {
6002                                                         p = q;
6003                                                         break;
6004                                                 }
6005                                                 if (strchr(defifs, *p) == NULL) {
6006                                                         if (ifsspc) {
6007                                                                 p++;
6008                                                                 ifsspc = 0;
6009                                                         } else {
6010                                                                 p = q;
6011                                                                 break;
6012                                                         }
6013                                                 } else
6014                                                         p++;
6015                                         }
6016                                 }
6017                                 start = p;
6018                         } /* while */
6019                         ifsp = ifsp->next;
6020                 } while (ifsp != NULL);
6021                 if (nulonly)
6022                         goto add;
6023         }
6024
6025         if (!*start)
6026                 return;
6027
6028  add:
6029         sp = stzalloc(sizeof(*sp));
6030         sp->text = start;
6031         *arglist->lastp = sp;
6032         arglist->lastp = &sp->next;
6033 }
6034
6035 static void
6036 ifsfree(void)
6037 {
6038         struct ifsregion *p = ifsfirst.next;
6039
6040         if (!p)
6041                 goto out;
6042
6043         INT_OFF;
6044         do {
6045                 struct ifsregion *ifsp;
6046                 ifsp = p->next;
6047                 free(p);
6048                 p = ifsp;
6049         } while (p);
6050         ifsfirst.next = NULL;
6051         INT_ON;
6052  out:
6053         ifslastp = NULL;
6054 }
6055
6056 static size_t
6057 esclen(const char *start, const char *p)
6058 {
6059         size_t esc = 0;
6060
6061         while (p > start && (unsigned char)*--p == CTLESC) {
6062                 esc++;
6063         }
6064         return esc;
6065 }
6066
6067 /*
6068  * Remove any CTLESC characters from a string.
6069  */
6070 #if !BASH_PATTERN_SUBST
6071 #define rmescapes(str, flag, slash_position) \
6072         rmescapes(str, flag)
6073 #endif
6074 static char *
6075 rmescapes(char *str, int flag, int *slash_position)
6076 {
6077         static const char qchars[] ALIGN1 = {
6078                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6079
6080         char *p, *q, *r;
6081         unsigned inquotes;
6082         unsigned protect_against_glob;
6083         unsigned globbing;
6084
6085         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6086         if (!p)
6087                 return str;
6088
6089         q = p;
6090         r = str;
6091         if (flag & RMESCAPE_ALLOC) {
6092                 size_t len = p - str;
6093                 size_t fulllen = len + strlen(p) + 1;
6094
6095                 if (flag & RMESCAPE_GROW) {
6096                         int strloc = str - (char *)stackblock();
6097                         r = makestrspace(fulllen, expdest);
6098                         /* p and str may be invalidated by makestrspace */
6099                         str = (char *)stackblock() + strloc;
6100                         p = str + len;
6101                 } else if (flag & RMESCAPE_HEAP) {
6102                         r = ckmalloc(fulllen);
6103                 } else {
6104                         r = stalloc(fulllen);
6105                 }
6106                 q = r;
6107                 if (len > 0) {
6108                         q = (char *)mempcpy(q, str, len);
6109                 }
6110         }
6111
6112         inquotes = 0;
6113         globbing = flag & RMESCAPE_GLOB;
6114         protect_against_glob = globbing;
6115         while (*p) {
6116                 if ((unsigned char)*p == CTLQUOTEMARK) {
6117 // Note: both inquotes and protect_against_glob only affect whether
6118 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6119                         inquotes = ~inquotes;
6120                         p++;
6121                         protect_against_glob = globbing;
6122                         continue;
6123                 }
6124                 if ((unsigned char)*p == CTLESC) {
6125                         p++;
6126 #if DEBUG
6127                         if (*p == '\0')
6128                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6129 #endif
6130                         if (protect_against_glob) {
6131                                 /*
6132                                  * We used to trust glob() and fnmatch() to eat
6133                                  * superfluous escapes (\z where z has no
6134                                  * special meaning anyway). But this causes
6135                                  * bugs such as string of one greek letter rho
6136                                  * (unicode-encoded as two bytes "cf,81")
6137                                  * getting encoded as "cf,CTLESC,81"
6138                                  * and here, converted to "cf,\,81" -
6139                                  * which does not go well with some flavors
6140                                  * of fnmatch() in unicode locales
6141                                  * (for example, glibc <= 2.22).
6142                                  *
6143                                  * Lets add "\" only on the chars which need it.
6144                                  * Testcases for less obvious chars are shown.
6145                                  */
6146                                 if (*p == '*'
6147                                  || *p == '?'
6148                                  || *p == '['
6149                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6150                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6151                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6152                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6153                                 /* Some libc support [^negate], that's why "^" also needs love */
6154                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6155                                 ) {
6156                                         *q++ = '\\';
6157                                 }
6158                         }
6159                 } else if (*p == '\\' && !inquotes) {
6160                         /* naked back slash */
6161                         protect_against_glob = 0;
6162                         goto copy;
6163                 }
6164 #if BASH_PATTERN_SUBST
6165                 else if (slash_position && p == str + *slash_position) {
6166                         /* stop handling globbing */
6167                         globbing = 0;
6168                         *slash_position = q - r;
6169                         slash_position = NULL;
6170                 }
6171 #endif
6172                 protect_against_glob = globbing;
6173  copy:
6174                 *q++ = *p++;
6175         }
6176         *q = '\0';
6177         if (flag & RMESCAPE_GROW) {
6178                 expdest = r;
6179                 STADJUST(q - r + 1, expdest);
6180         }
6181         return r;
6182 }
6183 #define pmatch(a, b) !fnmatch((a), (b), 0)
6184
6185 /*
6186  * Prepare a pattern for a expmeta (internal glob(3)) call.
6187  *
6188  * Returns an stalloced string.
6189  */
6190 static char *
6191 preglob(const char *pattern, int flag)
6192 {
6193         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6194 }
6195
6196 /*
6197  * Put a string on the stack.
6198  */
6199 static void
6200 memtodest(const char *p, size_t len, int syntax, int quotes)
6201 {
6202         char *q;
6203
6204         if (!len)
6205                 return;
6206
6207         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6208
6209         do {
6210                 unsigned char c = *p++;
6211                 if (c) {
6212                         if (quotes & QUOTES_ESC) {
6213                                 int n = SIT(c, syntax);
6214                                 if (n == CCTL
6215                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6216                                      && n == CBACK
6217                                     )
6218                                 ) {
6219                                         USTPUTC(CTLESC, q);
6220                                 }
6221                         }
6222                 } else if (!(quotes & QUOTES_KEEPNUL))
6223                         continue;
6224                 USTPUTC(c, q);
6225         } while (--len);
6226
6227         expdest = q;
6228 }
6229
6230 static size_t
6231 strtodest(const char *p, int syntax, int quotes)
6232 {
6233         size_t len = strlen(p);
6234         memtodest(p, len, syntax, quotes);
6235         return len;
6236 }
6237
6238 /*
6239  * Record the fact that we have to scan this region of the
6240  * string for IFS characters.
6241  */
6242 static void
6243 recordregion(int start, int end, int nulonly)
6244 {
6245         struct ifsregion *ifsp;
6246
6247         if (ifslastp == NULL) {
6248                 ifsp = &ifsfirst;
6249         } else {
6250                 INT_OFF;
6251                 ifsp = ckzalloc(sizeof(*ifsp));
6252                 /*ifsp->next = NULL; - ckzalloc did it */
6253                 ifslastp->next = ifsp;
6254                 INT_ON;
6255         }
6256         ifslastp = ifsp;
6257         ifslastp->begoff = start;
6258         ifslastp->endoff = end;
6259         ifslastp->nulonly = nulonly;
6260 }
6261
6262 static void
6263 removerecordregions(int endoff)
6264 {
6265         if (ifslastp == NULL)
6266                 return;
6267
6268         if (ifsfirst.endoff > endoff) {
6269                 while (ifsfirst.next) {
6270                         struct ifsregion *ifsp;
6271                         INT_OFF;
6272                         ifsp = ifsfirst.next->next;
6273                         free(ifsfirst.next);
6274                         ifsfirst.next = ifsp;
6275                         INT_ON;
6276                 }
6277                 if (ifsfirst.begoff > endoff) {
6278                         ifslastp = NULL;
6279                 } else {
6280                         ifslastp = &ifsfirst;
6281                         ifsfirst.endoff = endoff;
6282                 }
6283                 return;
6284         }
6285
6286         ifslastp = &ifsfirst;
6287         while (ifslastp->next && ifslastp->next->begoff < endoff)
6288                 ifslastp = ifslastp->next;
6289         while (ifslastp->next) {
6290                 struct ifsregion *ifsp;
6291                 INT_OFF;
6292                 ifsp = ifslastp->next->next;
6293                 free(ifslastp->next);
6294                 ifslastp->next = ifsp;
6295                 INT_ON;
6296         }
6297         if (ifslastp->endoff > endoff)
6298                 ifslastp->endoff = endoff;
6299 }
6300
6301 static char *
6302 exptilde(char *startp, char *p, int flags)
6303 {
6304         unsigned char c;
6305         char *name;
6306         struct passwd *pw;
6307         const char *home;
6308         int quotes = flags & QUOTES_ESC;
6309
6310         name = p + 1;
6311
6312         while ((c = *++p) != '\0') {
6313                 switch (c) {
6314                 case CTLESC:
6315                         return startp;
6316                 case CTLQUOTEMARK:
6317                         return startp;
6318                 case ':':
6319                         if (flags & EXP_VARTILDE)
6320                                 goto done;
6321                         break;
6322                 case '/':
6323                 case CTLENDVAR:
6324                         goto done;
6325                 }
6326         }
6327  done:
6328         *p = '\0';
6329         if (*name == '\0') {
6330                 home = lookupvar("HOME");
6331         } else {
6332                 pw = getpwnam(name);
6333                 if (pw == NULL)
6334                         goto lose;
6335                 home = pw->pw_dir;
6336         }
6337         if (!home || !*home)
6338                 goto lose;
6339         *p = c;
6340         strtodest(home, SQSYNTAX, quotes);
6341         return p;
6342  lose:
6343         *p = c;
6344         return startp;
6345 }
6346
6347 /*
6348  * Execute a command inside back quotes.  If it's a builtin command, we
6349  * want to save its output in a block obtained from malloc.  Otherwise
6350  * we fork off a subprocess and get the output of the command via a pipe.
6351  * Should be called with interrupts off.
6352  */
6353 struct backcmd {                /* result of evalbackcmd */
6354         int fd;                 /* file descriptor to read from */
6355         int nleft;              /* number of chars in buffer */
6356         char *buf;              /* buffer */
6357         struct job *jp;         /* job structure for command */
6358 };
6359
6360 /* These forward decls are needed to use "eval" code for backticks handling: */
6361 /* flags in argument to evaltree */
6362 #define EV_EXIT    01           /* exit after evaluating tree */
6363 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6364 static int evaltree(union node *, int);
6365
6366 /* An evaltree() which is known to never return.
6367  * Used to use an alias:
6368  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6369  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6370  */
6371 static ALWAYS_INLINE NORETURN void
6372 evaltreenr(union node *n, int flags)
6373 {
6374         evaltree(n, flags);
6375         bb_unreachable(abort());
6376         /* NOTREACHED */
6377 }
6378
6379 static void FAST_FUNC
6380 evalbackcmd(union node *n, struct backcmd *result)
6381 {
6382         int pip[2];
6383         struct job *jp;
6384
6385         result->fd = -1;
6386         result->buf = NULL;
6387         result->nleft = 0;
6388         result->jp = NULL;
6389         if (n == NULL) {
6390                 goto out;
6391         }
6392
6393         if (pipe(pip) < 0)
6394                 ash_msg_and_raise_perror("can't create pipe");
6395         jp = makejob(/*n,*/ 1);
6396         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6397                 /* child */
6398                 FORCE_INT_ON;
6399                 close(pip[0]);
6400                 if (pip[1] != 1) {
6401                         /*close(1);*/
6402                         dup2_or_raise(pip[1], 1);
6403                         close(pip[1]);
6404                 }
6405 /* TODO: eflag clearing makes the following not abort:
6406  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6407  * which is what bash does (unless it is in POSIX mode).
6408  * dash deleted "eflag = 0" line in the commit
6409  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6410  *  [EVAL] Don't clear eflag in evalbackcmd
6411  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6412  */
6413                 eflag = 0;
6414                 ifsfree();
6415                 evaltreenr(n, EV_EXIT);
6416                 /* NOTREACHED */
6417         }
6418         /* parent */
6419         close(pip[1]);
6420         result->fd = pip[0];
6421         result->jp = jp;
6422
6423  out:
6424         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6425                 result->fd, result->buf, result->nleft, result->jp));
6426 }
6427
6428 /*
6429  * Expand stuff in backwards quotes.
6430  */
6431 static void
6432 expbackq(union node *cmd, int flag)
6433 {
6434         struct backcmd in;
6435         int i;
6436         char buf[128];
6437         char *p;
6438         char *dest;
6439         int startloc;
6440         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6441         struct stackmark smark;
6442
6443         INT_OFF;
6444         startloc = expdest - (char *)stackblock();
6445         pushstackmark(&smark, startloc);
6446         evalbackcmd(cmd, &in);
6447         popstackmark(&smark);
6448
6449         p = in.buf;
6450         i = in.nleft;
6451         if (i == 0)
6452                 goto read;
6453         for (;;) {
6454                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6455  read:
6456                 if (in.fd < 0)
6457                         break;
6458                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6459                 TRACE(("expbackq: read returns %d\n", i));
6460                 if (i <= 0)
6461                         break;
6462                 p = buf;
6463         }
6464
6465         free(in.buf);
6466         if (in.fd >= 0) {
6467                 close(in.fd);
6468                 back_exitstatus = waitforjob(in.jp);
6469         }
6470         INT_ON;
6471
6472         /* Eat all trailing newlines */
6473         dest = expdest;
6474         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6475                 STUNPUTC(dest);
6476         expdest = dest;
6477
6478         if (!(flag & EXP_QUOTED))
6479                 recordregion(startloc, dest - (char *)stackblock(), 0);
6480         TRACE(("evalbackq: size:%d:'%.*s'\n",
6481                 (int)((dest - (char *)stackblock()) - startloc),
6482                 (int)((dest - (char *)stackblock()) - startloc),
6483                 stackblock() + startloc));
6484 }
6485
6486 #if ENABLE_FEATURE_SH_MATH
6487 /*
6488  * Expand arithmetic expression.  Backup to start of expression,
6489  * evaluate, place result in (backed up) result, adjust string position.
6490  */
6491 static void
6492 expari(int flag)
6493 {
6494         char *p, *start;
6495         int begoff;
6496         int len;
6497
6498         /* ifsfree(); */
6499
6500         /*
6501          * This routine is slightly over-complicated for
6502          * efficiency.  Next we scan backwards looking for the
6503          * start of arithmetic.
6504          */
6505         start = stackblock();
6506         p = expdest - 1;
6507         *p = '\0';
6508         p--;
6509         while (1) {
6510                 int esc;
6511
6512                 while ((unsigned char)*p != CTLARI) {
6513                         p--;
6514 #if DEBUG
6515                         if (p < start) {
6516                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6517                         }
6518 #endif
6519                 }
6520
6521                 esc = esclen(start, p);
6522                 if (!(esc % 2)) {
6523                         break;
6524                 }
6525
6526                 p -= esc + 1;
6527         }
6528
6529         begoff = p - start;
6530
6531         removerecordregions(begoff);
6532
6533         expdest = p;
6534
6535         if (flag & QUOTES_ESC)
6536                 rmescapes(p + 1, 0, NULL);
6537
6538         len = cvtnum(ash_arith(p + 1));
6539
6540         if (!(flag & EXP_QUOTED))
6541                 recordregion(begoff, begoff + len, 0);
6542 }
6543 #endif
6544
6545 /* argstr needs it */
6546 static char *evalvar(char *p, int flags);
6547
6548 /*
6549  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6550  * characters to allow for further processing.  Otherwise treat
6551  * $@ like $* since no splitting will be performed.
6552  */
6553 static void
6554 argstr(char *p, int flags)
6555 {
6556         static const char spclchars[] ALIGN1 = {
6557                 '=',
6558                 ':',
6559                 CTLQUOTEMARK,
6560                 CTLENDVAR,
6561                 CTLESC,
6562                 CTLVAR,
6563                 CTLBACKQ,
6564 #if ENABLE_FEATURE_SH_MATH
6565                 CTLENDARI,
6566 #endif
6567                 '\0'
6568         };
6569         const char *reject = spclchars;
6570         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6571         int inquotes;
6572         size_t length;
6573         int startloc;
6574
6575         if (!(flags & EXP_VARTILDE)) {
6576                 reject += 2;
6577         } else if (flags & EXP_VARTILDE2) {
6578                 reject++;
6579         }
6580         inquotes = 0;
6581         length = 0;
6582         if (flags & EXP_TILDE) {
6583                 char *q;
6584
6585                 flags &= ~EXP_TILDE;
6586  tilde:
6587                 q = p;
6588                 if (*q == '~')
6589                         p = exptilde(p, q, flags);
6590         }
6591  start:
6592         startloc = expdest - (char *)stackblock();
6593         for (;;) {
6594                 unsigned char c;
6595
6596                 length += strcspn(p + length, reject);
6597                 c = p[length];
6598                 if (c) {
6599                         if (!(c & 0x80)
6600                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6601                         ) {
6602                                 /* c == '=' || c == ':' || c == CTLENDARI */
6603                                 length++;
6604                         }
6605                 }
6606                 if (length > 0) {
6607                         int newloc;
6608                         expdest = stack_nputstr(p, length, expdest);
6609                         newloc = expdest - (char *)stackblock();
6610                         if (breakall && !inquotes && newloc > startloc) {
6611                                 recordregion(startloc, newloc, 0);
6612                         }
6613                         startloc = newloc;
6614                 }
6615                 p += length + 1;
6616                 length = 0;
6617
6618                 switch (c) {
6619                 case '\0':
6620                         goto breakloop;
6621                 case '=':
6622                         if (flags & EXP_VARTILDE2) {
6623                                 p--;
6624                                 continue;
6625                         }
6626                         flags |= EXP_VARTILDE2;
6627                         reject++;
6628                         /* fall through */
6629                 case ':':
6630                         /*
6631                          * sort of a hack - expand tildes in variable
6632                          * assignments (after the first '=' and after ':'s).
6633                          */
6634                         if (*--p == '~') {
6635                                 goto tilde;
6636                         }
6637                         continue;
6638                 }
6639
6640                 switch (c) {
6641                 case CTLENDVAR: /* ??? */
6642                         goto breakloop;
6643                 case CTLQUOTEMARK:
6644                         inquotes ^= EXP_QUOTED;
6645                         /* "$@" syntax adherence hack */
6646                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6647                                 p = evalvar(p + 1, flags | inquotes) + 1;
6648                                 goto start;
6649                         }
6650  addquote:
6651                         if (flags & QUOTES_ESC) {
6652                                 p--;
6653                                 length++;
6654                                 startloc++;
6655                         }
6656                         break;
6657                 case CTLESC:
6658                         startloc++;
6659                         length++;
6660
6661                         /*
6662                          * Quoted parameter expansion pattern: remove quote
6663                          * unless inside inner quotes or we have a literal
6664                          * backslash.
6665                          */
6666                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6667                             EXP_QPAT && *p != '\\')
6668                                 break;
6669
6670                         goto addquote;
6671                 case CTLVAR:
6672                         TRACE(("argstr: evalvar('%s')\n", p));
6673                         p = evalvar(p, flags | inquotes);
6674                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6675                         goto start;
6676                 case CTLBACKQ:
6677                         expbackq(argbackq->n, flags | inquotes);
6678                         argbackq = argbackq->next;
6679                         goto start;
6680 #if ENABLE_FEATURE_SH_MATH
6681                 case CTLENDARI:
6682                         p--;
6683                         expari(flags | inquotes);
6684                         goto start;
6685 #endif
6686                 }
6687         }
6688  breakloop: ;
6689 }
6690
6691 static char *
6692 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6693                 char *pattern, int quotes, int zero)
6694 {
6695         char *loc, *loc2;
6696         char c;
6697
6698         loc = startp;
6699         loc2 = rmesc;
6700         do {
6701                 int match;
6702                 const char *s = loc2;
6703
6704                 c = *loc2;
6705                 if (zero) {
6706                         *loc2 = '\0';
6707                         s = rmesc;
6708                 }
6709                 match = pmatch(pattern, s);
6710
6711                 *loc2 = c;
6712                 if (match)
6713                         return loc;
6714                 if (quotes && (unsigned char)*loc == CTLESC)
6715                         loc++;
6716                 loc++;
6717                 loc2++;
6718         } while (c);
6719         return NULL;
6720 }
6721
6722 static char *
6723 scanright(char *startp, char *rmesc, char *rmescend,
6724                 char *pattern, int quotes, int match_at_start)
6725 {
6726 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6727         int try2optimize = match_at_start;
6728 #endif
6729         int esc = 0;
6730         char *loc;
6731         char *loc2;
6732
6733         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6734          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6735          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6736          * Logic:
6737          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6738          * and on each iteration they go back two/one char until they reach the beginning.
6739          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6740          */
6741         /* TODO: document in what other circumstances we are called. */
6742
6743         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6744                 int match;
6745                 char c = *loc2;
6746                 const char *s = loc2;
6747                 if (match_at_start) {
6748                         *loc2 = '\0';
6749                         s = rmesc;
6750                 }
6751                 match = pmatch(pattern, s);
6752                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6753                 *loc2 = c;
6754                 if (match)
6755                         return loc;
6756 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6757                 if (try2optimize) {
6758                         /* Maybe we can optimize this:
6759                          * if pattern ends with unescaped *, we can avoid checking
6760                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6761                          * it won't match truncated "raw_value_of_" strings too.
6762                          */
6763                         unsigned plen = strlen(pattern);
6764                         /* Does it end with "*"? */
6765                         if (plen != 0 && pattern[--plen] == '*') {
6766                                 /* "xxxx*" is not escaped */
6767                                 /* "xxx\*" is escaped */
6768                                 /* "xx\\*" is not escaped */
6769                                 /* "x\\\*" is escaped */
6770                                 int slashes = 0;
6771                                 while (plen != 0 && pattern[--plen] == '\\')
6772                                         slashes++;
6773                                 if (!(slashes & 1))
6774                                         break; /* ends with unescaped "*" */
6775                         }
6776                         try2optimize = 0;
6777                 }
6778 #endif
6779                 loc--;
6780                 if (quotes) {
6781                         if (--esc < 0) {
6782                                 esc = esclen(startp, loc);
6783                         }
6784                         if (esc % 2) {
6785                                 esc--;
6786                                 loc--;
6787                         }
6788                 }
6789         }
6790         return NULL;
6791 }
6792
6793 static void varunset(const char *, const char *, const char *, int) NORETURN;
6794 static void
6795 varunset(const char *end, const char *var, const char *umsg, int varflags)
6796 {
6797         const char *msg;
6798         const char *tail;
6799
6800         tail = nullstr;
6801         msg = "parameter not set";
6802         if (umsg) {
6803                 if ((unsigned char)*end == CTLENDVAR) {
6804                         if (varflags & VSNUL)
6805                                 tail = " or null";
6806                 } else {
6807                         msg = umsg;
6808                 }
6809         }
6810         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6811 }
6812
6813 static const char *
6814 subevalvar(char *p, char *varname, int strloc, int subtype,
6815                 int startloc, int varflags, int flag)
6816 {
6817         struct nodelist *saveargbackq = argbackq;
6818         int quotes = flag & QUOTES_ESC;
6819         char *startp;
6820         char *loc;
6821         char *rmesc, *rmescend;
6822         char *str;
6823         int amount, resetloc;
6824         int argstr_flags;
6825         IF_BASH_PATTERN_SUBST(int workloc;)
6826         IF_BASH_PATTERN_SUBST(int slash_pos;)
6827         IF_BASH_PATTERN_SUBST(char *repl;)
6828         int zero;
6829         char *(*scan)(char*, char*, char*, char*, int, int);
6830
6831         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6832         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6833
6834 #if BASH_PATTERN_SUBST
6835         /* For "${v/pattern/repl}", we must find the delimiter _before_
6836          * argstr() call expands possible variable references in pattern:
6837          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6838          */
6839         repl = NULL;
6840         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6841                 /* Find '/' and replace with NUL */
6842                 repl = p;
6843                 for (;;) {
6844                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6845                         if (*repl == '\0') {
6846                                 repl = NULL;
6847                                 break;
6848                         }
6849                         if (*repl == '/') {
6850                                 *repl = '\0';
6851                                 break;
6852                         }
6853                         if ((unsigned char)*repl == CTLESC && repl[1])
6854                                 repl++;
6855                         repl++;
6856                 }
6857         }
6858 #endif
6859         argstr_flags = EXP_TILDE;
6860         if (subtype != VSASSIGN && subtype != VSQUESTION)
6861                 argstr_flags |= (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE);
6862         argstr(p, argstr_flags);
6863 #if BASH_PATTERN_SUBST
6864         slash_pos = -1;
6865         if (repl) {
6866                 slash_pos = expdest - ((char *)stackblock() + strloc);
6867                 STPUTC('/', expdest);
6868                 argstr(repl + 1, argstr_flags);
6869                 *repl = '/';
6870         }
6871 #endif
6872         STPUTC('\0', expdest);
6873         argbackq = saveargbackq;
6874         startp = (char *)stackblock() + startloc;
6875         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6876
6877         switch (subtype) {
6878         case VSASSIGN:
6879                 setvar0(varname, startp);
6880                 amount = startp - expdest;
6881                 STADJUST(amount, expdest);
6882                 return startp;
6883
6884         case VSQUESTION:
6885                 varunset(p, varname, startp, varflags);
6886                 /* NOTREACHED */
6887
6888 #if BASH_SUBSTR
6889         case VSSUBSTR: {
6890                 int pos, len, orig_len;
6891                 char *colon;
6892
6893                 loc = str = stackblock() + strloc;
6894
6895                 /* Read POS in ${var:POS:LEN} */
6896                 colon = strchr(loc, ':');
6897                 if (colon) *colon = '\0';
6898                 pos = substr_atoi(loc);
6899                 if (colon) *colon = ':';
6900
6901                 /* Read LEN in ${var:POS:LEN} */
6902                 len = str - startp - 1;
6903                 /* *loc != '\0', guaranteed by parser */
6904                 if (quotes) {
6905                         char *ptr;
6906                         /* Adjust the length by the number of escapes */
6907                         for (ptr = startp; ptr < (str - 1); ptr++) {
6908                                 if ((unsigned char)*ptr == CTLESC) {
6909                                         len--;
6910                                         ptr++;
6911                                 }
6912                         }
6913                 }
6914                 orig_len = len;
6915                 if (*loc++ == ':') {
6916                         /* ${var::LEN} */
6917                         len = substr_atoi(loc);
6918                 } else {
6919                         /* Skip POS in ${var:POS:LEN} */
6920                         len = orig_len;
6921                         while (*loc && *loc != ':')
6922                                 loc++;
6923                         if (*loc++ == ':')
6924                                 len = substr_atoi(loc);
6925                 }
6926                 if (pos < 0) {
6927                         /* ${VAR:$((-n)):l} starts n chars from the end */
6928                         pos = orig_len + pos;
6929                 }
6930                 if ((unsigned)pos >= orig_len) {
6931                         /* apart from obvious ${VAR:999999:l},
6932                          * covers ${VAR:$((-9999999)):l} - result is ""
6933                          * (bash compat)
6934                          */
6935                         pos = 0;
6936                         len = 0;
6937                 }
6938                 if (len < 0) {
6939                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6940                         len = (orig_len - pos) + len;
6941                 }
6942                 if ((unsigned)len > (orig_len - pos))
6943                         len = orig_len - pos;
6944
6945                 for (str = startp; pos; str++, pos--) {
6946                         if (quotes && (unsigned char)*str == CTLESC)
6947                                 str++;
6948                 }
6949                 for (loc = startp; len; len--) {
6950                         if (quotes && (unsigned char)*str == CTLESC)
6951                                 *loc++ = *str++;
6952                         *loc++ = *str++;
6953                 }
6954                 *loc = '\0';
6955                 amount = loc - expdest;
6956                 STADJUST(amount, expdest);
6957                 return loc;
6958         }
6959 #endif /* BASH_SUBSTR */
6960         }
6961
6962         resetloc = expdest - (char *)stackblock();
6963
6964 #if BASH_PATTERN_SUBST
6965         repl = NULL;
6966
6967         /* We'll comeback here if we grow the stack while handling
6968          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6969          * stack will need rebasing, and we'll need to remove our work
6970          * areas each time
6971          */
6972  restart:
6973 #endif
6974
6975         amount = expdest - ((char *)stackblock() + resetloc);
6976         STADJUST(-amount, expdest);
6977         startp = (char *)stackblock() + startloc;
6978
6979         rmesc = startp;
6980         rmescend = (char *)stackblock() + strloc;
6981         //bb_error_msg("str7:'%s'", rmescend);
6982         if (quotes) {
6983 //TODO: how to handle slash_pos here if string changes (shortens?)
6984                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
6985                 if (rmesc != startp) {
6986                         rmescend = expdest;
6987                         startp = (char *)stackblock() + startloc;
6988                 }
6989         }
6990         rmescend--;
6991         str = (char *)stackblock() + strloc;
6992         /*
6993          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6994          * The result is a_\_z_c (not a\_\_z_c)!
6995          *
6996          * The search pattern and replace string treat backslashes differently!
6997          * "&slash_pos" causes rmescapes() to work differently on the pattern
6998          * and string.  It's only used on the first call.
6999          */
7000         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7001         rmescapes(str, RMESCAPE_GLOB,
7002                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7003         );
7004
7005 #if BASH_PATTERN_SUBST
7006         workloc = expdest - (char *)stackblock();
7007         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7008                 int len;
7009                 char *idx, *end;
7010
7011                 if (!repl) {
7012                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7013                         repl = nullstr;
7014                         if (slash_pos >= 0) {
7015                                 repl = str + slash_pos;
7016                                 *repl++ = '\0';
7017                         }
7018                 }
7019                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7020
7021                 /* If there's no pattern to match, return the expansion unmolested */
7022                 if (str[0] == '\0')
7023                         return NULL;
7024
7025                 len = 0;
7026                 idx = startp;
7027                 end = str - 1;
7028                 while (idx < end) {
7029  try_to_match:
7030                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7031                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7032                         if (!loc) {
7033                                 /* No match, advance */
7034                                 char *restart_detect = stackblock();
7035  skip_matching:
7036                                 STPUTC(*idx, expdest);
7037                                 if (quotes && (unsigned char)*idx == CTLESC) {
7038                                         idx++;
7039                                         len++;
7040                                         STPUTC(*idx, expdest);
7041                                 }
7042                                 if (stackblock() != restart_detect)
7043                                         goto restart;
7044                                 idx++;
7045                                 len++;
7046                                 rmesc++;
7047                                 /* continue; - prone to quadratic behavior, smarter code: */
7048                                 if (idx >= end)
7049                                         break;
7050                                 if (str[0] == '*') {
7051                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7052                                          * it would never match "ong_string" etc, no point in trying.
7053                                          */
7054                                         goto skip_matching;
7055                                 }
7056                                 goto try_to_match;
7057                         }
7058
7059                         if (subtype == VSREPLACEALL) {
7060                                 while (idx < loc) {
7061                                         if (quotes && (unsigned char)*idx == CTLESC)
7062                                                 idx++;
7063                                         idx++;
7064                                         rmesc++;
7065                                 }
7066                         } else {
7067                                 idx = loc;
7068                         }
7069
7070                         //bb_error_msg("repl:'%s'", repl);
7071                         for (loc = (char*)repl; *loc; loc++) {
7072                                 char *restart_detect = stackblock();
7073                                 if (quotes && *loc == '\\') {
7074                                         STPUTC(CTLESC, expdest);
7075                                         len++;
7076                                 }
7077                                 STPUTC(*loc, expdest);
7078                                 if (stackblock() != restart_detect)
7079                                         goto restart;
7080                                 len++;
7081                         }
7082
7083                         if (subtype == VSREPLACE) {
7084                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7085                                 while (*idx) {
7086                                         char *restart_detect = stackblock();
7087                                         STPUTC(*idx, expdest);
7088                                         if (stackblock() != restart_detect)
7089                                                 goto restart;
7090                                         len++;
7091                                         idx++;
7092                                 }
7093                                 break;
7094                         }
7095                 }
7096
7097                 /* We've put the replaced text into a buffer at workloc, now
7098                  * move it to the right place and adjust the stack.
7099                  */
7100                 STPUTC('\0', expdest);
7101                 startp = (char *)stackblock() + startloc;
7102                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7103                 //bb_error_msg("startp:'%s'", startp);
7104                 amount = expdest - (startp + len);
7105                 STADJUST(-amount, expdest);
7106                 return startp;
7107         }
7108 #endif /* BASH_PATTERN_SUBST */
7109
7110         subtype -= VSTRIMRIGHT;
7111 #if DEBUG
7112         if (subtype < 0 || subtype > 7)
7113                 abort();
7114 #endif
7115         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7116         zero = subtype >> 1;
7117         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7118         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7119
7120         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7121         if (loc) {
7122                 if (zero) {
7123                         memmove(startp, loc, str - loc);
7124                         loc = startp + (str - loc) - 1;
7125                 }
7126                 *loc = '\0';
7127                 amount = loc - expdest;
7128                 STADJUST(amount, expdest);
7129         }
7130         return loc;
7131 }
7132
7133 /*
7134  * Add the value of a specialized variable to the stack string.
7135  * name parameter (examples):
7136  * ash -c 'echo $1'      name:'1='
7137  * ash -c 'echo $qwe'    name:'qwe='
7138  * ash -c 'echo $$'      name:'$='
7139  * ash -c 'echo ${$}'    name:'$='
7140  * ash -c 'echo ${$##q}' name:'$=q'
7141  * ash -c 'echo ${#$}'   name:'$='
7142  * note: examples with bad shell syntax:
7143  * ash -c 'echo ${#$1}'  name:'$=1'
7144  * ash -c 'echo ${#1#}'  name:'1=#'
7145  */
7146 static NOINLINE ssize_t
7147 varvalue(char *name, int varflags, int flags, int *quotedp)
7148 {
7149         const char *p;
7150         int num;
7151         int i;
7152         ssize_t len = 0;
7153         int sep;
7154         int quoted = *quotedp;
7155         int subtype = varflags & VSTYPE;
7156         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7157         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7158         int syntax;
7159
7160         sep = (flags & EXP_FULL) << CHAR_BIT;
7161         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7162
7163         switch (*name) {
7164         case '$':
7165                 num = rootpid;
7166                 goto numvar;
7167         case '?':
7168                 num = exitstatus;
7169                 goto numvar;
7170         case '#':
7171                 num = shellparam.nparam;
7172                 goto numvar;
7173         case '!':
7174                 num = backgndpid;
7175                 if (num == 0)
7176                         return -1;
7177  numvar:
7178                 len = cvtnum(num);
7179                 goto check_1char_name;
7180         case '-':
7181                 expdest = makestrspace(NOPTS, expdest);
7182                 for (i = NOPTS - 1; i >= 0; i--) {
7183                         if (optlist[i]) {
7184                                 USTPUTC(optletters(i), expdest);
7185                                 len++;
7186                         }
7187                 }
7188  check_1char_name:
7189 #if 0
7190                 /* handles cases similar to ${#$1} */
7191                 if (name[2] != '\0')
7192                         raise_error_syntax("bad substitution");
7193 #endif
7194                 break;
7195         case '@':
7196                 if (quoted && sep)
7197                         goto param;
7198                 /* fall through */
7199         case '*': {
7200                 char **ap;
7201                 char sepc;
7202
7203                 if (quoted)
7204                         sep = 0;
7205                 sep |= ifsset() ? ifsval()[0] : ' ';
7206  param:
7207                 sepc = sep;
7208                 *quotedp = !sepc;
7209                 ap = shellparam.p;
7210                 if (!ap)
7211                         return -1;
7212                 while ((p = *ap++) != NULL) {
7213                         len += strtodest(p, syntax, quotes);
7214
7215                         if (*ap && sep) {
7216                                 len++;
7217                                 memtodest(&sepc, 1, syntax, quotes);
7218                         }
7219                 }
7220                 break;
7221         } /* case '*' */
7222         case '0':
7223         case '1':
7224         case '2':
7225         case '3':
7226         case '4':
7227         case '5':
7228         case '6':
7229         case '7':
7230         case '8':
7231         case '9':
7232                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7233                 if (num < 0 || num > shellparam.nparam)
7234                         return -1;
7235                 p = num ? shellparam.p[num - 1] : arg0;
7236                 goto value;
7237         default:
7238                 /* NB: name has form "VAR=..." */
7239                 p = lookupvar(name);
7240  value:
7241                 if (!p)
7242                         return -1;
7243
7244                 len = strtodest(p, syntax, quotes);
7245 #if ENABLE_UNICODE_SUPPORT
7246                 if (subtype == VSLENGTH && len > 0) {
7247                         reinit_unicode_for_ash();
7248                         if (unicode_status == UNICODE_ON) {
7249                                 STADJUST(-len, expdest);
7250                                 discard = 0;
7251                                 len = unicode_strlen(p);
7252                         }
7253                 }
7254 #endif
7255                 break;
7256         }
7257
7258         if (discard)
7259                 STADJUST(-len, expdest);
7260         return len;
7261 }
7262
7263 /*
7264  * Expand a variable, and return a pointer to the next character in the
7265  * input string.
7266  */
7267 static char *
7268 evalvar(char *p, int flag)
7269 {
7270         char varflags;
7271         char subtype;
7272         int quoted;
7273         char easy;
7274         char *var;
7275         int patloc;
7276         int startloc;
7277         ssize_t varlen;
7278
7279         varflags = (unsigned char) *p++;
7280         subtype = varflags & VSTYPE;
7281
7282         if (!subtype)
7283                 raise_error_syntax("bad substitution");
7284
7285         quoted = flag & EXP_QUOTED;
7286         var = p;
7287         easy = (!quoted || (*var == '@' && shellparam.nparam));
7288         startloc = expdest - (char *)stackblock();
7289         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7290
7291  again:
7292         varlen = varvalue(var, varflags, flag, &quoted);
7293         if (varflags & VSNUL)
7294                 varlen--;
7295
7296         if (subtype == VSPLUS) {
7297                 varlen = -1 - varlen;
7298                 goto vsplus;
7299         }
7300
7301         if (subtype == VSMINUS) {
7302  vsplus:
7303                 if (varlen < 0) {
7304                         argstr(
7305                                 p,
7306                                 flag | EXP_TILDE | EXP_WORD
7307                         );
7308                         goto end;
7309                 }
7310                 goto record;
7311         }
7312
7313         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7314                 if (varlen >= 0)
7315                         goto record;
7316
7317                 subevalvar(p, var, 0, subtype, startloc, varflags,
7318                            flag & ~QUOTES_ESC);
7319                 varflags &= ~VSNUL;
7320                 /*
7321                  * Remove any recorded regions beyond
7322                  * start of variable
7323                  */
7324                 removerecordregions(startloc);
7325                 goto again;
7326         }
7327
7328         if (varlen < 0 && uflag)
7329                 varunset(p, var, 0, 0);
7330
7331         if (subtype == VSLENGTH) {
7332                 cvtnum(varlen > 0 ? varlen : 0);
7333                 goto record;
7334         }
7335
7336         if (subtype == VSNORMAL) {
7337  record:
7338                 if (!easy)
7339                         goto end;
7340                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7341                 goto end;
7342         }
7343
7344 #if DEBUG
7345         switch (subtype) {
7346         case VSTRIMLEFT:
7347         case VSTRIMLEFTMAX:
7348         case VSTRIMRIGHT:
7349         case VSTRIMRIGHTMAX:
7350 #if BASH_SUBSTR
7351         case VSSUBSTR:
7352 #endif
7353 #if BASH_PATTERN_SUBST
7354         case VSREPLACE:
7355         case VSREPLACEALL:
7356 #endif
7357                 break;
7358         default:
7359                 abort();
7360         }
7361 #endif
7362
7363         if (varlen >= 0) {
7364                 /*
7365                  * Terminate the string and start recording the pattern
7366                  * right after it
7367                  */
7368                 STPUTC('\0', expdest);
7369                 patloc = expdest - (char *)stackblock();
7370                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7371                                 startloc, varflags, flag)) {
7372                         int amount = expdest - (
7373                                 (char *)stackblock() + patloc - 1
7374                         );
7375                         STADJUST(-amount, expdest);
7376                 }
7377                 /* Remove any recorded regions beyond start of variable */
7378                 removerecordregions(startloc);
7379                 goto record;
7380         }
7381
7382  end:
7383         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7384                 int nesting = 1;
7385                 for (;;) {
7386                         unsigned char c = *p++;
7387                         if (c == CTLESC)
7388                                 p++;
7389                         else if (c == CTLBACKQ) {
7390                                 if (varlen >= 0)
7391                                         argbackq = argbackq->next;
7392                         } else if (c == CTLVAR) {
7393                                 if ((*p++ & VSTYPE) != VSNORMAL)
7394                                         nesting++;
7395                         } else if (c == CTLENDVAR) {
7396                                 if (--nesting == 0)
7397                                         break;
7398                         }
7399                 }
7400         }
7401         return p;
7402 }
7403
7404 /*
7405  * Add a file name to the list.
7406  */
7407 static void
7408 addfname(const char *name)
7409 {
7410         struct strlist *sp;
7411
7412         sp = stzalloc(sizeof(*sp));
7413         sp->text = sstrdup(name);
7414         *exparg.lastp = sp;
7415         exparg.lastp = &sp->next;
7416 }
7417
7418 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7419 static int
7420 hasmeta(const char *p)
7421 {
7422         static const char chars[] ALIGN1 = {
7423                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7424         };
7425
7426         for (;;) {
7427                 p = strpbrk(p, chars);
7428                 if (!p)
7429                         break;
7430                 switch ((unsigned char) *p) {
7431                 case CTLQUOTEMARK:
7432                         for (;;) {
7433                                 p++;
7434                                 if (*p == CTLQUOTEMARK)
7435                                         break;
7436                                 if (*p == CTLESC)
7437                                         p++;
7438                                 if (*p == '\0') /* huh? */
7439                                         return 0;
7440                         }
7441                         break;
7442                 case '\\':
7443                 case CTLESC:
7444                         p++;
7445                         if (*p == '\0')
7446                                 return 0;
7447                         break;
7448                 case '[':
7449                         if (!strchr(p + 1, ']')) {
7450                                 /* It's not a properly closed [] pattern,
7451                                  * but other metas may follow. Continue checking.
7452                                  * my[file* _is_ globbed by bash
7453                                  * and matches filenames like "my[file1".
7454                                  */
7455                                 break;
7456                         }
7457                         /* fallthrough */
7458                 default:
7459                 /* case '*': */
7460                 /* case '?': */
7461                         return 1;
7462                 }
7463                 p++;
7464         }
7465
7466         return 0;
7467 }
7468
7469 /* If we want to use glob() from libc... */
7470 #if !ENABLE_ASH_INTERNAL_GLOB
7471
7472 /* Add the result of glob() to the list */
7473 static void
7474 addglob(const glob_t *pglob)
7475 {
7476         char **p = pglob->gl_pathv;
7477
7478         do {
7479                 addfname(*p);
7480         } while (*++p);
7481 }
7482 static void
7483 expandmeta(struct strlist *str /*, int flag*/)
7484 {
7485         /* TODO - EXP_REDIR */
7486
7487         while (str) {
7488                 char *p;
7489                 glob_t pglob;
7490                 int i;
7491
7492                 if (fflag)
7493                         goto nometa;
7494
7495                 if (!hasmeta(str->text))
7496                         goto nometa;
7497
7498                 INT_OFF;
7499                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7500 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7501 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7502 //
7503 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7504 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7505 // Which means you need to unescape the string, right? Not so fast:
7506 // if there _is_ a file named "file\?" (with backslash), it is returned
7507 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7508 // You DON'T KNOW by looking at the result whether you need to unescape it.
7509 //
7510 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7511 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7512 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7513 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7514 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7515 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7516                 i = glob(p, 0, NULL, &pglob);
7517                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7518                 if (p != str->text)
7519                         free(p);
7520                 switch (i) {
7521                 case 0:
7522 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7523                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7524                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7525                                 goto nometa2;
7526 #endif
7527                         addglob(&pglob);
7528                         globfree(&pglob);
7529                         INT_ON;
7530                         break;
7531                 case GLOB_NOMATCH:
7532  //nometa2:
7533                         globfree(&pglob);
7534                         INT_ON;
7535  nometa:
7536                         *exparg.lastp = str;
7537                         rmescapes(str->text, 0, NULL);
7538                         exparg.lastp = &str->next;
7539                         break;
7540                 default:        /* GLOB_NOSPACE */
7541                         globfree(&pglob);
7542                         INT_ON;
7543                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7544                 }
7545                 str = str->next;
7546         }
7547 }
7548
7549 #else
7550 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7551
7552 /*
7553  * Do metacharacter (i.e. *, ?, [...]) expansion.
7554  */
7555 static void
7556 expmeta(char *expdir, char *enddir, char *name)
7557 {
7558         char *p;
7559         const char *cp;
7560         char *start;
7561         char *endname;
7562         int metaflag;
7563         struct stat statb;
7564         DIR *dirp;
7565         struct dirent *dp;
7566         int atend;
7567         int matchdot;
7568         int esc;
7569
7570         metaflag = 0;
7571         start = name;
7572         for (p = name; esc = 0, *p; p += esc + 1) {
7573                 if (*p == '*' || *p == '?')
7574                         metaflag = 1;
7575                 else if (*p == '[') {
7576                         char *q = p + 1;
7577                         if (*q == '!')
7578                                 q++;
7579                         for (;;) {
7580                                 if (*q == '\\')
7581                                         q++;
7582                                 if (*q == '/' || *q == '\0')
7583                                         break;
7584                                 if (*++q == ']') {
7585                                         metaflag = 1;
7586                                         break;
7587                                 }
7588                         }
7589                 } else {
7590                         if (*p == '\\')
7591                                 esc++;
7592                         if (p[esc] == '/') {
7593                                 if (metaflag)
7594                                         break;
7595                                 start = p + esc + 1;
7596                         }
7597                 }
7598         }
7599         if (metaflag == 0) {    /* we've reached the end of the file name */
7600                 if (enddir != expdir)
7601                         metaflag++;
7602                 p = name;
7603                 do {
7604                         if (*p == '\\')
7605                                 p++;
7606                         *enddir++ = *p;
7607                 } while (*p++);
7608                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7609                         addfname(expdir);
7610                 return;
7611         }
7612         endname = p;
7613         if (name < start) {
7614                 p = name;
7615                 do {
7616                         if (*p == '\\')
7617                                 p++;
7618                         *enddir++ = *p++;
7619                 } while (p < start);
7620         }
7621         if (enddir == expdir) {
7622                 cp = ".";
7623         } else if (enddir == expdir + 1 && *expdir == '/') {
7624                 cp = "/";
7625         } else {
7626                 cp = expdir;
7627                 enddir[-1] = '\0';
7628         }
7629         dirp = opendir(cp);
7630         if (dirp == NULL)
7631                 return;
7632         if (enddir != expdir)
7633                 enddir[-1] = '/';
7634         if (*endname == 0) {
7635                 atend = 1;
7636         } else {
7637                 atend = 0;
7638                 *endname = '\0';
7639                 endname += esc + 1;
7640         }
7641         matchdot = 0;
7642         p = start;
7643         if (*p == '\\')
7644                 p++;
7645         if (*p == '.')
7646                 matchdot++;
7647         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7648                 if (dp->d_name[0] == '.' && !matchdot)
7649                         continue;
7650                 if (pmatch(start, dp->d_name)) {
7651                         if (atend) {
7652                                 strcpy(enddir, dp->d_name);
7653                                 addfname(expdir);
7654                         } else {
7655                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7656                                         continue;
7657                                 p[-1] = '/';
7658                                 expmeta(expdir, p, endname);
7659                         }
7660                 }
7661         }
7662         closedir(dirp);
7663         if (!atend)
7664                 endname[-esc - 1] = esc ? '\\' : '/';
7665 }
7666
7667 static struct strlist *
7668 msort(struct strlist *list, int len)
7669 {
7670         struct strlist *p, *q = NULL;
7671         struct strlist **lpp;
7672         int half;
7673         int n;
7674
7675         if (len <= 1)
7676                 return list;
7677         half = len >> 1;
7678         p = list;
7679         for (n = half; --n >= 0;) {
7680                 q = p;
7681                 p = p->next;
7682         }
7683         q->next = NULL;                 /* terminate first half of list */
7684         q = msort(list, half);          /* sort first half of list */
7685         p = msort(p, len - half);               /* sort second half */
7686         lpp = &list;
7687         for (;;) {
7688 #if ENABLE_LOCALE_SUPPORT
7689                 if (strcoll(p->text, q->text) < 0)
7690 #else
7691                 if (strcmp(p->text, q->text) < 0)
7692 #endif
7693                                                 {
7694                         *lpp = p;
7695                         lpp = &p->next;
7696                         p = *lpp;
7697                         if (p == NULL) {
7698                                 *lpp = q;
7699                                 break;
7700                         }
7701                 } else {
7702                         *lpp = q;
7703                         lpp = &q->next;
7704                         q = *lpp;
7705                         if (q == NULL) {
7706                                 *lpp = p;
7707                                 break;
7708                         }
7709                 }
7710         }
7711         return list;
7712 }
7713
7714 /*
7715  * Sort the results of file name expansion.  It calculates the number of
7716  * strings to sort and then calls msort (short for merge sort) to do the
7717  * work.
7718  */
7719 static struct strlist *
7720 expsort(struct strlist *str)
7721 {
7722         int len;
7723         struct strlist *sp;
7724
7725         len = 0;
7726         for (sp = str; sp; sp = sp->next)
7727                 len++;
7728         return msort(str, len);
7729 }
7730
7731 static void
7732 expandmeta(struct strlist *str /*, int flag*/)
7733 {
7734         /* TODO - EXP_REDIR */
7735
7736         while (str) {
7737                 char *expdir;
7738                 struct strlist **savelastp;
7739                 struct strlist *sp;
7740                 char *p;
7741
7742                 if (fflag)
7743                         goto nometa;
7744                 if (!hasmeta(str->text))
7745                         goto nometa;
7746                 savelastp = exparg.lastp;
7747
7748                 INT_OFF;
7749                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7750                 {
7751                         int i = strlen(str->text);
7752 //BUGGY estimation of how long expanded name can be
7753                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7754                 }
7755                 expmeta(expdir, expdir, p);
7756                 free(expdir);
7757                 if (p != str->text)
7758                         free(p);
7759                 INT_ON;
7760                 if (exparg.lastp == savelastp) {
7761                         /*
7762                          * no matches
7763                          */
7764  nometa:
7765                         *exparg.lastp = str;
7766                         rmescapes(str->text, 0, NULL);
7767                         exparg.lastp = &str->next;
7768                 } else {
7769                         *exparg.lastp = NULL;
7770                         *savelastp = sp = expsort(*savelastp);
7771                         while (sp->next != NULL)
7772                                 sp = sp->next;
7773                         exparg.lastp = &sp->next;
7774                 }
7775                 str = str->next;
7776         }
7777 }
7778 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7779
7780 /*
7781  * Perform variable substitution and command substitution on an argument,
7782  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7783  * perform splitting and file name expansion.  When arglist is NULL, perform
7784  * here document expansion.
7785  */
7786 static void
7787 expandarg(union node *arg, struct arglist *arglist, int flag)
7788 {
7789         struct strlist *sp;
7790         char *p;
7791
7792         argbackq = arg->narg.backquote;
7793         STARTSTACKSTR(expdest);
7794         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7795         argstr(arg->narg.text, flag);
7796         p = _STPUTC('\0', expdest);
7797         expdest = p - 1;
7798         if (arglist == NULL) {
7799                 /* here document expanded */
7800                 goto out;
7801         }
7802         p = grabstackstr(p);
7803         TRACE(("expandarg: p:'%s'\n", p));
7804         exparg.lastp = &exparg.list;
7805         /*
7806          * TODO - EXP_REDIR
7807          */
7808         if (flag & EXP_FULL) {
7809                 ifsbreakup(p, &exparg);
7810                 *exparg.lastp = NULL;
7811                 exparg.lastp = &exparg.list;
7812                 expandmeta(exparg.list /*, flag*/);
7813         } else {
7814                 sp = stzalloc(sizeof(*sp));
7815                 sp->text = p;
7816                 *exparg.lastp = sp;
7817                 exparg.lastp = &sp->next;
7818         }
7819         *exparg.lastp = NULL;
7820         if (exparg.list) {
7821                 *arglist->lastp = exparg.list;
7822                 arglist->lastp = exparg.lastp;
7823         }
7824
7825  out:
7826         ifsfree();
7827 }
7828
7829 /*
7830  * Expand shell variables and backquotes inside a here document.
7831  */
7832 static void
7833 expandhere(union node *arg, int fd)
7834 {
7835         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7836         full_write(fd, stackblock(), expdest - (char *)stackblock());
7837 }
7838
7839 /*
7840  * Returns true if the pattern matches the string.
7841  */
7842 static int
7843 patmatch(char *pattern, const char *string)
7844 {
7845         char *p = preglob(pattern, 0);
7846         int r = pmatch(p, string);
7847         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7848         return r;
7849 }
7850
7851 /*
7852  * See if a pattern matches in a case statement.
7853  */
7854 static int
7855 casematch(union node *pattern, char *val)
7856 {
7857         struct stackmark smark;
7858         int result;
7859
7860         setstackmark(&smark);
7861         argbackq = pattern->narg.backquote;
7862         STARTSTACKSTR(expdest);
7863         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7864         STACKSTRNUL(expdest);
7865         ifsfree();
7866         result = patmatch(stackblock(), val);
7867         popstackmark(&smark);
7868         return result;
7869 }
7870
7871
7872 /* ============ find_command */
7873
7874 struct builtincmd {
7875         const char *name;
7876         int (*builtin)(int, char **) FAST_FUNC;
7877         /* unsigned flags; */
7878 };
7879 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7880 /* "regular" builtins always take precedence over commands,
7881  * regardless of PATH=....%builtin... position */
7882 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7883 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7884
7885 struct cmdentry {
7886         smallint cmdtype;       /* CMDxxx */
7887         union param {
7888                 int index;
7889                 /* index >= 0 for commands without path (slashes) */
7890                 /* (TODO: what exactly does the value mean? PATH position?) */
7891                 /* index == -1 for commands with slashes */
7892                 /* index == (-2 - applet_no) for NOFORK applets */
7893                 const struct builtincmd *cmd;
7894                 struct funcnode *func;
7895         } u;
7896 };
7897 /* values of cmdtype */
7898 #define CMDUNKNOWN      -1      /* no entry in table for command */
7899 #define CMDNORMAL       0       /* command is an executable program */
7900 #define CMDFUNCTION     1       /* command is a shell function */
7901 #define CMDBUILTIN      2       /* command is a shell builtin */
7902
7903 /* action to find_command() */
7904 #define DO_ERR          0x01    /* prints errors */
7905 #define DO_ABS          0x02    /* checks absolute paths */
7906 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7907 #define DO_ALTPATH      0x08    /* using alternate path */
7908 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7909
7910 static void find_command(char *, struct cmdentry *, int, const char *);
7911
7912
7913 /* ============ Hashing commands */
7914
7915 /*
7916  * When commands are first encountered, they are entered in a hash table.
7917  * This ensures that a full path search will not have to be done for them
7918  * on each invocation.
7919  *
7920  * We should investigate converting to a linear search, even though that
7921  * would make the command name "hash" a misnomer.
7922  */
7923
7924 struct tblentry {
7925         struct tblentry *next;  /* next entry in hash chain */
7926         union param param;      /* definition of builtin function */
7927         smallint cmdtype;       /* CMDxxx */
7928         char rehash;            /* if set, cd done since entry created */
7929         char cmdname[1];        /* name of command */
7930 };
7931
7932 static struct tblentry **cmdtable;
7933 #define INIT_G_cmdtable() do { \
7934         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7935 } while (0)
7936
7937 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7938
7939
7940 static void
7941 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7942 {
7943 #if ENABLE_FEATURE_SH_STANDALONE
7944         if (applet_no >= 0) {
7945                 if (APPLET_IS_NOEXEC(applet_no)) {
7946                         clearenv();
7947                         while (*envp)
7948                                 putenv(*envp++);
7949                         popredir(/*drop:*/ 1);
7950                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7951                 }
7952                 /* re-exec ourselves with the new arguments */
7953                 execve(bb_busybox_exec_path, argv, envp);
7954                 /* If they called chroot or otherwise made the binary no longer
7955                  * executable, fall through */
7956         }
7957 #endif
7958
7959  repeat:
7960 #ifdef SYSV
7961         do {
7962                 execve(cmd, argv, envp);
7963         } while (errno == EINTR);
7964 #else
7965         execve(cmd, argv, envp);
7966 #endif
7967         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7968                 /* Run "cmd" as a shell script:
7969                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7970                  * "If the execve() function fails with ENOEXEC, the shell
7971                  * shall execute a command equivalent to having a shell invoked
7972                  * with the command name as its first operand,
7973                  * with any remaining arguments passed to the new shell"
7974                  *
7975                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7976                  * just call ourselves.
7977                  *
7978                  * Note that bash reads ~80 chars of the file, and if it sees
7979                  * a zero byte before it sees newline, it doesn't try to
7980                  * interpret it, but fails with "cannot execute binary file"
7981                  * message and exit code 126. For one, this prevents attempts
7982                  * to interpret foreign ELF binaries as shell scripts.
7983                  */
7984                 argv[0] = (char*) cmd;
7985                 cmd = bb_busybox_exec_path;
7986                 /* NB: this is only possible because all callers of shellexec()
7987                  * ensure that the argv[-1] slot exists!
7988                  */
7989                 argv--;
7990                 argv[0] = (char*) "ash";
7991                 goto repeat;
7992         }
7993 }
7994
7995 /*
7996  * Exec a program.  Never returns.  If you change this routine, you may
7997  * have to change the find_command routine as well.
7998  * argv[-1] must exist and be writable! See tryexec() for why.
7999  */
8000 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8001 static void shellexec(char *prog, char **argv, const char *path, int idx)
8002 {
8003         char *cmdname;
8004         int e;
8005         char **envp;
8006         int exerrno;
8007         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8008
8009         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8010         if (strchr(prog, '/') != NULL
8011 #if ENABLE_FEATURE_SH_STANDALONE
8012          || (applet_no = find_applet_by_name(prog)) >= 0
8013 #endif
8014         ) {
8015                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8016                 if (applet_no >= 0) {
8017                         /* We tried execing ourself, but it didn't work.
8018                          * Maybe /proc/self/exe doesn't exist?
8019                          * Try $PATH search.
8020                          */
8021                         goto try_PATH;
8022                 }
8023                 e = errno;
8024         } else {
8025  try_PATH:
8026                 e = ENOENT;
8027                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8028                         if (--idx < 0 && pathopt == NULL) {
8029                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8030                                 if (errno != ENOENT && errno != ENOTDIR)
8031                                         e = errno;
8032                         }
8033                         stunalloc(cmdname);
8034                 }
8035         }
8036
8037         /* Map to POSIX errors */
8038         switch (e) {
8039         case EACCES:
8040                 exerrno = 126;
8041                 break;
8042         case ENOENT:
8043                 exerrno = 127;
8044                 break;
8045         default:
8046                 exerrno = 2;
8047                 break;
8048         }
8049         exitstatus = exerrno;
8050         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8051                 prog, e, suppress_int));
8052         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8053         /* NOTREACHED */
8054 }
8055
8056 static void
8057 printentry(struct tblentry *cmdp)
8058 {
8059         int idx;
8060         const char *path;
8061         char *name;
8062
8063         idx = cmdp->param.index;
8064         path = pathval();
8065         do {
8066                 name = path_advance(&path, cmdp->cmdname);
8067                 stunalloc(name);
8068         } while (--idx >= 0);
8069         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8070 }
8071
8072 /*
8073  * Clear out command entries.  The argument specifies the first entry in
8074  * PATH which has changed.
8075  */
8076 static void
8077 clearcmdentry(int firstchange)
8078 {
8079         struct tblentry **tblp;
8080         struct tblentry **pp;
8081         struct tblentry *cmdp;
8082
8083         INT_OFF;
8084         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8085                 pp = tblp;
8086                 while ((cmdp = *pp) != NULL) {
8087                         if ((cmdp->cmdtype == CMDNORMAL &&
8088                              cmdp->param.index >= firstchange)
8089                          || (cmdp->cmdtype == CMDBUILTIN &&
8090                              builtinloc >= firstchange)
8091                         ) {
8092                                 *pp = cmdp->next;
8093                                 free(cmdp);
8094                         } else {
8095                                 pp = &cmdp->next;
8096                         }
8097                 }
8098         }
8099         INT_ON;
8100 }
8101
8102 /*
8103  * Locate a command in the command hash table.  If "add" is nonzero,
8104  * add the command to the table if it is not already present.  The
8105  * variable "lastcmdentry" is set to point to the address of the link
8106  * pointing to the entry, so that delete_cmd_entry can delete the
8107  * entry.
8108  *
8109  * Interrupts must be off if called with add != 0.
8110  */
8111 static struct tblentry **lastcmdentry;
8112
8113 static struct tblentry *
8114 cmdlookup(const char *name, int add)
8115 {
8116         unsigned int hashval;
8117         const char *p;
8118         struct tblentry *cmdp;
8119         struct tblentry **pp;
8120
8121         p = name;
8122         hashval = (unsigned char)*p << 4;
8123         while (*p)
8124                 hashval += (unsigned char)*p++;
8125         hashval &= 0x7FFF;
8126         pp = &cmdtable[hashval % CMDTABLESIZE];
8127         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8128                 if (strcmp(cmdp->cmdname, name) == 0)
8129                         break;
8130                 pp = &cmdp->next;
8131         }
8132         if (add && cmdp == NULL) {
8133                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8134                                 + strlen(name)
8135                                 /* + 1 - already done because
8136                                  * tblentry::cmdname is char[1] */);
8137                 /*cmdp->next = NULL; - ckzalloc did it */
8138                 cmdp->cmdtype = CMDUNKNOWN;
8139                 strcpy(cmdp->cmdname, name);
8140         }
8141         lastcmdentry = pp;
8142         return cmdp;
8143 }
8144
8145 /*
8146  * Delete the command entry returned on the last lookup.
8147  */
8148 static void
8149 delete_cmd_entry(void)
8150 {
8151         struct tblentry *cmdp;
8152
8153         INT_OFF;
8154         cmdp = *lastcmdentry;
8155         *lastcmdentry = cmdp->next;
8156         if (cmdp->cmdtype == CMDFUNCTION)
8157                 freefunc(cmdp->param.func);
8158         free(cmdp);
8159         INT_ON;
8160 }
8161
8162 /*
8163  * Add a new command entry, replacing any existing command entry for
8164  * the same name - except special builtins.
8165  */
8166 static void
8167 addcmdentry(char *name, struct cmdentry *entry)
8168 {
8169         struct tblentry *cmdp;
8170
8171         cmdp = cmdlookup(name, 1);
8172         if (cmdp->cmdtype == CMDFUNCTION) {
8173                 freefunc(cmdp->param.func);
8174         }
8175         cmdp->cmdtype = entry->cmdtype;
8176         cmdp->param = entry->u;
8177         cmdp->rehash = 0;
8178 }
8179
8180 static int FAST_FUNC
8181 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8182 {
8183         struct tblentry **pp;
8184         struct tblentry *cmdp;
8185         int c;
8186         struct cmdentry entry;
8187         char *name;
8188
8189         if (nextopt("r") != '\0') {
8190                 clearcmdentry(0);
8191                 return 0;
8192         }
8193
8194         if (*argptr == NULL) {
8195                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8196                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8197                                 if (cmdp->cmdtype == CMDNORMAL)
8198                                         printentry(cmdp);
8199                         }
8200                 }
8201                 return 0;
8202         }
8203
8204         c = 0;
8205         while ((name = *argptr) != NULL) {
8206                 cmdp = cmdlookup(name, 0);
8207                 if (cmdp != NULL
8208                  && (cmdp->cmdtype == CMDNORMAL
8209                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8210                 ) {
8211                         delete_cmd_entry();
8212                 }
8213                 find_command(name, &entry, DO_ERR, pathval());
8214                 if (entry.cmdtype == CMDUNKNOWN)
8215                         c = 1;
8216                 argptr++;
8217         }
8218         return c;
8219 }
8220
8221 /*
8222  * Called when a cd is done.  Marks all commands so the next time they
8223  * are executed they will be rehashed.
8224  */
8225 static void
8226 hashcd(void)
8227 {
8228         struct tblentry **pp;
8229         struct tblentry *cmdp;
8230
8231         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8232                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8233                         if (cmdp->cmdtype == CMDNORMAL
8234                          || (cmdp->cmdtype == CMDBUILTIN
8235                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8236                              && builtinloc > 0)
8237                         ) {
8238                                 cmdp->rehash = 1;
8239                         }
8240                 }
8241         }
8242 }
8243
8244 /*
8245  * Fix command hash table when PATH changed.
8246  * Called before PATH is changed.  The argument is the new value of PATH;
8247  * pathval() still returns the old value at this point.
8248  * Called with interrupts off.
8249  */
8250 static void FAST_FUNC
8251 changepath(const char *new)
8252 {
8253         const char *old;
8254         int firstchange;
8255         int idx;
8256         int idx_bltin;
8257
8258         old = pathval();
8259         firstchange = 9999;     /* assume no change */
8260         idx = 0;
8261         idx_bltin = -1;
8262         for (;;) {
8263                 if (*old != *new) {
8264                         firstchange = idx;
8265                         if ((*old == '\0' && *new == ':')
8266                          || (*old == ':' && *new == '\0')
8267                         ) {
8268                                 firstchange++;
8269                         }
8270                         old = new;      /* ignore subsequent differences */
8271                 }
8272                 if (*new == '\0')
8273                         break;
8274                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8275                         idx_bltin = idx;
8276                 if (*new == ':')
8277                         idx++;
8278                 new++;
8279                 old++;
8280         }
8281         if (builtinloc < 0 && idx_bltin >= 0)
8282                 builtinloc = idx_bltin;             /* zap builtins */
8283         if (builtinloc >= 0 && idx_bltin < 0)
8284                 firstchange = 0;
8285         clearcmdentry(firstchange);
8286         builtinloc = idx_bltin;
8287 }
8288 enum {
8289         TEOF,
8290         TNL,
8291         TREDIR,
8292         TWORD,
8293         TSEMI,
8294         TBACKGND,
8295         TAND,
8296         TOR,
8297         TPIPE,
8298         TLP,
8299         TRP,
8300         TENDCASE,
8301         TENDBQUOTE,
8302         TNOT,
8303         TCASE,
8304         TDO,
8305         TDONE,
8306         TELIF,
8307         TELSE,
8308         TESAC,
8309         TFI,
8310         TFOR,
8311 #if BASH_FUNCTION
8312         TFUNCTION,
8313 #endif
8314         TIF,
8315         TIN,
8316         TTHEN,
8317         TUNTIL,
8318         TWHILE,
8319         TBEGIN,
8320         TEND
8321 };
8322 typedef smallint token_id_t;
8323
8324 /* Nth bit indicates if token marks the end of a list */
8325 enum {
8326         tokendlist = 0
8327         /*  0 */ | (1u << TEOF)
8328         /*  1 */ | (0u << TNL)
8329         /*  2 */ | (0u << TREDIR)
8330         /*  3 */ | (0u << TWORD)
8331         /*  4 */ | (0u << TSEMI)
8332         /*  5 */ | (0u << TBACKGND)
8333         /*  6 */ | (0u << TAND)
8334         /*  7 */ | (0u << TOR)
8335         /*  8 */ | (0u << TPIPE)
8336         /*  9 */ | (0u << TLP)
8337         /* 10 */ | (1u << TRP)
8338         /* 11 */ | (1u << TENDCASE)
8339         /* 12 */ | (1u << TENDBQUOTE)
8340         /* 13 */ | (0u << TNOT)
8341         /* 14 */ | (0u << TCASE)
8342         /* 15 */ | (1u << TDO)
8343         /* 16 */ | (1u << TDONE)
8344         /* 17 */ | (1u << TELIF)
8345         /* 18 */ | (1u << TELSE)
8346         /* 19 */ | (1u << TESAC)
8347         /* 20 */ | (1u << TFI)
8348         /* 21 */ | (0u << TFOR)
8349 #if BASH_FUNCTION
8350         /* 22 */ | (0u << TFUNCTION)
8351 #endif
8352         /* 23 */ | (0u << TIF)
8353         /* 24 */ | (0u << TIN)
8354         /* 25 */ | (1u << TTHEN)
8355         /* 26 */ | (0u << TUNTIL)
8356         /* 27 */ | (0u << TWHILE)
8357         /* 28 */ | (0u << TBEGIN)
8358         /* 29 */ | (1u << TEND)
8359         , /* thus far 29 bits used */
8360 };
8361
8362 static const char *const tokname_array[] = {
8363         "end of file",
8364         "newline",
8365         "redirection",
8366         "word",
8367         ";",
8368         "&",
8369         "&&",
8370         "||",
8371         "|",
8372         "(",
8373         ")",
8374         ";;",
8375         "`",
8376 #define KWDOFFSET 13
8377         /* the following are keywords */
8378         "!",
8379         "case",
8380         "do",
8381         "done",
8382         "elif",
8383         "else",
8384         "esac",
8385         "fi",
8386         "for",
8387 #if BASH_FUNCTION
8388         "function",
8389 #endif
8390         "if",
8391         "in",
8392         "then",
8393         "until",
8394         "while",
8395         "{",
8396         "}",
8397 };
8398
8399 /* Wrapper around strcmp for qsort/bsearch/... */
8400 static int
8401 pstrcmp(const void *a, const void *b)
8402 {
8403         return strcmp((char*)a, *(char**)b);
8404 }
8405
8406 static const char *const *
8407 findkwd(const char *s)
8408 {
8409         return bsearch(s, tokname_array + KWDOFFSET,
8410                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8411                         sizeof(tokname_array[0]), pstrcmp);
8412 }
8413
8414 /*
8415  * Locate and print what a word is...
8416  */
8417 static int
8418 describe_command(char *command, const char *path, int describe_command_verbose)
8419 {
8420         struct cmdentry entry;
8421 #if ENABLE_ASH_ALIAS
8422         const struct alias *ap;
8423 #endif
8424
8425         path = path ? path : pathval();
8426
8427         if (describe_command_verbose) {
8428                 out1str(command);
8429         }
8430
8431         /* First look at the keywords */
8432         if (findkwd(command)) {
8433                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8434                 goto out;
8435         }
8436
8437 #if ENABLE_ASH_ALIAS
8438         /* Then look at the aliases */
8439         ap = lookupalias(command, 0);
8440         if (ap != NULL) {
8441                 if (!describe_command_verbose) {
8442                         out1str("alias ");
8443                         printalias(ap);
8444                         return 0;
8445                 }
8446                 out1fmt(" is an alias for %s", ap->val);
8447                 goto out;
8448         }
8449 #endif
8450         /* Brute force */
8451         find_command(command, &entry, DO_ABS, path);
8452
8453         switch (entry.cmdtype) {
8454         case CMDNORMAL: {
8455                 int j = entry.u.index;
8456                 char *p;
8457                 if (j < 0) {
8458                         p = command;
8459                 } else {
8460                         do {
8461                                 p = path_advance(&path, command);
8462                                 stunalloc(p);
8463                         } while (--j >= 0);
8464                 }
8465                 if (describe_command_verbose) {
8466                         out1fmt(" is %s", p);
8467                 } else {
8468                         out1str(p);
8469                 }
8470                 break;
8471         }
8472
8473         case CMDFUNCTION:
8474                 if (describe_command_verbose) {
8475                         out1str(" is a shell function");
8476                 } else {
8477                         out1str(command);
8478                 }
8479                 break;
8480
8481         case CMDBUILTIN:
8482                 if (describe_command_verbose) {
8483                         out1fmt(" is a %sshell builtin",
8484                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8485                                         "special " : nullstr
8486                         );
8487                 } else {
8488                         out1str(command);
8489                 }
8490                 break;
8491
8492         default:
8493                 if (describe_command_verbose) {
8494                         out1str(": not found\n");
8495                 }
8496                 return 127;
8497         }
8498  out:
8499         out1str("\n");
8500         return 0;
8501 }
8502
8503 static int FAST_FUNC
8504 typecmd(int argc UNUSED_PARAM, char **argv)
8505 {
8506         int i = 1;
8507         int err = 0;
8508         int verbose = 1;
8509
8510         /* type -p ... ? (we don't bother checking for 'p') */
8511         if (argv[1] && argv[1][0] == '-') {
8512                 i++;
8513                 verbose = 0;
8514         }
8515         while (argv[i]) {
8516                 err |= describe_command(argv[i++], NULL, verbose);
8517         }
8518         return err;
8519 }
8520
8521 #if ENABLE_ASH_CMDCMD
8522 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8523 static char **
8524 parse_command_args(char **argv, const char **path)
8525 {
8526         char *cp, c;
8527
8528         for (;;) {
8529                 cp = *++argv;
8530                 if (!cp)
8531                         return NULL;
8532                 if (*cp++ != '-')
8533                         break;
8534                 c = *cp++;
8535                 if (!c)
8536                         break;
8537                 if (c == '-' && !*cp) {
8538                         if (!*++argv)
8539                                 return NULL;
8540                         break;
8541                 }
8542                 do {
8543                         switch (c) {
8544                         case 'p':
8545                                 *path = bb_default_path;
8546                                 break;
8547                         default:
8548                                 /* run 'typecmd' for other options */
8549                                 return NULL;
8550                         }
8551                         c = *cp++;
8552                 } while (c);
8553         }
8554         return argv;
8555 }
8556
8557 static int FAST_FUNC
8558 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8559 {
8560         char *cmd;
8561         int c;
8562         enum {
8563                 VERIFY_BRIEF = 1,
8564                 VERIFY_VERBOSE = 2,
8565         } verify = 0;
8566         const char *path = NULL;
8567
8568         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8569          * never reaches this function.
8570          */
8571
8572         while ((c = nextopt("pvV")) != '\0')
8573                 if (c == 'V')
8574                         verify |= VERIFY_VERBOSE;
8575                 else if (c == 'v')
8576                         /*verify |= VERIFY_BRIEF*/;
8577 #if DEBUG
8578                 else if (c != 'p')
8579                         abort();
8580 #endif
8581                 else
8582                         path = bb_default_path;
8583
8584         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8585         cmd = *argptr;
8586         if (/*verify && */ cmd)
8587                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8588
8589         return 0;
8590 }
8591 #endif
8592
8593
8594 /*static int funcblocksize;     // size of structures in function */
8595 /*static int funcstringsize;    // size of strings in node */
8596 static void *funcblock;         /* block to allocate function from */
8597 static char *funcstring_end;    /* end of block to allocate strings from */
8598
8599 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8600         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8601         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8602         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8603         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8604         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8605         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8606         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8607         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8608         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8609         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8610         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8611         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8612         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8613         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8614         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8615         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8616         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8617 #if BASH_REDIR_OUTPUT
8618         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8619 #endif
8620         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8621         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8622         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8623         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8624         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8625         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8626         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8627         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8628         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8629 };
8630
8631 static int calcsize(int funcblocksize, union node *n);
8632
8633 static int
8634 sizenodelist(int funcblocksize, struct nodelist *lp)
8635 {
8636         while (lp) {
8637                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8638                 funcblocksize = calcsize(funcblocksize, lp->n);
8639                 lp = lp->next;
8640         }
8641         return funcblocksize;
8642 }
8643
8644 static int
8645 calcsize(int funcblocksize, union node *n)
8646 {
8647         if (n == NULL)
8648                 return funcblocksize;
8649         funcblocksize += nodesize[n->type];
8650         switch (n->type) {
8651         case NCMD:
8652                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8653                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8654                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8655                 break;
8656         case NPIPE:
8657                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8658                 break;
8659         case NREDIR:
8660         case NBACKGND:
8661         case NSUBSHELL:
8662                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8663                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8664                 break;
8665         case NAND:
8666         case NOR:
8667         case NSEMI:
8668         case NWHILE:
8669         case NUNTIL:
8670                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8671                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8672                 break;
8673         case NIF:
8674                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8675                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8676                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8677                 break;
8678         case NFOR:
8679                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8680                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8681                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8682                 break;
8683         case NCASE:
8684                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8685                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8686                 break;
8687         case NCLIST:
8688                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8689                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8690                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8691                 break;
8692         case NDEFUN:
8693                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8694                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8695                 break;
8696         case NARG:
8697                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8698                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8699                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8700                 break;
8701         case NTO:
8702 #if BASH_REDIR_OUTPUT
8703         case NTO2:
8704 #endif
8705         case NCLOBBER:
8706         case NFROM:
8707         case NFROMTO:
8708         case NAPPEND:
8709                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8710                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8711                 break;
8712         case NTOFD:
8713         case NFROMFD:
8714                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8715                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8716         break;
8717         case NHERE:
8718         case NXHERE:
8719                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8720                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8721                 break;
8722         case NNOT:
8723                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8724                 break;
8725         };
8726         return funcblocksize;
8727 }
8728
8729 static char *
8730 nodeckstrdup(char *s)
8731 {
8732         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8733         return strcpy(funcstring_end, s);
8734 }
8735
8736 static union node *copynode(union node *);
8737
8738 static struct nodelist *
8739 copynodelist(struct nodelist *lp)
8740 {
8741         struct nodelist *start;
8742         struct nodelist **lpp;
8743
8744         lpp = &start;
8745         while (lp) {
8746                 *lpp = funcblock;
8747                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8748                 (*lpp)->n = copynode(lp->n);
8749                 lp = lp->next;
8750                 lpp = &(*lpp)->next;
8751         }
8752         *lpp = NULL;
8753         return start;
8754 }
8755
8756 static union node *
8757 copynode(union node *n)
8758 {
8759         union node *new;
8760
8761         if (n == NULL)
8762                 return NULL;
8763         new = funcblock;
8764         funcblock = (char *) funcblock + nodesize[n->type];
8765
8766         switch (n->type) {
8767         case NCMD:
8768                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8769                 new->ncmd.args = copynode(n->ncmd.args);
8770                 new->ncmd.assign = copynode(n->ncmd.assign);
8771                 new->ncmd.linno = n->ncmd.linno;
8772                 break;
8773         case NPIPE:
8774                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8775                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8776                 break;
8777         case NREDIR:
8778         case NBACKGND:
8779         case NSUBSHELL:
8780                 new->nredir.redirect = copynode(n->nredir.redirect);
8781                 new->nredir.n = copynode(n->nredir.n);
8782                 new->nredir.linno = n->nredir.linno;
8783                 break;
8784         case NAND:
8785         case NOR:
8786         case NSEMI:
8787         case NWHILE:
8788         case NUNTIL:
8789                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8790                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8791                 break;
8792         case NIF:
8793                 new->nif.elsepart = copynode(n->nif.elsepart);
8794                 new->nif.ifpart = copynode(n->nif.ifpart);
8795                 new->nif.test = copynode(n->nif.test);
8796                 break;
8797         case NFOR:
8798                 new->nfor.var = nodeckstrdup(n->nfor.var);
8799                 new->nfor.body = copynode(n->nfor.body);
8800                 new->nfor.args = copynode(n->nfor.args);
8801                 new->nfor.linno = n->nfor.linno;
8802                 break;
8803         case NCASE:
8804                 new->ncase.cases = copynode(n->ncase.cases);
8805                 new->ncase.expr = copynode(n->ncase.expr);
8806                 new->ncase.linno = n->ncase.linno;
8807                 break;
8808         case NCLIST:
8809                 new->nclist.body = copynode(n->nclist.body);
8810                 new->nclist.pattern = copynode(n->nclist.pattern);
8811                 new->nclist.next = copynode(n->nclist.next);
8812                 break;
8813         case NDEFUN:
8814                 new->ndefun.body = copynode(n->ndefun.body);
8815                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8816                 new->ndefun.linno = n->ndefun.linno;
8817                 break;
8818         case NARG:
8819                 new->narg.backquote = copynodelist(n->narg.backquote);
8820                 new->narg.text = nodeckstrdup(n->narg.text);
8821                 new->narg.next = copynode(n->narg.next);
8822                 break;
8823         case NTO:
8824 #if BASH_REDIR_OUTPUT
8825         case NTO2:
8826 #endif
8827         case NCLOBBER:
8828         case NFROM:
8829         case NFROMTO:
8830         case NAPPEND:
8831                 new->nfile.fname = copynode(n->nfile.fname);
8832                 new->nfile.fd = n->nfile.fd;
8833                 new->nfile.next = copynode(n->nfile.next);
8834                 break;
8835         case NTOFD:
8836         case NFROMFD:
8837                 new->ndup.vname = copynode(n->ndup.vname);
8838                 new->ndup.dupfd = n->ndup.dupfd;
8839                 new->ndup.fd = n->ndup.fd;
8840                 new->ndup.next = copynode(n->ndup.next);
8841                 break;
8842         case NHERE:
8843         case NXHERE:
8844                 new->nhere.doc = copynode(n->nhere.doc);
8845                 new->nhere.fd = n->nhere.fd;
8846                 new->nhere.next = copynode(n->nhere.next);
8847                 break;
8848         case NNOT:
8849                 new->nnot.com = copynode(n->nnot.com);
8850                 break;
8851         };
8852         new->type = n->type;
8853         return new;
8854 }
8855
8856 /*
8857  * Make a copy of a parse tree.
8858  */
8859 static struct funcnode *
8860 copyfunc(union node *n)
8861 {
8862         struct funcnode *f;
8863         size_t blocksize;
8864
8865         /*funcstringsize = 0;*/
8866         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8867         f = ckzalloc(blocksize /* + funcstringsize */);
8868         funcblock = (char *) f + offsetof(struct funcnode, n);
8869         funcstring_end = (char *) f + blocksize;
8870         copynode(n);
8871         /* f->count = 0; - ckzalloc did it */
8872         return f;
8873 }
8874
8875 /*
8876  * Define a shell function.
8877  */
8878 static void
8879 defun(union node *func)
8880 {
8881         struct cmdentry entry;
8882
8883         INT_OFF;
8884         entry.cmdtype = CMDFUNCTION;
8885         entry.u.func = copyfunc(func);
8886         addcmdentry(func->ndefun.text, &entry);
8887         INT_ON;
8888 }
8889
8890 /* Reasons for skipping commands (see comment on breakcmd routine) */
8891 #define SKIPBREAK      (1 << 0)
8892 #define SKIPCONT       (1 << 1)
8893 #define SKIPFUNC       (1 << 2)
8894 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8895 static int skipcount;           /* number of levels to skip */
8896 static int loopnest;            /* current loop nesting level */
8897 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8898
8899 /* Forward decl way out to parsing code - dotrap needs it */
8900 static int evalstring(char *s, int flags);
8901
8902 /* Called to execute a trap.
8903  * Single callsite - at the end of evaltree().
8904  * If we return non-zero, evaltree raises EXEXIT exception.
8905  *
8906  * Perhaps we should avoid entering new trap handlers
8907  * while we are executing a trap handler. [is it a TODO?]
8908  */
8909 static void
8910 dotrap(void)
8911 {
8912         uint8_t *g;
8913         int sig;
8914         uint8_t last_status;
8915
8916         if (!pending_sig)
8917                 return;
8918
8919         last_status = exitstatus;
8920         pending_sig = 0;
8921         barrier();
8922
8923         TRACE(("dotrap entered\n"));
8924         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8925                 char *p;
8926
8927                 if (!*g)
8928                         continue;
8929
8930                 if (evalskip) {
8931                         pending_sig = sig;
8932                         break;
8933                 }
8934
8935                 p = trap[sig];
8936                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8937                  * don't upset it by resetting gotsig[SIGINT-1] */
8938                 if (sig == SIGINT && !p)
8939                         continue;
8940
8941                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8942                 *g = 0;
8943                 if (!p)
8944                         continue;
8945                 evalstring(p, 0);
8946         }
8947         exitstatus = last_status;
8948         TRACE(("dotrap returns\n"));
8949 }
8950
8951 /* forward declarations - evaluation is fairly recursive business... */
8952 static int evalloop(union node *, int);
8953 static int evalfor(union node *, int);
8954 static int evalcase(union node *, int);
8955 static int evalsubshell(union node *, int);
8956 static void expredir(union node *);
8957 static int evalpipe(union node *, int);
8958 static int evalcommand(union node *, int);
8959 static int evalbltin(const struct builtincmd *, int, char **, int);
8960 static void prehash(union node *);
8961
8962 /*
8963  * Evaluate a parse tree.  The value is left in the global variable
8964  * exitstatus.
8965  */
8966 static int
8967 evaltree(union node *n, int flags)
8968 {
8969         int checkexit = 0;
8970         int (*evalfn)(union node *, int);
8971         int status = 0;
8972
8973         if (n == NULL) {
8974                 TRACE(("evaltree(NULL) called\n"));
8975                 goto out;
8976         }
8977         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8978
8979         dotrap();
8980
8981         switch (n->type) {
8982         default:
8983 #if DEBUG
8984                 out1fmt("Node type = %d\n", n->type);
8985                 fflush_all();
8986                 break;
8987 #endif
8988         case NNOT:
8989                 status = !evaltree(n->nnot.com, EV_TESTED);
8990                 goto setstatus;
8991         case NREDIR:
8992                 errlinno = lineno = n->nredir.linno;
8993                 if (funcline)
8994                         lineno -= funcline - 1;
8995                 expredir(n->nredir.redirect);
8996                 pushredir(n->nredir.redirect);
8997                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8998                 if (!status) {
8999                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9000                 }
9001                 if (n->nredir.redirect)
9002                         popredir(/*drop:*/ 0);
9003                 goto setstatus;
9004         case NCMD:
9005                 evalfn = evalcommand;
9006  checkexit:
9007                 if (eflag && !(flags & EV_TESTED))
9008                         checkexit = ~0;
9009                 goto calleval;
9010         case NFOR:
9011                 evalfn = evalfor;
9012                 goto calleval;
9013         case NWHILE:
9014         case NUNTIL:
9015                 evalfn = evalloop;
9016                 goto calleval;
9017         case NSUBSHELL:
9018         case NBACKGND:
9019                 evalfn = evalsubshell;
9020                 goto checkexit;
9021         case NPIPE:
9022                 evalfn = evalpipe;
9023                 goto checkexit;
9024         case NCASE:
9025                 evalfn = evalcase;
9026                 goto calleval;
9027         case NAND:
9028         case NOR:
9029         case NSEMI: {
9030
9031 #if NAND + 1 != NOR
9032 #error NAND + 1 != NOR
9033 #endif
9034 #if NOR + 1 != NSEMI
9035 #error NOR + 1 != NSEMI
9036 #endif
9037                 unsigned is_or = n->type - NAND;
9038                 status = evaltree(
9039                         n->nbinary.ch1,
9040                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9041                 );
9042                 if ((!status) == is_or || evalskip)
9043                         break;
9044                 n = n->nbinary.ch2;
9045  evaln:
9046                 evalfn = evaltree;
9047  calleval:
9048                 status = evalfn(n, flags);
9049                 goto setstatus;
9050         }
9051         case NIF:
9052                 status = evaltree(n->nif.test, EV_TESTED);
9053                 if (evalskip)
9054                         break;
9055                 if (!status) {
9056                         n = n->nif.ifpart;
9057                         goto evaln;
9058                 }
9059                 if (n->nif.elsepart) {
9060                         n = n->nif.elsepart;
9061                         goto evaln;
9062                 }
9063                 status = 0;
9064                 goto setstatus;
9065         case NDEFUN:
9066                 defun(n);
9067                 /* Not necessary. To test it:
9068                  * "false; f() { qwerty; }; echo $?" should print 0.
9069                  */
9070                 /* status = 0; */
9071  setstatus:
9072                 exitstatus = status;
9073                 break;
9074         }
9075  out:
9076         /* Order of checks below is important:
9077          * signal handlers trigger before exit caused by "set -e".
9078          */
9079         dotrap();
9080
9081         if (checkexit & status)
9082                 raise_exception(EXEXIT);
9083         if (flags & EV_EXIT)
9084                 raise_exception(EXEXIT);
9085
9086         TRACE(("leaving evaltree (no interrupts)\n"));
9087         return exitstatus;
9088 }
9089
9090 static int
9091 skiploop(void)
9092 {
9093         int skip = evalskip;
9094
9095         switch (skip) {
9096         case 0:
9097                 break;
9098         case SKIPBREAK:
9099         case SKIPCONT:
9100                 if (--skipcount <= 0) {
9101                         evalskip = 0;
9102                         break;
9103                 }
9104                 skip = SKIPBREAK;
9105                 break;
9106         }
9107         return skip;
9108 }
9109
9110 static int
9111 evalloop(union node *n, int flags)
9112 {
9113         int skip;
9114         int status;
9115
9116         loopnest++;
9117         status = 0;
9118         flags &= EV_TESTED;
9119         do {
9120                 int i;
9121
9122                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9123                 skip = skiploop();
9124                 if (skip == SKIPFUNC)
9125                         status = i;
9126                 if (skip)
9127                         continue;
9128                 if (n->type != NWHILE)
9129                         i = !i;
9130                 if (i != 0)
9131                         break;
9132                 status = evaltree(n->nbinary.ch2, flags);
9133                 skip = skiploop();
9134         } while (!(skip & ~SKIPCONT));
9135         loopnest--;
9136
9137         return status;
9138 }
9139
9140 static int
9141 evalfor(union node *n, int flags)
9142 {
9143         struct arglist arglist;
9144         union node *argp;
9145         struct strlist *sp;
9146         struct stackmark smark;
9147         int status = 0;
9148
9149         errlinno = lineno = n->ncase.linno;
9150         if (funcline)
9151                 lineno -= funcline - 1;
9152
9153         setstackmark(&smark);
9154         arglist.list = NULL;
9155         arglist.lastp = &arglist.list;
9156         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9157                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9158         }
9159         *arglist.lastp = NULL;
9160
9161         loopnest++;
9162         flags &= EV_TESTED;
9163         for (sp = arglist.list; sp; sp = sp->next) {
9164                 setvar0(n->nfor.var, sp->text);
9165                 status = evaltree(n->nfor.body, flags);
9166                 if (skiploop() & ~SKIPCONT)
9167                         break;
9168         }
9169         loopnest--;
9170         popstackmark(&smark);
9171
9172         return status;
9173 }
9174
9175 static int
9176 evalcase(union node *n, int flags)
9177 {
9178         union node *cp;
9179         union node *patp;
9180         struct arglist arglist;
9181         struct stackmark smark;
9182         int status = 0;
9183
9184         errlinno = lineno = n->ncase.linno;
9185         if (funcline)
9186                 lineno -= funcline - 1;
9187
9188         setstackmark(&smark);
9189         arglist.list = NULL;
9190         arglist.lastp = &arglist.list;
9191         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9192         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9193                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9194                         if (casematch(patp, arglist.list->text)) {
9195                                 /* Ensure body is non-empty as otherwise
9196                                  * EV_EXIT may prevent us from setting the
9197                                  * exit status.
9198                                  */
9199                                 if (evalskip == 0 && cp->nclist.body) {
9200                                         status = evaltree(cp->nclist.body, flags);
9201                                 }
9202                                 goto out;
9203                         }
9204                 }
9205         }
9206  out:
9207         popstackmark(&smark);
9208
9209         return status;
9210 }
9211
9212 /*
9213  * Kick off a subshell to evaluate a tree.
9214  */
9215 static int
9216 evalsubshell(union node *n, int flags)
9217 {
9218         struct job *jp;
9219         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9220         int status;
9221
9222         errlinno = lineno = n->nredir.linno;
9223         if (funcline)
9224                 lineno -= funcline - 1;
9225
9226         expredir(n->nredir.redirect);
9227         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9228                 goto nofork;
9229         INT_OFF;
9230         if (backgnd == FORK_FG)
9231                 get_tty_state();
9232         jp = makejob(/*n,*/ 1);
9233         if (forkshell(jp, n, backgnd) == 0) {
9234                 /* child */
9235                 INT_ON;
9236                 flags |= EV_EXIT;
9237                 if (backgnd)
9238                         flags &= ~EV_TESTED;
9239  nofork:
9240                 redirect(n->nredir.redirect, 0);
9241                 evaltreenr(n->nredir.n, flags);
9242                 /* never returns */
9243         }
9244         /* parent */
9245         status = 0;
9246         if (backgnd == FORK_FG)
9247                 status = waitforjob(jp);
9248         INT_ON;
9249         return status;
9250 }
9251
9252 /*
9253  * Compute the names of the files in a redirection list.
9254  */
9255 static void fixredir(union node *, const char *, int);
9256 static void
9257 expredir(union node *n)
9258 {
9259         union node *redir;
9260
9261         for (redir = n; redir; redir = redir->nfile.next) {
9262                 struct arglist fn;
9263
9264                 fn.list = NULL;
9265                 fn.lastp = &fn.list;
9266                 switch (redir->type) {
9267                 case NFROMTO:
9268                 case NFROM:
9269                 case NTO:
9270 #if BASH_REDIR_OUTPUT
9271                 case NTO2:
9272 #endif
9273                 case NCLOBBER:
9274                 case NAPPEND:
9275                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9276                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9277 #if BASH_REDIR_OUTPUT
9278  store_expfname:
9279 #endif
9280 #if 0
9281 // By the design of stack allocator, the loop of this kind:
9282 //      while true; do while true; do break; done </dev/null; done
9283 // will look like a memory leak: ash plans to free expfname's
9284 // of "/dev/null" as soon as it finishes running the loop
9285 // (in this case, never).
9286 // This "fix" is wrong:
9287                         if (redir->nfile.expfname)
9288                                 stunalloc(redir->nfile.expfname);
9289 // It results in corrupted state of stacked allocations.
9290 #endif
9291                         redir->nfile.expfname = fn.list->text;
9292                         break;
9293                 case NFROMFD:
9294                 case NTOFD: /* >& */
9295                         if (redir->ndup.vname) {
9296                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9297                                 if (fn.list == NULL)
9298                                         ash_msg_and_raise_error("redir error");
9299 #if BASH_REDIR_OUTPUT
9300 //FIXME: we used expandarg with different args!
9301                                 if (!isdigit_str9(fn.list->text)) {
9302                                         /* >&file, not >&fd */
9303                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9304                                                 ash_msg_and_raise_error("redir error");
9305                                         redir->type = NTO2;
9306                                         goto store_expfname;
9307                                 }
9308 #endif
9309                                 fixredir(redir, fn.list->text, 1);
9310                         }
9311                         break;
9312                 }
9313         }
9314 }
9315
9316 /*
9317  * Evaluate a pipeline.  All the processes in the pipeline are children
9318  * of the process creating the pipeline.  (This differs from some versions
9319  * of the shell, which make the last process in a pipeline the parent
9320  * of all the rest.)
9321  */
9322 static int
9323 evalpipe(union node *n, int flags)
9324 {
9325         struct job *jp;
9326         struct nodelist *lp;
9327         int pipelen;
9328         int prevfd;
9329         int pip[2];
9330         int status = 0;
9331
9332         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9333         pipelen = 0;
9334         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9335                 pipelen++;
9336         flags |= EV_EXIT;
9337         INT_OFF;
9338         if (n->npipe.pipe_backgnd == 0)
9339                 get_tty_state();
9340         jp = makejob(/*n,*/ pipelen);
9341         prevfd = -1;
9342         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9343                 prehash(lp->n);
9344                 pip[1] = -1;
9345                 if (lp->next) {
9346                         if (pipe(pip) < 0) {
9347                                 close(prevfd);
9348                                 ash_msg_and_raise_perror("can't create pipe");
9349                         }
9350                 }
9351                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9352                         /* child */
9353                         INT_ON;
9354                         if (pip[1] >= 0) {
9355                                 close(pip[0]);
9356                         }
9357                         if (prevfd > 0) {
9358                                 dup2(prevfd, 0);
9359                                 close(prevfd);
9360                         }
9361                         if (pip[1] > 1) {
9362                                 dup2(pip[1], 1);
9363                                 close(pip[1]);
9364                         }
9365                         evaltreenr(lp->n, flags);
9366                         /* never returns */
9367                 }
9368                 /* parent */
9369                 if (prevfd >= 0)
9370                         close(prevfd);
9371                 prevfd = pip[0];
9372                 /* Don't want to trigger debugging */
9373                 if (pip[1] != -1)
9374                         close(pip[1]);
9375         }
9376         if (n->npipe.pipe_backgnd == 0) {
9377                 status = waitforjob(jp);
9378                 TRACE(("evalpipe:  job done exit status %d\n", status));
9379         }
9380         INT_ON;
9381
9382         return status;
9383 }
9384
9385 /*
9386  * Controls whether the shell is interactive or not.
9387  */
9388 static void
9389 setinteractive(int on)
9390 {
9391         static smallint is_interactive;
9392
9393         if (++on == is_interactive)
9394                 return;
9395         is_interactive = on;
9396         setsignal(SIGINT);
9397         setsignal(SIGQUIT);
9398         setsignal(SIGTERM);
9399 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9400         if (is_interactive > 1) {
9401                 /* Looks like they want an interactive shell */
9402                 static smallint did_banner;
9403
9404                 if (!did_banner) {
9405                         /* note: ash and hush share this string */
9406                         out1fmt("\n\n%s %s\n"
9407                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9408                                 "\n",
9409                                 bb_banner,
9410                                 "built-in shell (ash)"
9411                         );
9412                         did_banner = 1;
9413                 }
9414         }
9415 #endif
9416 }
9417
9418 static void
9419 optschanged(void)
9420 {
9421 #if DEBUG
9422         opentrace();
9423 #endif
9424         setinteractive(iflag);
9425         setjobctl(mflag);
9426 #if ENABLE_FEATURE_EDITING_VI
9427         if (viflag)
9428                 line_input_state->flags |= VI_MODE;
9429         else
9430                 line_input_state->flags &= ~VI_MODE;
9431 #else
9432         viflag = 0; /* forcibly keep the option off */
9433 #endif
9434 }
9435
9436 struct localvar_list {
9437         struct localvar_list *next;
9438         struct localvar *lv;
9439 };
9440
9441 static struct localvar_list *localvar_stack;
9442
9443 /*
9444  * Called after a function returns.
9445  * Interrupts must be off.
9446  */
9447 static void
9448 poplocalvars(int keep)
9449 {
9450         struct localvar_list *ll;
9451         struct localvar *lvp, *next;
9452         struct var *vp;
9453
9454         INT_OFF;
9455         ll = localvar_stack;
9456         localvar_stack = ll->next;
9457
9458         next = ll->lv;
9459         free(ll);
9460
9461         while ((lvp = next) != NULL) {
9462                 next = lvp->next;
9463                 vp = lvp->vp;
9464                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9465                 if (keep) {
9466                         int bits = VSTRFIXED;
9467
9468                         if (lvp->flags != VUNSET) {
9469                                 if (vp->var_text == lvp->text)
9470                                         bits |= VTEXTFIXED;
9471                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9472                                         free((char*)lvp->text);
9473                         }
9474
9475                         vp->flags &= ~bits;
9476                         vp->flags |= (lvp->flags & bits);
9477
9478                         if ((vp->flags &
9479                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9480                                 unsetvar(vp->var_text);
9481                 } else if (vp == NULL) {        /* $- saved */
9482                         memcpy(optlist, lvp->text, sizeof(optlist));
9483                         free((char*)lvp->text);
9484                         optschanged();
9485                 } else if (lvp->flags == VUNSET) {
9486                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9487                         unsetvar(vp->var_text);
9488                 } else {
9489                         if (vp->var_func)
9490                                 vp->var_func(var_end(lvp->text));
9491                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9492                                 free((char*)vp->var_text);
9493                         vp->flags = lvp->flags;
9494                         vp->var_text = lvp->text;
9495                 }
9496                 free(lvp);
9497         }
9498         INT_ON;
9499 }
9500
9501 /*
9502  * Create a new localvar environment.
9503  */
9504 static struct localvar_list *
9505 pushlocalvars(void)
9506 {
9507         struct localvar_list *ll;
9508
9509         INT_OFF;
9510         ll = ckzalloc(sizeof(*ll));
9511         /*ll->lv = NULL; - zalloc did it */
9512         ll->next = localvar_stack;
9513         localvar_stack = ll;
9514         INT_ON;
9515
9516         return ll->next;
9517 }
9518
9519 static void
9520 unwindlocalvars(struct localvar_list *stop)
9521 {
9522         while (localvar_stack != stop)
9523                 poplocalvars(0);
9524 }
9525
9526 static int
9527 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9528 {
9529         volatile struct shparam saveparam;
9530         struct jmploc *volatile savehandler;
9531         struct jmploc jmploc;
9532         int e;
9533         int savefuncline;
9534
9535         saveparam = shellparam;
9536         savefuncline = funcline;
9537         savehandler = exception_handler;
9538         e = setjmp(jmploc.loc);
9539         if (e) {
9540                 goto funcdone;
9541         }
9542         INT_OFF;
9543         exception_handler = &jmploc;
9544         shellparam.malloced = 0;
9545         func->count++;
9546         funcline = func->n.ndefun.linno;
9547         INT_ON;
9548         shellparam.nparam = argc - 1;
9549         shellparam.p = argv + 1;
9550 #if ENABLE_ASH_GETOPTS
9551         shellparam.optind = 1;
9552         shellparam.optoff = -1;
9553 #endif
9554         pushlocalvars();
9555         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9556         poplocalvars(0);
9557  funcdone:
9558         INT_OFF;
9559         funcline = savefuncline;
9560         freefunc(func);
9561         freeparam(&shellparam);
9562         shellparam = saveparam;
9563         exception_handler = savehandler;
9564         INT_ON;
9565         evalskip &= ~SKIPFUNC;
9566         return e;
9567 }
9568
9569 /*
9570  * Make a variable a local variable.  When a variable is made local, it's
9571  * value and flags are saved in a localvar structure.  The saved values
9572  * will be restored when the shell function returns.  We handle the name
9573  * "-" as a special case: it makes changes to "set +-options" local
9574  * (options will be restored on return from the function).
9575  */
9576 static void
9577 mklocal(char *name)
9578 {
9579         struct localvar *lvp;
9580         struct var **vpp;
9581         struct var *vp;
9582         char *eq = strchr(name, '=');
9583
9584         INT_OFF;
9585         /* Cater for duplicate "local". Examples:
9586          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9587          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9588          */
9589         lvp = localvar_stack->lv;
9590         while (lvp) {
9591                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9592                         if (eq)
9593                                 setvareq(name, 0);
9594                         /* else:
9595                          * it's a duplicate "local VAR" declaration, do nothing
9596                          */
9597                         goto ret;
9598                 }
9599                 lvp = lvp->next;
9600         }
9601
9602         lvp = ckzalloc(sizeof(*lvp));
9603         if (LONE_DASH(name)) {
9604                 char *p;
9605                 p = ckmalloc(sizeof(optlist));
9606                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9607                 vp = NULL;
9608         } else {
9609                 vpp = hashvar(name);
9610                 vp = *findvar(vpp, name);
9611                 if (vp == NULL) {
9612                         /* variable did not exist yet */
9613                         if (eq)
9614                                 vp = setvareq(name, VSTRFIXED);
9615                         else
9616                                 vp = setvar(name, NULL, VSTRFIXED);
9617                         lvp->flags = VUNSET;
9618                 } else {
9619                         lvp->text = vp->var_text;
9620                         lvp->flags = vp->flags;
9621                         /* make sure neither "struct var" nor string gets freed
9622                          * during (un)setting:
9623                          */
9624                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9625                         if (eq)
9626                                 setvareq(name, 0);
9627                         else
9628                                 /* "local VAR" unsets VAR: */
9629                                 setvar0(name, NULL);
9630                 }
9631         }
9632         lvp->vp = vp;
9633         lvp->next = localvar_stack->lv;
9634         localvar_stack->lv = lvp;
9635  ret:
9636         INT_ON;
9637 }
9638
9639 /*
9640  * The "local" command.
9641  */
9642 static int FAST_FUNC
9643 localcmd(int argc UNUSED_PARAM, char **argv)
9644 {
9645         char *name;
9646
9647         if (!localvar_stack)
9648                 ash_msg_and_raise_error("not in a function");
9649
9650         argv = argptr;
9651         while ((name = *argv++) != NULL) {
9652                 mklocal(name);
9653         }
9654         return 0;
9655 }
9656
9657 static int FAST_FUNC
9658 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9659 {
9660         return 1;
9661 }
9662
9663 static int FAST_FUNC
9664 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9665 {
9666         return 0;
9667 }
9668
9669 static int FAST_FUNC
9670 execcmd(int argc UNUSED_PARAM, char **argv)
9671 {
9672         optionarg = NULL;
9673         while (nextopt("a:") != '\0')
9674                 /* nextopt() sets optionarg to "-a ARGV0" */;
9675
9676         argv = argptr;
9677         if (argv[0]) {
9678                 char *prog;
9679
9680                 iflag = 0;              /* exit on error */
9681                 mflag = 0;
9682                 optschanged();
9683                 /* We should set up signals for "exec CMD"
9684                  * the same way as for "CMD" without "exec".
9685                  * But optschanged->setinteractive->setsignal
9686                  * still thought we are a root shell. Therefore, for example,
9687                  * SIGQUIT is still set to IGN. Fix it:
9688                  */
9689                 shlvl++;
9690                 setsignal(SIGQUIT);
9691                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9692                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9693                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9694
9695                 prog = argv[0];
9696                 if (optionarg)
9697                         argv[0] = optionarg;
9698                 shellexec(prog, argv, pathval(), 0);
9699                 /* NOTREACHED */
9700         }
9701         return 0;
9702 }
9703
9704 /*
9705  * The return command.
9706  */
9707 static int FAST_FUNC
9708 returncmd(int argc UNUSED_PARAM, char **argv)
9709 {
9710         /*
9711          * If called outside a function, do what ksh does;
9712          * skip the rest of the file.
9713          */
9714         evalskip = SKIPFUNC;
9715         return argv[1] ? number(argv[1]) : exitstatus;
9716 }
9717
9718 /* Forward declarations for builtintab[] */
9719 static int breakcmd(int, char **) FAST_FUNC;
9720 static int dotcmd(int, char **) FAST_FUNC;
9721 static int evalcmd(int, char **, int) FAST_FUNC;
9722 static int exitcmd(int, char **) FAST_FUNC;
9723 static int exportcmd(int, char **) FAST_FUNC;
9724 #if ENABLE_ASH_GETOPTS
9725 static int getoptscmd(int, char **) FAST_FUNC;
9726 #endif
9727 #if ENABLE_ASH_HELP
9728 static int helpcmd(int, char **) FAST_FUNC;
9729 #endif
9730 #if MAX_HISTORY
9731 static int historycmd(int, char **) FAST_FUNC;
9732 #endif
9733 #if ENABLE_FEATURE_SH_MATH
9734 static int letcmd(int, char **) FAST_FUNC;
9735 #endif
9736 static int readcmd(int, char **) FAST_FUNC;
9737 static int setcmd(int, char **) FAST_FUNC;
9738 static int shiftcmd(int, char **) FAST_FUNC;
9739 static int timescmd(int, char **) FAST_FUNC;
9740 static int trapcmd(int, char **) FAST_FUNC;
9741 static int umaskcmd(int, char **) FAST_FUNC;
9742 static int unsetcmd(int, char **) FAST_FUNC;
9743 static int ulimitcmd(int, char **) FAST_FUNC;
9744
9745 #define BUILTIN_NOSPEC          "0"
9746 #define BUILTIN_SPECIAL         "1"
9747 #define BUILTIN_REGULAR         "2"
9748 #define BUILTIN_SPEC_REG        "3"
9749 #define BUILTIN_ASSIGN          "4"
9750 #define BUILTIN_SPEC_ASSG       "5"
9751 #define BUILTIN_REG_ASSG        "6"
9752 #define BUILTIN_SPEC_REG_ASSG   "7"
9753
9754 /* Stubs for calling non-FAST_FUNC's */
9755 #if ENABLE_ASH_ECHO
9756 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9757 #endif
9758 #if ENABLE_ASH_PRINTF
9759 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9760 #endif
9761 #if ENABLE_ASH_TEST || BASH_TEST2
9762 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9763 #endif
9764
9765 /* Keep these in proper order since it is searched via bsearch() */
9766 static const struct builtincmd builtintab[] = {
9767         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9768         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9769 #if ENABLE_ASH_TEST
9770         { BUILTIN_REGULAR       "["       , testcmd    },
9771 #endif
9772 #if BASH_TEST2
9773         { BUILTIN_REGULAR       "[["      , testcmd    },
9774 #endif
9775 #if ENABLE_ASH_ALIAS
9776         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9777 #endif
9778 #if JOBS
9779         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9780 #endif
9781         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9782         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9783         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9784 #if ENABLE_ASH_CMDCMD
9785         { BUILTIN_REGULAR       "command" , commandcmd },
9786 #endif
9787         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9788 #if ENABLE_ASH_ECHO
9789         { BUILTIN_REGULAR       "echo"    , echocmd    },
9790 #endif
9791         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9792         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9793         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9794         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9795         { BUILTIN_REGULAR       "false"   , falsecmd   },
9796 #if JOBS
9797         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9798 #endif
9799 #if ENABLE_ASH_GETOPTS
9800         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9801 #endif
9802         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9803 #if ENABLE_ASH_HELP
9804         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9805 #endif
9806 #if MAX_HISTORY
9807         { BUILTIN_NOSPEC        "history" , historycmd },
9808 #endif
9809 #if JOBS
9810         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9811         { BUILTIN_REGULAR       "kill"    , killcmd    },
9812 #endif
9813 #if ENABLE_FEATURE_SH_MATH
9814         { BUILTIN_NOSPEC        "let"     , letcmd     },
9815 #endif
9816         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9817 #if ENABLE_ASH_PRINTF
9818         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9819 #endif
9820         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9821         { BUILTIN_REGULAR       "read"    , readcmd    },
9822         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9823         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9824         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9825         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9826 #if BASH_SOURCE
9827         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9828 #endif
9829 #if ENABLE_ASH_TEST
9830         { BUILTIN_REGULAR       "test"    , testcmd    },
9831 #endif
9832         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9833         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9834         { BUILTIN_REGULAR       "true"    , truecmd    },
9835         { BUILTIN_NOSPEC        "type"    , typecmd    },
9836         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9837         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9838 #if ENABLE_ASH_ALIAS
9839         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9840 #endif
9841         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9842         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9843 };
9844
9845 /* Should match the above table! */
9846 #define COMMANDCMD (builtintab + \
9847         /* . : */       2 + \
9848         /* [ */         1 * ENABLE_ASH_TEST + \
9849         /* [[ */        1 * BASH_TEST2 + \
9850         /* alias */     1 * ENABLE_ASH_ALIAS + \
9851         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9852         /* break cd cddir  */   3)
9853 #define EVALCMD (COMMANDCMD + \
9854         /* command */   1 * ENABLE_ASH_CMDCMD + \
9855         /* continue */  1 + \
9856         /* echo */      1 * ENABLE_ASH_ECHO + \
9857         0)
9858 #define EXECCMD (EVALCMD + \
9859         /* eval */      1)
9860
9861 /*
9862  * Search the table of builtin commands.
9863  */
9864 static int
9865 pstrcmp1(const void *a, const void *b)
9866 {
9867         return strcmp((char*)a, *(char**)b + 1);
9868 }
9869 static struct builtincmd *
9870 find_builtin(const char *name)
9871 {
9872         struct builtincmd *bp;
9873
9874         bp = bsearch(
9875                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9876                 pstrcmp1
9877         );
9878         return bp;
9879 }
9880
9881 /*
9882  * Execute a simple command.
9883  */
9884 static int
9885 isassignment(const char *p)
9886 {
9887         const char *q = endofname(p);
9888         if (p == q)
9889                 return 0;
9890         return *q == '=';
9891 }
9892 static int FAST_FUNC
9893 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9894 {
9895         /* Preserve exitstatus of a previous possible redirection
9896          * as POSIX mandates */
9897         return back_exitstatus;
9898 }
9899 static int
9900 evalcommand(union node *cmd, int flags)
9901 {
9902         static const struct builtincmd null_bltin = {
9903                 "\0\0", bltincmd /* why three NULs? */
9904         };
9905         struct localvar_list *localvar_stop;
9906         struct redirtab *redir_stop;
9907         struct stackmark smark;
9908         union node *argp;
9909         struct arglist arglist;
9910         struct arglist varlist;
9911         char **argv;
9912         int argc;
9913         const struct strlist *sp;
9914         struct cmdentry cmdentry;
9915         struct job *jp;
9916         char *lastarg;
9917         const char *path;
9918         int spclbltin;
9919         int status;
9920         char **nargv;
9921         smallint cmd_is_exec;
9922
9923         errlinno = lineno = cmd->ncmd.linno;
9924         if (funcline)
9925                 lineno -= funcline - 1;
9926
9927         /* First expand the arguments. */
9928         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9929         setstackmark(&smark);
9930         localvar_stop = pushlocalvars();
9931         back_exitstatus = 0;
9932
9933         cmdentry.cmdtype = CMDBUILTIN;
9934         cmdentry.u.cmd = &null_bltin;
9935         varlist.lastp = &varlist.list;
9936         *varlist.lastp = NULL;
9937         arglist.lastp = &arglist.list;
9938         *arglist.lastp = NULL;
9939
9940         argc = 0;
9941         if (cmd->ncmd.args) {
9942                 struct builtincmd *bcmd;
9943                 smallint pseudovarflag;
9944
9945                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9946                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9947
9948                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9949                         struct strlist **spp;
9950
9951                         spp = arglist.lastp;
9952                         if (pseudovarflag && isassignment(argp->narg.text))
9953                                 expandarg(argp, &arglist, EXP_VARTILDE);
9954                         else
9955                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9956
9957                         for (sp = *spp; sp; sp = sp->next)
9958                                 argc++;
9959                 }
9960         }
9961
9962         /* Reserve one extra spot at the front for shellexec. */
9963         nargv = stalloc(sizeof(char *) * (argc + 2));
9964         argv = ++nargv;
9965         for (sp = arglist.list; sp; sp = sp->next) {
9966                 TRACE(("evalcommand arg: %s\n", sp->text));
9967                 *nargv++ = sp->text;
9968         }
9969         *nargv = NULL;
9970
9971         lastarg = NULL;
9972         if (iflag && funcline == 0 && argc > 0)
9973                 lastarg = nargv[-1];
9974
9975         expredir(cmd->ncmd.redirect);
9976         redir_stop = pushredir(cmd->ncmd.redirect);
9977         preverrout_fd = 2;
9978         if (BASH_XTRACEFD && xflag) {
9979                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9980                  * we do not emulate this. We only use its value.
9981                  */
9982                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9983                 if (xtracefd && is_number(xtracefd))
9984                         preverrout_fd = atoi(xtracefd);
9985
9986         }
9987         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9988
9989         path = vpath.var_text;
9990         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9991                 struct strlist **spp;
9992                 char *p;
9993
9994                 spp = varlist.lastp;
9995                 expandarg(argp, &varlist, EXP_VARTILDE);
9996
9997                 mklocal((*spp)->text);
9998
9999                 /*
10000                  * Modify the command lookup path, if a PATH= assignment
10001                  * is present
10002                  */
10003                 p = (*spp)->text;
10004                 if (varcmp(p, path) == 0)
10005                         path = p;
10006         }
10007
10008         /* Print the command if xflag is set. */
10009         if (xflag) {
10010                 const char *pfx = "";
10011
10012                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10013
10014                 sp = varlist.list;
10015                 while (sp) {
10016                         char *varval = sp->text;
10017                         char *eq = strchrnul(varval, '=');
10018                         if (*eq)
10019                                 eq++;
10020                         fdprintf(preverrout_fd, "%s%.*s%s",
10021                                 pfx,
10022                                 (int)(eq - varval), varval,
10023                                 maybe_single_quote(eq)
10024                         );
10025                         sp = sp->next;
10026                         pfx = " ";
10027                 }
10028
10029                 sp = arglist.list;
10030                 while (sp) {
10031                         fdprintf(preverrout_fd, "%s%s",
10032                                 pfx,
10033                                 /* always quote if matches reserved word: */
10034                                 findkwd(sp->text)
10035                                 ? single_quote(sp->text)
10036                                 : maybe_single_quote(sp->text)
10037                         );
10038                         sp = sp->next;
10039                         pfx = " ";
10040                 }
10041                 safe_write(preverrout_fd, "\n", 1);
10042         }
10043
10044         cmd_is_exec = 0;
10045         spclbltin = -1;
10046
10047         /* Now locate the command. */
10048         if (argc) {
10049                 int cmd_flag = DO_ERR;
10050 #if ENABLE_ASH_CMDCMD
10051                 const char *oldpath = path + 5;
10052 #endif
10053                 path += 5;
10054                 for (;;) {
10055                         find_command(argv[0], &cmdentry, cmd_flag, path);
10056                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10057                                 flush_stdout_stderr();
10058                                 status = 127;
10059                                 goto bail;
10060                         }
10061
10062                         /* implement bltin and command here */
10063                         if (cmdentry.cmdtype != CMDBUILTIN)
10064                                 break;
10065                         if (spclbltin < 0)
10066                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10067                         if (cmdentry.u.cmd == EXECCMD)
10068                                 cmd_is_exec = 1;
10069 #if ENABLE_ASH_CMDCMD
10070                         if (cmdentry.u.cmd == COMMANDCMD) {
10071                                 path = oldpath;
10072                                 nargv = parse_command_args(argv, &path);
10073                                 if (!nargv)
10074                                         break;
10075                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10076                                  * nargv => "PROG". path is updated if -p.
10077                                  */
10078                                 argc -= nargv - argv;
10079                                 argv = nargv;
10080                                 cmd_flag |= DO_NOFUNC;
10081                         } else
10082 #endif
10083                                 break;
10084                 }
10085         }
10086
10087         if (status) {
10088  bail:
10089                 exitstatus = status;
10090
10091                 /* We have a redirection error. */
10092                 if (spclbltin > 0)
10093                         raise_exception(EXERROR);
10094
10095                 goto out;
10096         }
10097
10098         /* Execute the command. */
10099         switch (cmdentry.cmdtype) {
10100         default: {
10101
10102 #if ENABLE_FEATURE_SH_STANDALONE \
10103  && ENABLE_FEATURE_SH_NOFORK \
10104  && NUM_APPLETS > 1
10105 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10106  *     around run_nofork_applet() call.
10107  * (2) Should this check also be done in forkshell()?
10108  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10109  */
10110                 /* find_command() encodes applet_no as (-2 - applet_no) */
10111                 int applet_no = (- cmdentry.u.index - 2);
10112                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10113                         char **sv_environ;
10114
10115                         INT_OFF;
10116                         sv_environ = environ;
10117                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10118                         /*
10119                          * Run <applet>_main().
10120                          * Signals (^C) can't interrupt here.
10121                          * Otherwise we can mangle stdio or malloc internal state.
10122                          * This makes applets which can run for a long time
10123                          * and/or wait for user input ineligible for NOFORK:
10124                          * for example, "yes" or "rm" (rm -i waits for input).
10125                          */
10126                         status = run_nofork_applet(applet_no, argv);
10127                         environ = sv_environ;
10128                         /*
10129                          * Try enabling NOFORK for "yes" applet.
10130                          * ^C _will_ stop it (write returns EINTR),
10131                          * but this causes stdout FILE to be stuck
10132                          * and needing clearerr(). What if other applets
10133                          * also can get EINTRs? Do we need to switch
10134                          * our signals to SA_RESTART?
10135                          */
10136                         /*clearerr(stdout);*/
10137                         INT_ON;
10138                         break;
10139                 }
10140 #endif
10141                 /* Can we avoid forking? For example, very last command
10142                  * in a script or a subshell does not need forking,
10143                  * we can just exec it.
10144                  */
10145                 if (!(flags & EV_EXIT) || may_have_traps) {
10146                         /* No, forking off a child is necessary */
10147                         INT_OFF;
10148                         get_tty_state();
10149                         jp = makejob(/*cmd,*/ 1);
10150                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10151                                 /* parent */
10152                                 status = waitforjob(jp);
10153                                 INT_ON;
10154                                 TRACE(("forked child exited with %d\n", status));
10155                                 break;
10156                         }
10157                         /* child */
10158                         FORCE_INT_ON;
10159                         /* fall through to exec'ing external program */
10160                 }
10161                 listsetvar(varlist.list, VEXPORT|VSTACK);
10162                 shellexec(argv[0], argv, path, cmdentry.u.index);
10163                 /* NOTREACHED */
10164         } /* default */
10165         case CMDBUILTIN:
10166                 if (spclbltin > 0 || argc == 0) {
10167                         poplocalvars(1);
10168                         if (cmd_is_exec && argc > 1)
10169                                 listsetvar(varlist.list, VEXPORT);
10170                 }
10171
10172                 /* Tight loop with builtins only:
10173                  * "while kill -0 $child; do true; done"
10174                  * will never exit even if $child died, unless we do this
10175                  * to reap the zombie and make kill detect that it's gone: */
10176                 dowait(DOWAIT_NONBLOCK, NULL);
10177
10178                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10179                         if (exception_type == EXERROR && spclbltin <= 0) {
10180                                 FORCE_INT_ON;
10181                                 goto readstatus;
10182                         }
10183  raise:
10184                         longjmp(exception_handler->loc, 1);
10185                 }
10186                 goto readstatus;
10187
10188         case CMDFUNCTION:
10189                 poplocalvars(1);
10190                 /* See above for the rationale */
10191                 dowait(DOWAIT_NONBLOCK, NULL);
10192                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10193                         goto raise;
10194  readstatus:
10195                 status = exitstatus;
10196                 break;
10197         } /* switch */
10198
10199  out:
10200         if (cmd->ncmd.redirect)
10201                 popredir(/*drop:*/ cmd_is_exec);
10202         unwindredir(redir_stop);
10203         unwindlocalvars(localvar_stop);
10204         if (lastarg) {
10205                 /* dsl: I think this is intended to be used to support
10206                  * '_' in 'vi' command mode during line editing...
10207                  * However I implemented that within libedit itself.
10208                  */
10209                 setvar0("_", lastarg);
10210         }
10211         popstackmark(&smark);
10212
10213         return status;
10214 }
10215
10216 static int
10217 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10218 {
10219         char *volatile savecmdname;
10220         struct jmploc *volatile savehandler;
10221         struct jmploc jmploc;
10222         int status;
10223         int i;
10224
10225         savecmdname = commandname;
10226         savehandler = exception_handler;
10227         i = setjmp(jmploc.loc);
10228         if (i)
10229                 goto cmddone;
10230         exception_handler = &jmploc;
10231         commandname = argv[0];
10232         argptr = argv + 1;
10233         optptr = NULL;                  /* initialize nextopt */
10234         if (cmd == EVALCMD)
10235                 status = evalcmd(argc, argv, flags);
10236         else
10237                 status = (*cmd->builtin)(argc, argv);
10238         flush_stdout_stderr();
10239         status |= ferror(stdout);
10240         exitstatus = status;
10241  cmddone:
10242         clearerr(stdout);
10243         commandname = savecmdname;
10244         exception_handler = savehandler;
10245
10246         return i;
10247 }
10248
10249 static int
10250 goodname(const char *p)
10251 {
10252         return endofname(p)[0] == '\0';
10253 }
10254
10255
10256 /*
10257  * Search for a command.  This is called before we fork so that the
10258  * location of the command will be available in the parent as well as
10259  * the child.  The check for "goodname" is an overly conservative
10260  * check that the name will not be subject to expansion.
10261  */
10262 static void
10263 prehash(union node *n)
10264 {
10265         struct cmdentry entry;
10266
10267         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10268                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10269 }
10270
10271
10272 /* ============ Builtin commands
10273  *
10274  * Builtin commands whose functions are closely tied to evaluation
10275  * are implemented here.
10276  */
10277
10278 /*
10279  * Handle break and continue commands.  Break, continue, and return are
10280  * all handled by setting the evalskip flag.  The evaluation routines
10281  * above all check this flag, and if it is set they start skipping
10282  * commands rather than executing them.  The variable skipcount is
10283  * the number of loops to break/continue, or the number of function
10284  * levels to return.  (The latter is always 1.)  It should probably
10285  * be an error to break out of more loops than exist, but it isn't
10286  * in the standard shell so we don't make it one here.
10287  */
10288 static int FAST_FUNC
10289 breakcmd(int argc UNUSED_PARAM, char **argv)
10290 {
10291         int n = argv[1] ? number(argv[1]) : 1;
10292
10293         if (n <= 0)
10294                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10295         if (n > loopnest)
10296                 n = loopnest;
10297         if (n > 0) {
10298                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10299                 skipcount = n;
10300         }
10301         return 0;
10302 }
10303
10304
10305 /*
10306  * This implements the input routines used by the parser.
10307  */
10308
10309 enum {
10310         INPUT_PUSH_FILE = 1,
10311         INPUT_NOFILE_OK = 2,
10312 };
10313
10314 static smallint checkkwd;
10315 /* values of checkkwd variable */
10316 #define CHKALIAS        0x1
10317 #define CHKKWD          0x2
10318 #define CHKNL           0x4
10319 #define CHKEOFMARK      0x8
10320
10321 /*
10322  * Push a string back onto the input at this current parsefile level.
10323  * We handle aliases this way.
10324  */
10325 #if !ENABLE_ASH_ALIAS
10326 #define pushstring(s, ap) pushstring(s)
10327 #endif
10328 static void
10329 pushstring(char *s, struct alias *ap)
10330 {
10331         struct strpush *sp;
10332         int len;
10333
10334         len = strlen(s);
10335         INT_OFF;
10336         if (g_parsefile->strpush) {
10337                 sp = ckzalloc(sizeof(*sp));
10338                 sp->prev = g_parsefile->strpush;
10339         } else {
10340                 sp = &(g_parsefile->basestrpush);
10341         }
10342         g_parsefile->strpush = sp;
10343         sp->prev_string = g_parsefile->next_to_pgetc;
10344         sp->prev_left_in_line = g_parsefile->left_in_line;
10345         sp->unget = g_parsefile->unget;
10346         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10347 #if ENABLE_ASH_ALIAS
10348         sp->ap = ap;
10349         if (ap) {
10350                 ap->flag |= ALIASINUSE;
10351                 sp->string = s;
10352         }
10353 #endif
10354         g_parsefile->next_to_pgetc = s;
10355         g_parsefile->left_in_line = len;
10356         g_parsefile->unget = 0;
10357         INT_ON;
10358 }
10359
10360 static void
10361 popstring(void)
10362 {
10363         struct strpush *sp = g_parsefile->strpush;
10364
10365         INT_OFF;
10366 #if ENABLE_ASH_ALIAS
10367         if (sp->ap) {
10368                 if (g_parsefile->next_to_pgetc[-1] == ' '
10369                  || g_parsefile->next_to_pgetc[-1] == '\t'
10370                 ) {
10371                         checkkwd |= CHKALIAS;
10372                 }
10373                 if (sp->string != sp->ap->val) {
10374                         free(sp->string);
10375                 }
10376                 sp->ap->flag &= ~ALIASINUSE;
10377                 if (sp->ap->flag & ALIASDEAD) {
10378                         unalias(sp->ap->name);
10379                 }
10380         }
10381 #endif
10382         g_parsefile->next_to_pgetc = sp->prev_string;
10383         g_parsefile->left_in_line = sp->prev_left_in_line;
10384         g_parsefile->unget = sp->unget;
10385         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10386         g_parsefile->strpush = sp->prev;
10387         if (sp != &(g_parsefile->basestrpush))
10388                 free(sp);
10389         INT_ON;
10390 }
10391
10392 static int
10393 preadfd(void)
10394 {
10395         int nr;
10396         char *buf = g_parsefile->buf;
10397
10398         g_parsefile->next_to_pgetc = buf;
10399 #if ENABLE_FEATURE_EDITING
10400  retry:
10401         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10402                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10403         else {
10404 # if ENABLE_ASH_IDLE_TIMEOUT
10405                 int timeout = -1;
10406                 if (iflag) {
10407                         const char *tmout_var = lookupvar("TMOUT");
10408                         if (tmout_var) {
10409                                 timeout = atoi(tmout_var) * 1000;
10410                                 if (timeout <= 0)
10411                                         timeout = -1;
10412                         }
10413                 }
10414                 line_input_state->timeout = timeout;
10415 # endif
10416 # if ENABLE_FEATURE_TAB_COMPLETION
10417                 line_input_state->path_lookup = pathval();
10418 # endif
10419                 reinit_unicode_for_ash();
10420                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10421                 if (nr == 0) {
10422                         /* ^C pressed, "convert" to SIGINT */
10423                         write(STDOUT_FILENO, "^C", 2);
10424                         if (trap[SIGINT]) {
10425                                 buf[0] = '\n';
10426                                 buf[1] = '\0';
10427                                 raise(SIGINT);
10428                                 return 1;
10429                         }
10430                         exitstatus = 128 + SIGINT;
10431                         bb_putchar('\n');
10432                         goto retry;
10433                 }
10434                 if (nr < 0) {
10435                         if (errno == 0) {
10436                                 /* Ctrl+D pressed */
10437                                 nr = 0;
10438                         }
10439 # if ENABLE_ASH_IDLE_TIMEOUT
10440                         else if (errno == EAGAIN && timeout > 0) {
10441                                 puts("\007timed out waiting for input: auto-logout");
10442                                 exitshell();
10443                         }
10444 # endif
10445                 }
10446         }
10447 #else
10448         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10449 #endif
10450
10451 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10452         if (nr < 0) {
10453                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10454                         int flags = fcntl(0, F_GETFL);
10455                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10456                                 flags &= ~O_NONBLOCK;
10457                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10458                                         out2str("sh: turning off NDELAY mode\n");
10459                                         goto retry;
10460                                 }
10461                         }
10462                 }
10463         }
10464 #endif
10465         return nr;
10466 }
10467
10468 /*
10469  * Refill the input buffer and return the next input character:
10470  *
10471  * 1) If a string was pushed back on the input, pop it;
10472  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10473  *    or we are reading from a string so we can't refill the buffer,
10474  *    return EOF.
10475  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10476  * 4) Process input up to the next newline, deleting nul characters.
10477  */
10478 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10479 #define pgetc_debug(...) ((void)0)
10480 static int pgetc(void);
10481 static int
10482 preadbuffer(void)
10483 {
10484         char *q;
10485         int more;
10486
10487         if (g_parsefile->strpush) {
10488 #if ENABLE_ASH_ALIAS
10489                 if (g_parsefile->left_in_line == -1
10490                  && g_parsefile->strpush->ap
10491                  && g_parsefile->next_to_pgetc[-1] != ' '
10492                  && g_parsefile->next_to_pgetc[-1] != '\t'
10493                 ) {
10494                         pgetc_debug("preadbuffer PEOA");
10495                         return PEOA;
10496                 }
10497 #endif
10498                 popstring();
10499                 return pgetc();
10500         }
10501         /* on both branches above g_parsefile->left_in_line < 0.
10502          * "pgetc" needs refilling.
10503          */
10504
10505         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10506          * pungetc() may increment it a few times.
10507          * Assuming it won't increment it to less than -90.
10508          */
10509         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10510                 pgetc_debug("preadbuffer PEOF1");
10511                 /* even in failure keep left_in_line and next_to_pgetc
10512                  * in lock step, for correct multi-layer pungetc.
10513                  * left_in_line was decremented before preadbuffer(),
10514                  * must inc next_to_pgetc: */
10515                 g_parsefile->next_to_pgetc++;
10516                 return PEOF;
10517         }
10518
10519         more = g_parsefile->left_in_buffer;
10520         if (more <= 0) {
10521                 flush_stdout_stderr();
10522  again:
10523                 more = preadfd();
10524                 if (more <= 0) {
10525                         /* don't try reading again */
10526                         g_parsefile->left_in_line = -99;
10527                         pgetc_debug("preadbuffer PEOF2");
10528                         g_parsefile->next_to_pgetc++;
10529                         return PEOF;
10530                 }
10531         }
10532
10533         /* Find out where's the end of line.
10534          * Set g_parsefile->left_in_line
10535          * and g_parsefile->left_in_buffer acordingly.
10536          * NUL chars are deleted.
10537          */
10538         q = g_parsefile->next_to_pgetc;
10539         for (;;) {
10540                 char c;
10541
10542                 more--;
10543
10544                 c = *q;
10545                 if (c == '\0') {
10546                         memmove(q, q + 1, more);
10547                 } else {
10548                         q++;
10549                         if (c == '\n') {
10550                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10551                                 break;
10552                         }
10553                 }
10554
10555                 if (more <= 0) {
10556                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10557                         if (g_parsefile->left_in_line < 0)
10558                                 goto again;
10559                         break;
10560                 }
10561         }
10562         g_parsefile->left_in_buffer = more;
10563
10564         if (vflag) {
10565                 char save = *q;
10566                 *q = '\0';
10567                 out2str(g_parsefile->next_to_pgetc);
10568                 *q = save;
10569         }
10570
10571         pgetc_debug("preadbuffer at %d:%p'%s'",
10572                         g_parsefile->left_in_line,
10573                         g_parsefile->next_to_pgetc,
10574                         g_parsefile->next_to_pgetc);
10575         return (unsigned char)*g_parsefile->next_to_pgetc++;
10576 }
10577
10578 static void
10579 nlprompt(void)
10580 {
10581         g_parsefile->linno++;
10582         setprompt_if(doprompt, 2);
10583 }
10584 static void
10585 nlnoprompt(void)
10586 {
10587         g_parsefile->linno++;
10588         needprompt = doprompt;
10589 }
10590
10591 static int
10592 pgetc(void)
10593 {
10594         int c;
10595
10596         pgetc_debug("pgetc at %d:%p'%s'",
10597                         g_parsefile->left_in_line,
10598                         g_parsefile->next_to_pgetc,
10599                         g_parsefile->next_to_pgetc);
10600         if (g_parsefile->unget)
10601                 return g_parsefile->lastc[--g_parsefile->unget];
10602
10603         if (--g_parsefile->left_in_line >= 0)
10604                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10605         else
10606                 c = preadbuffer();
10607
10608         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10609         g_parsefile->lastc[0] = c;
10610
10611         return c;
10612 }
10613
10614 #if ENABLE_ASH_ALIAS
10615 static int
10616 pgetc_without_PEOA(void)
10617 {
10618         int c;
10619         do {
10620                 pgetc_debug("pgetc at %d:%p'%s'",
10621                                 g_parsefile->left_in_line,
10622                                 g_parsefile->next_to_pgetc,
10623                                 g_parsefile->next_to_pgetc);
10624                 c = pgetc();
10625         } while (c == PEOA);
10626         return c;
10627 }
10628 #else
10629 # define pgetc_without_PEOA() pgetc()
10630 #endif
10631
10632 /*
10633  * Undo a call to pgetc.  Only two characters may be pushed back.
10634  * PEOF may be pushed back.
10635  */
10636 static void
10637 pungetc(void)
10638 {
10639         g_parsefile->unget++;
10640 }
10641
10642 /* This one eats backslash+newline */
10643 static int
10644 pgetc_eatbnl(void)
10645 {
10646         int c;
10647
10648         while ((c = pgetc()) == '\\') {
10649                 if (pgetc() != '\n') {
10650                         pungetc();
10651                         break;
10652                 }
10653
10654                 nlprompt();
10655         }
10656
10657         return c;
10658 }
10659
10660 /*
10661  * To handle the "." command, a stack of input files is used.  Pushfile
10662  * adds a new entry to the stack and popfile restores the previous level.
10663  */
10664 static void
10665 pushfile(void)
10666 {
10667         struct parsefile *pf;
10668
10669         pf = ckzalloc(sizeof(*pf));
10670         pf->prev = g_parsefile;
10671         pf->pf_fd = -1;
10672         /*pf->strpush = NULL; - ckzalloc did it */
10673         /*pf->basestrpush.prev = NULL;*/
10674         /*pf->unget = 0;*/
10675         g_parsefile = pf;
10676 }
10677
10678 static void
10679 popfile(void)
10680 {
10681         struct parsefile *pf = g_parsefile;
10682
10683         if (pf == &basepf)
10684                 return;
10685
10686         INT_OFF;
10687         if (pf->pf_fd >= 0)
10688                 close(pf->pf_fd);
10689         free(pf->buf);
10690         while (pf->strpush)
10691                 popstring();
10692         g_parsefile = pf->prev;
10693         free(pf);
10694         INT_ON;
10695 }
10696
10697 /*
10698  * Return to top level.
10699  */
10700 static void
10701 popallfiles(void)
10702 {
10703         while (g_parsefile != &basepf)
10704                 popfile();
10705 }
10706
10707 /*
10708  * Close the file(s) that the shell is reading commands from.  Called
10709  * after a fork is done.
10710  */
10711 static void
10712 closescript(void)
10713 {
10714         popallfiles();
10715         if (g_parsefile->pf_fd > 0) {
10716                 close(g_parsefile->pf_fd);
10717                 g_parsefile->pf_fd = 0;
10718         }
10719 }
10720
10721 /*
10722  * Like setinputfile, but takes an open file descriptor.  Call this with
10723  * interrupts off.
10724  */
10725 static void
10726 setinputfd(int fd, int push)
10727 {
10728         if (push) {
10729                 pushfile();
10730                 g_parsefile->buf = NULL;
10731         }
10732         g_parsefile->pf_fd = fd;
10733         if (g_parsefile->buf == NULL)
10734                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10735         g_parsefile->left_in_buffer = 0;
10736         g_parsefile->left_in_line = 0;
10737         g_parsefile->linno = 1;
10738 }
10739
10740 /*
10741  * Set the input to take input from a file.  If push is set, push the
10742  * old input onto the stack first.
10743  */
10744 static int
10745 setinputfile(const char *fname, int flags)
10746 {
10747         int fd;
10748
10749         INT_OFF;
10750         fd = open(fname, O_RDONLY);
10751         if (fd < 0) {
10752                 if (flags & INPUT_NOFILE_OK)
10753                         goto out;
10754                 exitstatus = 127;
10755                 ash_msg_and_raise_perror("can't open '%s'", fname);
10756         }
10757         if (fd < 10)
10758                 fd = savefd(fd);
10759         else
10760                 close_on_exec_on(fd);
10761         setinputfd(fd, flags & INPUT_PUSH_FILE);
10762  out:
10763         INT_ON;
10764         return fd;
10765 }
10766
10767 /*
10768  * Like setinputfile, but takes input from a string.
10769  */
10770 static void
10771 setinputstring(char *string)
10772 {
10773         INT_OFF;
10774         pushfile();
10775         g_parsefile->next_to_pgetc = string;
10776         g_parsefile->left_in_line = strlen(string);
10777         g_parsefile->buf = NULL;
10778         g_parsefile->linno = 1;
10779         INT_ON;
10780 }
10781
10782
10783 /*
10784  * Routines to check for mail.
10785  */
10786
10787 #if ENABLE_ASH_MAIL
10788
10789 /* Hash of mtimes of mailboxes */
10790 static unsigned mailtime_hash;
10791 /* Set if MAIL or MAILPATH is changed. */
10792 static smallint mail_var_path_changed;
10793
10794 /*
10795  * Print appropriate message(s) if mail has arrived.
10796  * If mail_var_path_changed is set,
10797  * then the value of MAIL has mail_var_path_changed,
10798  * so we just update the values.
10799  */
10800 static void
10801 chkmail(void)
10802 {
10803         const char *mpath;
10804         char *p;
10805         char *q;
10806         unsigned new_hash;
10807         struct stackmark smark;
10808         struct stat statb;
10809
10810         setstackmark(&smark);
10811         mpath = mpathset() ? mpathval() : mailval();
10812         new_hash = 0;
10813         for (;;) {
10814                 p = path_advance(&mpath, nullstr);
10815                 if (p == NULL)
10816                         break;
10817                 if (*p == '\0')
10818                         continue;
10819                 for (q = p; *q; q++)
10820                         continue;
10821 #if DEBUG
10822                 if (q[-1] != '/')
10823                         abort();
10824 #endif
10825                 q[-1] = '\0';                   /* delete trailing '/' */
10826                 if (stat(p, &statb) < 0) {
10827                         continue;
10828                 }
10829                 /* Very simplistic "hash": just a sum of all mtimes */
10830                 new_hash += (unsigned)statb.st_mtime;
10831         }
10832         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10833                 if (mailtime_hash != 0)
10834                         out2str("you have mail\n");
10835                 mailtime_hash = new_hash;
10836         }
10837         mail_var_path_changed = 0;
10838         popstackmark(&smark);
10839 }
10840
10841 static void FAST_FUNC
10842 changemail(const char *val UNUSED_PARAM)
10843 {
10844         mail_var_path_changed = 1;
10845 }
10846
10847 #endif /* ASH_MAIL */
10848
10849
10850 /* ============ ??? */
10851
10852 /*
10853  * Set the shell parameters.
10854  */
10855 static void
10856 setparam(char **argv)
10857 {
10858         char **newparam;
10859         char **ap;
10860         int nparam;
10861
10862         for (nparam = 0; argv[nparam]; nparam++)
10863                 continue;
10864         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10865         while (*argv) {
10866                 *ap++ = ckstrdup(*argv++);
10867         }
10868         *ap = NULL;
10869         freeparam(&shellparam);
10870         shellparam.malloced = 1;
10871         shellparam.nparam = nparam;
10872         shellparam.p = newparam;
10873 #if ENABLE_ASH_GETOPTS
10874         shellparam.optind = 1;
10875         shellparam.optoff = -1;
10876 #endif
10877 }
10878
10879 /*
10880  * Process shell options.  The global variable argptr contains a pointer
10881  * to the argument list; we advance it past the options.
10882  *
10883  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10884  * For a non-interactive shell, an error condition encountered
10885  * by a special built-in ... shall cause the shell to write a diagnostic message
10886  * to standard error and exit as shown in the following table:
10887  * Error                                           Special Built-In
10888  * ...
10889  * Utility syntax error (option or operand error)  Shall exit
10890  * ...
10891  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10892  * we see that bash does not do that (set "finishes" with error code 1 instead,
10893  * and shell continues), and people rely on this behavior!
10894  * Testcase:
10895  * set -o barfoo 2>/dev/null
10896  * echo $?
10897  *
10898  * Oh well. Let's mimic that.
10899  */
10900 static int
10901 plus_minus_o(char *name, int val)
10902 {
10903         int i;
10904
10905         if (name) {
10906                 for (i = 0; i < NOPTS; i++) {
10907                         if (strcmp(name, optnames(i)) == 0) {
10908                                 optlist[i] = val;
10909                                 return 0;
10910                         }
10911                 }
10912                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10913                 return 1;
10914         }
10915         for (i = 0; i < NOPTS; i++) {
10916                 if (val) {
10917                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10918                 } else {
10919                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10920                 }
10921         }
10922         return 0;
10923 }
10924 static void
10925 setoption(int flag, int val)
10926 {
10927         int i;
10928
10929         for (i = 0; i < NOPTS; i++) {
10930                 if (optletters(i) == flag) {
10931                         optlist[i] = val;
10932                         return;
10933                 }
10934         }
10935         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10936         /* NOTREACHED */
10937 }
10938 static int
10939 options(int cmdline, int *login_sh)
10940 {
10941         char *p;
10942         int val;
10943         int c;
10944
10945         if (cmdline)
10946                 minusc = NULL;
10947         while ((p = *argptr) != NULL) {
10948                 c = *p++;
10949                 if (c != '-' && c != '+')
10950                         break;
10951                 argptr++;
10952                 val = 0; /* val = 0 if c == '+' */
10953                 if (c == '-') {
10954                         val = 1;
10955                         if (p[0] == '\0' || LONE_DASH(p)) {
10956                                 if (!cmdline) {
10957                                         /* "-" means turn off -x and -v */
10958                                         if (p[0] == '\0')
10959                                                 xflag = vflag = 0;
10960                                         /* "--" means reset params */
10961                                         else if (*argptr == NULL)
10962                                                 setparam(argptr);
10963                                 }
10964                                 break;    /* "-" or "--" terminates options */
10965                         }
10966                 }
10967                 /* first char was + or - */
10968                 while ((c = *p++) != '\0') {
10969                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10970                         if (c == 'c' && cmdline) {
10971                                 minusc = p;     /* command is after shell args */
10972                         } else if (c == 'o') {
10973                                 if (plus_minus_o(*argptr, val)) {
10974                                         /* it already printed err message */
10975                                         return 1; /* error */
10976                                 }
10977                                 if (*argptr)
10978                                         argptr++;
10979                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10980                                 if (login_sh)
10981                                         *login_sh = 1;
10982                         /* bash does not accept +-login, we also won't */
10983                         } else if (cmdline && val && (c == '-')) { /* long options */
10984                                 if (strcmp(p, "login") == 0) {
10985                                         if (login_sh)
10986                                                 *login_sh = 1;
10987                                 }
10988                                 break;
10989                         } else {
10990                                 setoption(c, val);
10991                         }
10992                 }
10993         }
10994         return 0;
10995 }
10996
10997 /*
10998  * The shift builtin command.
10999  */
11000 static int FAST_FUNC
11001 shiftcmd(int argc UNUSED_PARAM, char **argv)
11002 {
11003         int n;
11004         char **ap1, **ap2;
11005
11006         n = 1;
11007         if (argv[1])
11008                 n = number(argv[1]);
11009         if (n > shellparam.nparam)
11010                 return 1;
11011         INT_OFF;
11012         shellparam.nparam -= n;
11013         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11014                 if (shellparam.malloced)
11015                         free(*ap1);
11016         }
11017         ap2 = shellparam.p;
11018         while ((*ap2++ = *ap1++) != NULL)
11019                 continue;
11020 #if ENABLE_ASH_GETOPTS
11021         shellparam.optind = 1;
11022         shellparam.optoff = -1;
11023 #endif
11024         INT_ON;
11025         return 0;
11026 }
11027
11028 /*
11029  * POSIX requires that 'set' (but not export or readonly) output the
11030  * variables in lexicographic order - by the locale's collating order (sigh).
11031  * Maybe we could keep them in an ordered balanced binary tree
11032  * instead of hashed lists.
11033  * For now just roll 'em through qsort for printing...
11034  */
11035 static int
11036 showvars(const char *sep_prefix, int on, int off)
11037 {
11038         const char *sep;
11039         char **ep, **epend;
11040
11041         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11042         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11043
11044         sep = *sep_prefix ? " " : sep_prefix;
11045
11046         for (; ep < epend; ep++) {
11047                 const char *p;
11048                 const char *q;
11049
11050                 p = endofname(*ep);
11051 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11052  * makes "export -p" to have output not suitable for "eval":
11053  * import os
11054  * os.environ["test-test"]="test"
11055  * if os.fork() == 0:
11056  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11057  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11058  */
11059                 q = nullstr;
11060                 if (*p == '=')
11061                         q = single_quote(++p);
11062                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11063         }
11064         return 0;
11065 }
11066
11067 /*
11068  * The set command builtin.
11069  */
11070 static int FAST_FUNC
11071 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11072 {
11073         int retval;
11074
11075         if (!argv[1])
11076                 return showvars(nullstr, 0, VUNSET);
11077
11078         INT_OFF;
11079         retval = options(/*cmdline:*/ 0, NULL);
11080         if (retval == 0) { /* if no parse error... */
11081                 optschanged();
11082                 if (*argptr != NULL) {
11083                         setparam(argptr);
11084                 }
11085         }
11086         INT_ON;
11087         return retval;
11088 }
11089
11090 #if ENABLE_ASH_RANDOM_SUPPORT
11091 static void FAST_FUNC
11092 change_random(const char *value)
11093 {
11094         uint32_t t;
11095
11096         if (value == NULL) {
11097                 /* "get", generate */
11098                 t = next_random(&random_gen);
11099                 /* set without recursion */
11100                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11101                 vrandom.flags &= ~VNOFUNC;
11102         } else {
11103                 /* set/reset */
11104                 t = strtoul(value, NULL, 10);
11105                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11106         }
11107 }
11108 #endif
11109
11110 #if ENABLE_ASH_GETOPTS
11111 static int
11112 getopts(char *optstr, char *optvar, char **optfirst)
11113 {
11114         char *p, *q;
11115         char c = '?';
11116         int done = 0;
11117         char sbuf[2];
11118         char **optnext;
11119         int ind = shellparam.optind;
11120         int off = shellparam.optoff;
11121
11122         sbuf[1] = '\0';
11123
11124         shellparam.optind = -1;
11125         optnext = optfirst + ind - 1;
11126
11127         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11128                 p = NULL;
11129         else
11130                 p = optnext[-1] + off;
11131         if (p == NULL || *p == '\0') {
11132                 /* Current word is done, advance */
11133                 p = *optnext;
11134                 if (p == NULL || *p != '-' || *++p == '\0') {
11135  atend:
11136                         unsetvar("OPTARG");
11137                         p = NULL;
11138                         done = 1;
11139                         goto out;
11140                 }
11141                 optnext++;
11142                 if (LONE_DASH(p))        /* check for "--" */
11143                         goto atend;
11144         }
11145
11146         c = *p++;
11147         for (q = optstr; *q != c;) {
11148                 if (*q == '\0') {
11149                         /* OPTERR is a bashism */
11150                         const char *cp = lookupvar("OPTERR");
11151                         if ((cp && LONE_CHAR(cp, '0'))
11152                          || (optstr[0] == ':')
11153                         ) {
11154                                 sbuf[0] = c;
11155                                 /*sbuf[1] = '\0'; - already is */
11156                                 setvar0("OPTARG", sbuf);
11157                         } else {
11158                                 fprintf(stderr, "Illegal option -%c\n", c);
11159                                 unsetvar("OPTARG");
11160                         }
11161                         c = '?';
11162                         goto out;
11163                 }
11164                 if (*++q == ':')
11165                         q++;
11166         }
11167
11168         if (*++q == ':') {
11169                 if (*p == '\0' && (p = *optnext) == NULL) {
11170                         /* OPTERR is a bashism */
11171                         const char *cp = lookupvar("OPTERR");
11172                         if ((cp && LONE_CHAR(cp, '0'))
11173                          || (optstr[0] == ':')
11174                         ) {
11175                                 sbuf[0] = c;
11176                                 /*sbuf[1] = '\0'; - already is */
11177                                 setvar0("OPTARG", sbuf);
11178                                 c = ':';
11179                         } else {
11180                                 fprintf(stderr, "No arg for -%c option\n", c);
11181                                 unsetvar("OPTARG");
11182                                 c = '?';
11183                         }
11184                         goto out;
11185                 }
11186
11187                 if (p == *optnext)
11188                         optnext++;
11189                 setvar0("OPTARG", p);
11190                 p = NULL;
11191         } else
11192                 setvar0("OPTARG", nullstr);
11193  out:
11194         ind = optnext - optfirst + 1;
11195         setvar("OPTIND", itoa(ind), VNOFUNC);
11196         sbuf[0] = c;
11197         /*sbuf[1] = '\0'; - already is */
11198         setvar0(optvar, sbuf);
11199
11200         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11201         shellparam.optind = ind;
11202
11203         return done;
11204 }
11205
11206 /*
11207  * The getopts builtin.  Shellparam.optnext points to the next argument
11208  * to be processed.  Shellparam.optptr points to the next character to
11209  * be processed in the current argument.  If shellparam.optnext is NULL,
11210  * then it's the first time getopts has been called.
11211  */
11212 static int FAST_FUNC
11213 getoptscmd(int argc, char **argv)
11214 {
11215         char **optbase;
11216
11217         if (argc < 3)
11218                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11219         if (argc == 3) {
11220                 optbase = shellparam.p;
11221                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11222                         shellparam.optind = 1;
11223                         shellparam.optoff = -1;
11224                 }
11225         } else {
11226                 optbase = &argv[3];
11227                 if ((unsigned)shellparam.optind > argc - 2) {
11228                         shellparam.optind = 1;
11229                         shellparam.optoff = -1;
11230                 }
11231         }
11232
11233         return getopts(argv[1], argv[2], optbase);
11234 }
11235 #endif /* ASH_GETOPTS */
11236
11237
11238 /* ============ Shell parser */
11239
11240 struct heredoc {
11241         struct heredoc *next;   /* next here document in list */
11242         union node *here;       /* redirection node */
11243         char *eofmark;          /* string indicating end of input */
11244         smallint striptabs;     /* if set, strip leading tabs */
11245 };
11246
11247 static smallint tokpushback;           /* last token pushed back */
11248 static smallint quoteflag;             /* set if (part of) last token was quoted */
11249 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11250 static struct heredoc *heredoclist;    /* list of here documents to read */
11251 static char *wordtext;                 /* text of last word returned by readtoken */
11252 static struct nodelist *backquotelist;
11253 static union node *redirnode;
11254 static struct heredoc *heredoc;
11255
11256 static const char *
11257 tokname(char *buf, int tok)
11258 {
11259         if (tok < TSEMI)
11260                 return tokname_array[tok];
11261         sprintf(buf, "\"%s\"", tokname_array[tok]);
11262         return buf;
11263 }
11264
11265 /* raise_error_unexpected_syntax:
11266  * Called when an unexpected token is read during the parse.  The argument
11267  * is the token that is expected, or -1 if more than one type of token can
11268  * occur at this point.
11269  */
11270 static void raise_error_unexpected_syntax(int) NORETURN;
11271 static void
11272 raise_error_unexpected_syntax(int token)
11273 {
11274         char msg[64];
11275         char buf[16];
11276         int l;
11277
11278         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11279         if (token >= 0)
11280                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11281         raise_error_syntax(msg);
11282         /* NOTREACHED */
11283 }
11284
11285 /* parsing is heavily cross-recursive, need these forward decls */
11286 static union node *andor(void);
11287 static union node *pipeline(void);
11288 static union node *parse_command(void);
11289 static void parseheredoc(void);
11290 static int peektoken(void);
11291 static int readtoken(void);
11292
11293 static union node *
11294 list(int nlflag)
11295 {
11296         union node *n1, *n2, *n3;
11297         int tok;
11298
11299         n1 = NULL;
11300         for (;;) {
11301                 switch (peektoken()) {
11302                 case TNL:
11303                         if (!(nlflag & 1))
11304                                 break;
11305                         parseheredoc();
11306                         return n1;
11307
11308                 case TEOF:
11309                         if (!n1 && (nlflag & 1))
11310                                 n1 = NODE_EOF;
11311                         parseheredoc();
11312                         return n1;
11313                 }
11314
11315                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11316                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11317                         return n1;
11318                 nlflag |= 2;
11319
11320                 n2 = andor();
11321                 tok = readtoken();
11322                 if (tok == TBACKGND) {
11323                         if (n2->type == NPIPE) {
11324                                 n2->npipe.pipe_backgnd = 1;
11325                         } else {
11326                                 if (n2->type != NREDIR) {
11327                                         n3 = stzalloc(sizeof(struct nredir));
11328                                         n3->nredir.n = n2;
11329                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11330                                         n2 = n3;
11331                                 }
11332                                 n2->type = NBACKGND;
11333                         }
11334                 }
11335                 if (n1 == NULL) {
11336                         n1 = n2;
11337                 } else {
11338                         n3 = stzalloc(sizeof(struct nbinary));
11339                         n3->type = NSEMI;
11340                         n3->nbinary.ch1 = n1;
11341                         n3->nbinary.ch2 = n2;
11342                         n1 = n3;
11343                 }
11344                 switch (tok) {
11345                 case TNL:
11346                 case TEOF:
11347                         tokpushback = 1;
11348                         /* fall through */
11349                 case TBACKGND:
11350                 case TSEMI:
11351                         break;
11352                 default:
11353                         if ((nlflag & 1))
11354                                 raise_error_unexpected_syntax(-1);
11355                         tokpushback = 1;
11356                         return n1;
11357                 }
11358         }
11359 }
11360
11361 static union node *
11362 andor(void)
11363 {
11364         union node *n1, *n2, *n3;
11365         int t;
11366
11367         n1 = pipeline();
11368         for (;;) {
11369                 t = readtoken();
11370                 if (t == TAND) {
11371                         t = NAND;
11372                 } else if (t == TOR) {
11373                         t = NOR;
11374                 } else {
11375                         tokpushback = 1;
11376                         return n1;
11377                 }
11378                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11379                 n2 = pipeline();
11380                 n3 = stzalloc(sizeof(struct nbinary));
11381                 n3->type = t;
11382                 n3->nbinary.ch1 = n1;
11383                 n3->nbinary.ch2 = n2;
11384                 n1 = n3;
11385         }
11386 }
11387
11388 static union node *
11389 pipeline(void)
11390 {
11391         union node *n1, *n2, *pipenode;
11392         struct nodelist *lp, *prev;
11393         int negate;
11394
11395         negate = 0;
11396         TRACE(("pipeline: entered\n"));
11397         if (readtoken() == TNOT) {
11398                 negate = !negate;
11399                 checkkwd = CHKKWD | CHKALIAS;
11400         } else
11401                 tokpushback = 1;
11402         n1 = parse_command();
11403         if (readtoken() == TPIPE) {
11404                 pipenode = stzalloc(sizeof(struct npipe));
11405                 pipenode->type = NPIPE;
11406                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11407                 lp = stzalloc(sizeof(struct nodelist));
11408                 pipenode->npipe.cmdlist = lp;
11409                 lp->n = n1;
11410                 do {
11411                         prev = lp;
11412                         lp = stzalloc(sizeof(struct nodelist));
11413                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11414                         lp->n = parse_command();
11415                         prev->next = lp;
11416                 } while (readtoken() == TPIPE);
11417                 lp->next = NULL;
11418                 n1 = pipenode;
11419         }
11420         tokpushback = 1;
11421         if (negate) {
11422                 n2 = stzalloc(sizeof(struct nnot));
11423                 n2->type = NNOT;
11424                 n2->nnot.com = n1;
11425                 return n2;
11426         }
11427         return n1;
11428 }
11429
11430 static union node *
11431 makename(void)
11432 {
11433         union node *n;
11434
11435         n = stzalloc(sizeof(struct narg));
11436         n->type = NARG;
11437         /*n->narg.next = NULL; - stzalloc did it */
11438         n->narg.text = wordtext;
11439         n->narg.backquote = backquotelist;
11440         return n;
11441 }
11442
11443 static void
11444 fixredir(union node *n, const char *text, int err)
11445 {
11446         int fd;
11447
11448         TRACE(("Fix redir %s %d\n", text, err));
11449         if (!err)
11450                 n->ndup.vname = NULL;
11451
11452         fd = bb_strtou(text, NULL, 10);
11453         if (!errno && fd >= 0)
11454                 n->ndup.dupfd = fd;
11455         else if (LONE_DASH(text))
11456                 n->ndup.dupfd = -1;
11457         else {
11458                 if (err)
11459                         raise_error_syntax("bad fd number");
11460                 n->ndup.vname = makename();
11461         }
11462 }
11463
11464 static void
11465 parsefname(void)
11466 {
11467         union node *n = redirnode;
11468
11469         if (n->type == NHERE)
11470                 checkkwd = CHKEOFMARK;
11471         if (readtoken() != TWORD)
11472                 raise_error_unexpected_syntax(-1);
11473         if (n->type == NHERE) {
11474                 struct heredoc *here = heredoc;
11475                 struct heredoc *p;
11476
11477                 if (quoteflag == 0)
11478                         n->type = NXHERE;
11479                 TRACE(("Here document %d\n", n->type));
11480                 rmescapes(wordtext, 0, NULL);
11481                 here->eofmark = wordtext;
11482                 here->next = NULL;
11483                 if (heredoclist == NULL)
11484                         heredoclist = here;
11485                 else {
11486                         for (p = heredoclist; p->next; p = p->next)
11487                                 continue;
11488                         p->next = here;
11489                 }
11490         } else if (n->type == NTOFD || n->type == NFROMFD) {
11491                 fixredir(n, wordtext, 0);
11492         } else {
11493                 n->nfile.fname = makename();
11494         }
11495 }
11496
11497 static union node *
11498 simplecmd(void)
11499 {
11500         union node *args, **app;
11501         union node *n = NULL;
11502         union node *vars, **vpp;
11503         union node **rpp, *redir;
11504         int savecheckkwd;
11505         int savelinno;
11506 #if BASH_TEST2
11507         smallint double_brackets_flag = 0;
11508 #endif
11509         IF_BASH_FUNCTION(smallint function_flag = 0;)
11510
11511         args = NULL;
11512         app = &args;
11513         vars = NULL;
11514         vpp = &vars;
11515         redir = NULL;
11516         rpp = &redir;
11517
11518         savecheckkwd = CHKALIAS;
11519         savelinno = g_parsefile->linno;
11520         for (;;) {
11521                 int t;
11522                 checkkwd = savecheckkwd;
11523                 t = readtoken();
11524                 switch (t) {
11525 #if BASH_FUNCTION
11526                 case TFUNCTION:
11527                         if (peektoken() != TWORD)
11528                                 raise_error_unexpected_syntax(TWORD);
11529                         function_flag = 1;
11530                         break;
11531 #endif
11532 #if BASH_TEST2
11533                 case TAND: /* "&&" */
11534                 case TOR: /* "||" */
11535                         if (!double_brackets_flag) {
11536                                 tokpushback = 1;
11537                                 goto out;
11538                         }
11539                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11540 #endif
11541                 case TWORD:
11542                         n = stzalloc(sizeof(struct narg));
11543                         n->type = NARG;
11544                         /*n->narg.next = NULL; - stzalloc did it */
11545                         n->narg.text = wordtext;
11546 #if BASH_TEST2
11547                         if (strcmp("[[", wordtext) == 0)
11548                                 double_brackets_flag = 1;
11549                         else if (strcmp("]]", wordtext) == 0)
11550                                 double_brackets_flag = 0;
11551 #endif
11552                         n->narg.backquote = backquotelist;
11553                         if (savecheckkwd && isassignment(wordtext)) {
11554                                 *vpp = n;
11555                                 vpp = &n->narg.next;
11556                         } else {
11557                                 *app = n;
11558                                 app = &n->narg.next;
11559                                 savecheckkwd = 0;
11560                         }
11561 #if BASH_FUNCTION
11562                         if (function_flag) {
11563                                 checkkwd = CHKNL | CHKKWD;
11564                                 switch (peektoken()) {
11565                                 case TBEGIN:
11566                                 case TIF:
11567                                 case TCASE:
11568                                 case TUNTIL:
11569                                 case TWHILE:
11570                                 case TFOR:
11571                                         goto do_func;
11572                                 case TLP:
11573                                         function_flag = 0;
11574                                         break;
11575                                 case TWORD:
11576                                         if (strcmp("[[", wordtext) == 0)
11577                                                 goto do_func;
11578                                         /* fall through */
11579                                 default:
11580                                         raise_error_unexpected_syntax(-1);
11581                                 }
11582                         }
11583 #endif
11584                         break;
11585                 case TREDIR:
11586                         *rpp = n = redirnode;
11587                         rpp = &n->nfile.next;
11588                         parsefname();   /* read name of redirection file */
11589                         break;
11590                 case TLP:
11591  IF_BASH_FUNCTION(do_func:)
11592                         if (args && app == &args->narg.next
11593                          && !vars && !redir
11594                         ) {
11595                                 struct builtincmd *bcmd;
11596                                 const char *name;
11597
11598                                 /* We have a function */
11599                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11600                                         raise_error_unexpected_syntax(TRP);
11601                                 name = n->narg.text;
11602                                 if (!goodname(name)
11603                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11604                                 ) {
11605                                         raise_error_syntax("bad function name");
11606                                 }
11607                                 n->type = NDEFUN;
11608                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11609                                 n->ndefun.text = n->narg.text;
11610                                 n->ndefun.linno = g_parsefile->linno;
11611                                 n->ndefun.body = parse_command();
11612                                 return n;
11613                         }
11614                         IF_BASH_FUNCTION(function_flag = 0;)
11615                         /* fall through */
11616                 default:
11617                         tokpushback = 1;
11618                         goto out;
11619                 }
11620         }
11621  out:
11622         *app = NULL;
11623         *vpp = NULL;
11624         *rpp = NULL;
11625         n = stzalloc(sizeof(struct ncmd));
11626         n->type = NCMD;
11627         n->ncmd.linno = savelinno;
11628         n->ncmd.args = args;
11629         n->ncmd.assign = vars;
11630         n->ncmd.redirect = redir;
11631         return n;
11632 }
11633
11634 static union node *
11635 parse_command(void)
11636 {
11637         union node *n1, *n2;
11638         union node *ap, **app;
11639         union node *cp, **cpp;
11640         union node *redir, **rpp;
11641         union node **rpp2;
11642         int t;
11643         int savelinno;
11644
11645         redir = NULL;
11646         rpp2 = &redir;
11647
11648         savelinno = g_parsefile->linno;
11649
11650         switch (readtoken()) {
11651         default:
11652                 raise_error_unexpected_syntax(-1);
11653                 /* NOTREACHED */
11654         case TIF:
11655                 n1 = stzalloc(sizeof(struct nif));
11656                 n1->type = NIF;
11657                 n1->nif.test = list(0);
11658                 if (readtoken() != TTHEN)
11659                         raise_error_unexpected_syntax(TTHEN);
11660                 n1->nif.ifpart = list(0);
11661                 n2 = n1;
11662                 while (readtoken() == TELIF) {
11663                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11664                         n2 = n2->nif.elsepart;
11665                         n2->type = NIF;
11666                         n2->nif.test = list(0);
11667                         if (readtoken() != TTHEN)
11668                                 raise_error_unexpected_syntax(TTHEN);
11669                         n2->nif.ifpart = list(0);
11670                 }
11671                 if (lasttoken == TELSE)
11672                         n2->nif.elsepart = list(0);
11673                 else {
11674                         n2->nif.elsepart = NULL;
11675                         tokpushback = 1;
11676                 }
11677                 t = TFI;
11678                 break;
11679         case TWHILE:
11680         case TUNTIL: {
11681                 int got;
11682                 n1 = stzalloc(sizeof(struct nbinary));
11683                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11684                 n1->nbinary.ch1 = list(0);
11685                 got = readtoken();
11686                 if (got != TDO) {
11687                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11688                                         got == TWORD ? wordtext : ""));
11689                         raise_error_unexpected_syntax(TDO);
11690                 }
11691                 n1->nbinary.ch2 = list(0);
11692                 t = TDONE;
11693                 break;
11694         }
11695         case TFOR:
11696                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11697                         raise_error_syntax("bad for loop variable");
11698                 n1 = stzalloc(sizeof(struct nfor));
11699                 n1->type = NFOR;
11700                 n1->nfor.linno = savelinno;
11701                 n1->nfor.var = wordtext;
11702                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11703                 if (readtoken() == TIN) {
11704                         app = &ap;
11705                         while (readtoken() == TWORD) {
11706                                 n2 = stzalloc(sizeof(struct narg));
11707                                 n2->type = NARG;
11708                                 /*n2->narg.next = NULL; - stzalloc did it */
11709                                 n2->narg.text = wordtext;
11710                                 n2->narg.backquote = backquotelist;
11711                                 *app = n2;
11712                                 app = &n2->narg.next;
11713                         }
11714                         *app = NULL;
11715                         n1->nfor.args = ap;
11716                         if (lasttoken != TNL && lasttoken != TSEMI)
11717                                 raise_error_unexpected_syntax(-1);
11718                 } else {
11719                         n2 = stzalloc(sizeof(struct narg));
11720                         n2->type = NARG;
11721                         /*n2->narg.next = NULL; - stzalloc did it */
11722                         n2->narg.text = (char *)dolatstr;
11723                         /*n2->narg.backquote = NULL;*/
11724                         n1->nfor.args = n2;
11725                         /*
11726                          * Newline or semicolon here is optional (but note
11727                          * that the original Bourne shell only allowed NL).
11728                          */
11729                         if (lasttoken != TSEMI)
11730                                 tokpushback = 1;
11731                 }
11732                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11733                 if (readtoken() != TDO)
11734                         raise_error_unexpected_syntax(TDO);
11735                 n1->nfor.body = list(0);
11736                 t = TDONE;
11737                 break;
11738         case TCASE:
11739                 n1 = stzalloc(sizeof(struct ncase));
11740                 n1->type = NCASE;
11741                 n1->ncase.linno = savelinno;
11742                 if (readtoken() != TWORD)
11743                         raise_error_unexpected_syntax(TWORD);
11744                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11745                 n2->type = NARG;
11746                 /*n2->narg.next = NULL; - stzalloc did it */
11747                 n2->narg.text = wordtext;
11748                 n2->narg.backquote = backquotelist;
11749                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11750                 if (readtoken() != TIN)
11751                         raise_error_unexpected_syntax(TIN);
11752                 cpp = &n1->ncase.cases;
11753  next_case:
11754                 checkkwd = CHKNL | CHKKWD;
11755                 t = readtoken();
11756                 while (t != TESAC) {
11757                         if (lasttoken == TLP)
11758                                 readtoken();
11759                         *cpp = cp = stzalloc(sizeof(struct nclist));
11760                         cp->type = NCLIST;
11761                         app = &cp->nclist.pattern;
11762                         for (;;) {
11763                                 *app = ap = stzalloc(sizeof(struct narg));
11764                                 ap->type = NARG;
11765                                 /*ap->narg.next = NULL; - stzalloc did it */
11766                                 ap->narg.text = wordtext;
11767                                 ap->narg.backquote = backquotelist;
11768                                 if (readtoken() != TPIPE)
11769                                         break;
11770                                 app = &ap->narg.next;
11771                                 readtoken();
11772                         }
11773                         //ap->narg.next = NULL;
11774                         if (lasttoken != TRP)
11775                                 raise_error_unexpected_syntax(TRP);
11776                         cp->nclist.body = list(2);
11777
11778                         cpp = &cp->nclist.next;
11779
11780                         checkkwd = CHKNL | CHKKWD;
11781                         t = readtoken();
11782                         if (t != TESAC) {
11783                                 if (t != TENDCASE)
11784                                         raise_error_unexpected_syntax(TENDCASE);
11785                                 goto next_case;
11786                         }
11787                 }
11788                 *cpp = NULL;
11789                 goto redir;
11790         case TLP:
11791                 n1 = stzalloc(sizeof(struct nredir));
11792                 n1->type = NSUBSHELL;
11793                 n1->nredir.linno = savelinno;
11794                 n1->nredir.n = list(0);
11795                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11796                 t = TRP;
11797                 break;
11798         case TBEGIN:
11799                 n1 = list(0);
11800                 t = TEND;
11801                 break;
11802         IF_BASH_FUNCTION(case TFUNCTION:)
11803         case TWORD:
11804         case TREDIR:
11805                 tokpushback = 1;
11806                 return simplecmd();
11807         }
11808
11809         if (readtoken() != t)
11810                 raise_error_unexpected_syntax(t);
11811
11812  redir:
11813         /* Now check for redirection which may follow command */
11814         checkkwd = CHKKWD | CHKALIAS;
11815         rpp = rpp2;
11816         while (readtoken() == TREDIR) {
11817                 *rpp = n2 = redirnode;
11818                 rpp = &n2->nfile.next;
11819                 parsefname();
11820         }
11821         tokpushback = 1;
11822         *rpp = NULL;
11823         if (redir) {
11824                 if (n1->type != NSUBSHELL) {
11825                         n2 = stzalloc(sizeof(struct nredir));
11826                         n2->type = NREDIR;
11827                         n2->nredir.linno = savelinno;
11828                         n2->nredir.n = n1;
11829                         n1 = n2;
11830                 }
11831                 n1->nredir.redirect = redir;
11832         }
11833         return n1;
11834 }
11835
11836 #if BASH_DOLLAR_SQUOTE
11837 static int
11838 decode_dollar_squote(void)
11839 {
11840         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11841         int c, cnt;
11842         char *p;
11843         char buf[4];
11844
11845         c = pgetc();
11846         p = strchr(C_escapes, c);
11847         if (p) {
11848                 buf[0] = c;
11849                 p = buf;
11850                 cnt = 3;
11851                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11852                         do {
11853                                 c = pgetc();
11854                                 *++p = c;
11855                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11856                         pungetc();
11857                 } else if (c == 'x') { /* \xHH */
11858                         do {
11859                                 c = pgetc();
11860                                 *++p = c;
11861                         } while (isxdigit(c) && --cnt);
11862                         pungetc();
11863                         if (cnt == 3) { /* \x but next char is "bad" */
11864                                 c = 'x';
11865                                 goto unrecognized;
11866                         }
11867                 } else { /* simple seq like \\ or \t */
11868                         p++;
11869                 }
11870                 *p = '\0';
11871                 p = buf;
11872                 c = bb_process_escape_sequence((void*)&p);
11873         } else { /* unrecognized "\z": print both chars unless ' or " */
11874                 if (c != '\'' && c != '"') {
11875  unrecognized:
11876                         c |= 0x100; /* "please encode \, then me" */
11877                 }
11878         }
11879         return c;
11880 }
11881 #endif
11882
11883 /* Used by expandstr to get here-doc like behaviour. */
11884 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11885
11886 static ALWAYS_INLINE int
11887 realeofmark(const char *eofmark)
11888 {
11889         return eofmark && eofmark != FAKEEOFMARK;
11890 }
11891
11892 /*
11893  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11894  * is not NULL, read a here document.  In the latter case, eofmark is the
11895  * word which marks the end of the document and striptabs is true if
11896  * leading tabs should be stripped from the document.  The argument c
11897  * is the first character of the input token or document.
11898  *
11899  * Because C does not have internal subroutines, I have simulated them
11900  * using goto's to implement the subroutine linkage.  The following macros
11901  * will run code that appears at the end of readtoken1.
11902  */
11903 #define CHECKEND()      {goto checkend; checkend_return:;}
11904 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11905 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11906 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11907 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11908 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11909 static int
11910 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11911 {
11912         /* NB: syntax parameter fits into smallint */
11913         /* c parameter is an unsigned char or PEOF or PEOA */
11914         char *out;
11915         size_t len;
11916         struct nodelist *bqlist;
11917         smallint quotef;
11918         smallint dblquote;
11919         smallint oldstyle;
11920         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11921         smallint pssyntax;   /* we are expanding a prompt string */
11922         int varnest;         /* levels of variables expansion */
11923         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11924         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11925         int dqvarnest;       /* levels of variables expansion within double quotes */
11926         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11927
11928         bqlist = NULL;
11929         quotef = 0;
11930         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11931 #if ENABLE_ASH_EXPAND_PRMT
11932         pssyntax = (syntax == PSSYNTAX);
11933         if (pssyntax)
11934                 syntax = DQSYNTAX;
11935 #else
11936         pssyntax = 0; /* constant */
11937 #endif
11938         dblquote = (syntax == DQSYNTAX);
11939         varnest = 0;
11940         IF_FEATURE_SH_MATH(arinest = 0;)
11941         IF_FEATURE_SH_MATH(parenlevel = 0;)
11942         dqvarnest = 0;
11943
11944         STARTSTACKSTR(out);
11945  loop:
11946         /* For each line, until end of word */
11947         CHECKEND();     /* set c to PEOF if at end of here document */
11948         for (;;) {      /* until end of line or end of word */
11949                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11950                 switch (SIT(c, syntax)) {
11951                 case CNL:       /* '\n' */
11952                         if (syntax == BASESYNTAX)
11953                                 goto endword;   /* exit outer loop */
11954                         USTPUTC(c, out);
11955                         nlprompt();
11956                         c = pgetc();
11957                         goto loop;              /* continue outer loop */
11958                 case CWORD:
11959                         USTPUTC(c, out);
11960                         break;
11961                 case CCTL:
11962 #if BASH_DOLLAR_SQUOTE
11963                         if (c == '\\' && bash_dollar_squote) {
11964                                 c = decode_dollar_squote();
11965                                 if (c == '\0') {
11966                                         /* skip $'\000', $'\x00' (like bash) */
11967                                         break;
11968                                 }
11969                                 if (c & 0x100) {
11970                                         /* Unknown escape. Encode as '\z' */
11971                                         c = (unsigned char)c;
11972                                         if (eofmark == NULL || dblquote)
11973                                                 USTPUTC(CTLESC, out);
11974                                         USTPUTC('\\', out);
11975                                 }
11976                         }
11977 #endif
11978                         if (eofmark == NULL || dblquote)
11979                                 USTPUTC(CTLESC, out);
11980                         USTPUTC(c, out);
11981                         break;
11982                 case CBACK:     /* backslash */
11983                         c = pgetc_without_PEOA();
11984                         if (c == PEOF) {
11985                                 USTPUTC(CTLESC, out);
11986                                 USTPUTC('\\', out);
11987                                 pungetc();
11988                         } else if (c == '\n') {
11989                                 nlprompt();
11990                         } else {
11991                                 if (pssyntax && c == '$') {
11992                                         USTPUTC(CTLESC, out);
11993                                         USTPUTC('\\', out);
11994                                 }
11995                                 /* Backslash is retained if we are in "str" and next char isn't special */
11996                                 if (dblquote
11997                                  && c != '\\'
11998                                  && c != '`'
11999                                  && c != '$'
12000                                  && (c != '"' || eofmark != NULL)
12001                                 ) {
12002                                         USTPUTC('\\', out);
12003                                 }
12004                                 USTPUTC(CTLESC, out);
12005                                 USTPUTC(c, out);
12006                                 quotef = 1;
12007                         }
12008                         break;
12009                 case CSQUOTE:
12010                         syntax = SQSYNTAX;
12011  quotemark:
12012                         if (eofmark == NULL) {
12013                                 USTPUTC(CTLQUOTEMARK, out);
12014                         }
12015                         break;
12016                 case CDQUOTE:
12017                         syntax = DQSYNTAX;
12018                         dblquote = 1;
12019                         goto quotemark;
12020                 case CENDQUOTE:
12021                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12022                         if (eofmark != NULL && varnest == 0) {
12023                                 USTPUTC(c, out);
12024                         } else {
12025                                 if (dqvarnest == 0) {
12026                                         syntax = BASESYNTAX;
12027                                         dblquote = 0;
12028                                 }
12029                                 quotef = 1;
12030                                 goto quotemark;
12031                         }
12032                         break;
12033                 case CVAR:      /* '$' */
12034                         PARSESUB();             /* parse substitution */
12035                         break;
12036                 case CENDVAR:   /* '}' */
12037                         if (varnest > 0) {
12038                                 varnest--;
12039                                 if (dqvarnest > 0) {
12040                                         dqvarnest--;
12041                                 }
12042                                 c = CTLENDVAR;
12043                         }
12044                         USTPUTC(c, out);
12045                         break;
12046 #if ENABLE_FEATURE_SH_MATH
12047                 case CLP:       /* '(' in arithmetic */
12048                         parenlevel++;
12049                         USTPUTC(c, out);
12050                         break;
12051                 case CRP:       /* ')' in arithmetic */
12052                         if (parenlevel > 0) {
12053                                 parenlevel--;
12054                         } else {
12055                                 if (pgetc_eatbnl() == ')') {
12056                                         c = CTLENDARI;
12057                                         if (--arinest == 0) {
12058                                                 syntax = prevsyntax;
12059                                         }
12060                                 } else {
12061                                         /*
12062                                          * unbalanced parens
12063                                          * (don't 2nd guess - no error)
12064                                          */
12065                                         pungetc();
12066                                 }
12067                         }
12068                         USTPUTC(c, out);
12069                         break;
12070 #endif
12071                 case CBQUOTE:   /* '`' */
12072                         PARSEBACKQOLD();
12073                         break;
12074                 case CENDFILE:
12075                         goto endword;           /* exit outer loop */
12076                 case CIGN:
12077                         break;
12078                 default:
12079                         if (varnest == 0) {
12080 #if BASH_REDIR_OUTPUT
12081                                 if (c == '&') {
12082 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12083                                         if (pgetc() == '>')
12084                                                 c = 0x100 + '>'; /* flag &> */
12085                                         pungetc();
12086                                 }
12087 #endif
12088                                 goto endword;   /* exit outer loop */
12089                         }
12090                         IF_ASH_ALIAS(if (c != PEOA))
12091                                 USTPUTC(c, out);
12092                 }
12093                 c = pgetc();
12094         } /* for (;;) */
12095  endword:
12096
12097 #if ENABLE_FEATURE_SH_MATH
12098         if (syntax == ARISYNTAX)
12099                 raise_error_syntax("missing '))'");
12100 #endif
12101         if (syntax != BASESYNTAX && eofmark == NULL)
12102                 raise_error_syntax("unterminated quoted string");
12103         if (varnest != 0) {
12104                 /* { */
12105                 raise_error_syntax("missing '}'");
12106         }
12107         USTPUTC('\0', out);
12108         len = out - (char *)stackblock();
12109         out = stackblock();
12110         if (eofmark == NULL) {
12111                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12112                  && quotef == 0
12113                 ) {
12114                         if (isdigit_str9(out)) {
12115                                 PARSEREDIR(); /* passed as params: out, c */
12116                                 lasttoken = TREDIR;
12117                                 return lasttoken;
12118                         }
12119                         /* else: non-number X seen, interpret it
12120                          * as "NNNX>file" = "NNNX >file" */
12121                 }
12122                 pungetc();
12123         }
12124         quoteflag = quotef;
12125         backquotelist = bqlist;
12126         grabstackblock(len);
12127         wordtext = out;
12128         lasttoken = TWORD;
12129         return lasttoken;
12130 /* end of readtoken routine */
12131
12132 /*
12133  * Check to see whether we are at the end of the here document.  When this
12134  * is called, c is set to the first character of the next input line.  If
12135  * we are at the end of the here document, this routine sets the c to PEOF.
12136  */
12137 checkend: {
12138         if (realeofmark(eofmark)) {
12139                 int markloc;
12140                 char *p;
12141
12142 #if ENABLE_ASH_ALIAS
12143                 if (c == PEOA)
12144                         c = pgetc_without_PEOA();
12145 #endif
12146                 if (striptabs) {
12147                         while (c == '\t') {
12148                                 c = pgetc_without_PEOA();
12149                         }
12150                 }
12151
12152                 markloc = out - (char *)stackblock();
12153                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12154                         if (c != *p)
12155                                 goto more_heredoc;
12156
12157                         c = pgetc_without_PEOA();
12158                 }
12159
12160                 if (c == '\n' || c == PEOF) {
12161                         c = PEOF;
12162                         g_parsefile->linno++;
12163                         needprompt = doprompt;
12164                 } else {
12165                         int len_here;
12166
12167  more_heredoc:
12168                         p = (char *)stackblock() + markloc + 1;
12169                         len_here = out - p;
12170
12171                         if (len_here) {
12172                                 len_here -= (c >= PEOF);
12173                                 c = p[-1];
12174
12175                                 if (len_here) {
12176                                         char *str;
12177
12178                                         str = alloca(len_here + 1);
12179                                         *(char *)mempcpy(str, p, len_here) = '\0';
12180
12181                                         pushstring(str, NULL);
12182                                 }
12183                         }
12184                 }
12185
12186                 STADJUST((char *)stackblock() + markloc - out, out);
12187         }
12188         goto checkend_return;
12189 }
12190
12191 /*
12192  * Parse a redirection operator.  The variable "out" points to a string
12193  * specifying the fd to be redirected.  The variable "c" contains the
12194  * first character of the redirection operator.
12195  */
12196 parseredir: {
12197         /* out is already checked to be a valid number or "" */
12198         int fd = (*out == '\0' ? -1 : atoi(out));
12199         union node *np;
12200
12201         np = stzalloc(sizeof(struct nfile));
12202         if (c == '>') {
12203                 np->nfile.fd = 1;
12204                 c = pgetc();
12205                 if (c == '>')
12206                         np->type = NAPPEND;
12207                 else if (c == '|')
12208                         np->type = NCLOBBER;
12209                 else if (c == '&')
12210                         np->type = NTOFD;
12211                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12212                 else {
12213                         np->type = NTO;
12214                         pungetc();
12215                 }
12216         }
12217 #if BASH_REDIR_OUTPUT
12218         else if (c == 0x100 + '>') { /* this flags &> redirection */
12219                 np->nfile.fd = 1;
12220                 pgetc(); /* this is '>', no need to check */
12221                 np->type = NTO2;
12222         }
12223 #endif
12224         else { /* c == '<' */
12225                 /*np->nfile.fd = 0; - stzalloc did it */
12226                 c = pgetc();
12227                 switch (c) {
12228                 case '<':
12229                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12230                                 np = stzalloc(sizeof(struct nhere));
12231                                 /*np->nfile.fd = 0; - stzalloc did it */
12232                         }
12233                         np->type = NHERE;
12234                         heredoc = stzalloc(sizeof(struct heredoc));
12235                         heredoc->here = np;
12236                         c = pgetc();
12237                         if (c == '-') {
12238                                 heredoc->striptabs = 1;
12239                         } else {
12240                                 /*heredoc->striptabs = 0; - stzalloc did it */
12241                                 pungetc();
12242                         }
12243                         break;
12244
12245                 case '&':
12246                         np->type = NFROMFD;
12247                         break;
12248
12249                 case '>':
12250                         np->type = NFROMTO;
12251                         break;
12252
12253                 default:
12254                         np->type = NFROM;
12255                         pungetc();
12256                         break;
12257                 }
12258         }
12259         if (fd >= 0)
12260                 np->nfile.fd = fd;
12261         redirnode = np;
12262         goto parseredir_return;
12263 }
12264
12265 /*
12266  * Parse a substitution.  At this point, we have read the dollar sign
12267  * and nothing else.
12268  */
12269
12270 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12271  * (assuming ascii char codes, as the original implementation did) */
12272 #define is_special(c) \
12273         (((unsigned)(c) - 33 < 32) \
12274                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12275 parsesub: {
12276         unsigned char subtype;
12277         int typeloc;
12278
12279         c = pgetc_eatbnl();
12280         if ((checkkwd & CHKEOFMARK)
12281          || c > 255 /* PEOA or PEOF */
12282          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12283         ) {
12284 #if BASH_DOLLAR_SQUOTE
12285                 if (syntax != DQSYNTAX && c == '\'')
12286                         bash_dollar_squote = 1;
12287                 else
12288 #endif
12289                         USTPUTC('$', out);
12290                 pungetc();
12291         } else if (c == '(') {
12292                 /* $(command) or $((arith)) */
12293                 if (pgetc_eatbnl() == '(') {
12294 #if ENABLE_FEATURE_SH_MATH
12295                         PARSEARITH();
12296 #else
12297                         raise_error_syntax("support for $((arith)) is disabled");
12298 #endif
12299                 } else {
12300                         pungetc();
12301                         PARSEBACKQNEW();
12302                 }
12303         } else {
12304                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12305                 USTPUTC(CTLVAR, out);
12306                 typeloc = out - (char *)stackblock();
12307                 STADJUST(1, out);
12308                 subtype = VSNORMAL;
12309                 if (c == '{') {
12310                         c = pgetc_eatbnl();
12311                         subtype = 0;
12312                 }
12313  varname:
12314                 if (is_name(c)) {
12315                         /* $[{[#]]NAME[}] */
12316                         do {
12317                                 STPUTC(c, out);
12318                                 c = pgetc_eatbnl();
12319                         } while (is_in_name(c));
12320                 } else if (isdigit(c)) {
12321                         /* $[{[#]]NUM[}] */
12322                         do {
12323                                 STPUTC(c, out);
12324                                 c = pgetc_eatbnl();
12325                         } while (isdigit(c));
12326                 } else {
12327                         /* $[{[#]]<specialchar>[}] */
12328                         int cc = c;
12329
12330                         c = pgetc_eatbnl();
12331                         if (!subtype && cc == '#') {
12332                                 subtype = VSLENGTH;
12333                                 if (c == '_' || isalnum(c))
12334                                         goto varname;
12335                                 cc = c;
12336                                 c = pgetc_eatbnl();
12337                                 if (cc == '}' || c != '}') {
12338                                         pungetc();
12339                                         subtype = 0;
12340                                         c = cc;
12341                                         cc = '#';
12342                                 }
12343                         }
12344
12345                         if (!is_special(cc)) {
12346                                 if (subtype == VSLENGTH)
12347                                         subtype = 0;
12348                                 goto badsub;
12349                         }
12350
12351                         USTPUTC(cc, out);
12352                 }
12353
12354                 if (c != '}' && subtype == VSLENGTH) {
12355                         /* ${#VAR didn't end with } */
12356                         goto badsub;
12357                 }
12358
12359                 if (subtype == 0) {
12360                         static const char types[] ALIGN1 = "}-+?=";
12361                         /* ${VAR...} but not $VAR or ${#VAR} */
12362                         /* c == first char after VAR */
12363                         switch (c) {
12364                         case ':':
12365                                 c = pgetc_eatbnl();
12366 #if BASH_SUBSTR
12367                                 /* This check is only needed to not misinterpret
12368                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12369                                  * constructs.
12370                                  */
12371                                 if (!strchr(types, c)) {
12372                                         subtype = VSSUBSTR;
12373                                         pungetc();
12374                                         break; /* "goto badsub" is bigger (!) */
12375                                 }
12376 #endif
12377                                 subtype = VSNUL;
12378                                 /*FALLTHROUGH*/
12379                         default: {
12380                                 const char *p = strchr(types, c);
12381                                 if (p == NULL)
12382                                         break;
12383                                 subtype |= p - types + VSNORMAL;
12384                                 break;
12385                         }
12386                         case '%':
12387                         case '#': {
12388                                 int cc = c;
12389                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12390                                 c = pgetc_eatbnl();
12391                                 if (c != cc)
12392                                         goto badsub;
12393                                 subtype++;
12394                                 break;
12395                         }
12396 #if BASH_PATTERN_SUBST
12397                         case '/':
12398                                 /* ${v/[/]pattern/repl} */
12399 //TODO: encode pattern and repl separately.
12400 // Currently ${v/$var_with_slash/repl} is horribly broken
12401                                 subtype = VSREPLACE;
12402                                 c = pgetc_eatbnl();
12403                                 if (c != '/')
12404                                         goto badsub;
12405                                 subtype++; /* VSREPLACEALL */
12406                                 break;
12407 #endif
12408                         }
12409                 } else {
12410  badsub:
12411                         pungetc();
12412                 }
12413                 ((unsigned char *)stackblock())[typeloc] = subtype;
12414                 if (subtype != VSNORMAL) {
12415                         varnest++;
12416                         if (dblquote)
12417                                 dqvarnest++;
12418                 }
12419                 STPUTC('=', out);
12420         }
12421         goto parsesub_return;
12422 }
12423
12424 /*
12425  * Called to parse command substitutions.  Newstyle is set if the command
12426  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12427  * list of commands (passed by reference), and savelen is the number of
12428  * characters on the top of the stack which must be preserved.
12429  */
12430 parsebackq: {
12431         struct nodelist **nlpp;
12432         union node *n;
12433         char *str;
12434         size_t savelen;
12435         smallint saveprompt = 0;
12436
12437         str = NULL;
12438         savelen = out - (char *)stackblock();
12439         if (savelen > 0) {
12440                 /*
12441                  * FIXME: this can allocate very large block on stack and SEGV.
12442                  * Example:
12443                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12444                  * allocates 100kb for every command subst. With about
12445                  * a hundred command substitutions stack overflows.
12446                  * With larger prepended string, SEGV happens sooner.
12447                  */
12448                 str = alloca(savelen);
12449                 memcpy(str, stackblock(), savelen);
12450         }
12451
12452         if (oldstyle) {
12453                 /* We must read until the closing backquote, giving special
12454                  * treatment to some slashes, and then push the string and
12455                  * reread it as input, interpreting it normally.
12456                  */
12457                 char *pout;
12458                 size_t psavelen;
12459                 char *pstr;
12460
12461                 STARTSTACKSTR(pout);
12462                 for (;;) {
12463                         int pc;
12464
12465                         setprompt_if(needprompt, 2);
12466                         pc = pgetc();
12467                         switch (pc) {
12468                         case '`':
12469                                 goto done;
12470
12471                         case '\\':
12472                                 pc = pgetc();
12473                                 if (pc == '\n') {
12474                                         nlprompt();
12475                                         /*
12476                                          * If eating a newline, avoid putting
12477                                          * the newline into the new character
12478                                          * stream (via the STPUTC after the
12479                                          * switch).
12480                                          */
12481                                         continue;
12482                                 }
12483                                 if (pc != '\\' && pc != '`' && pc != '$'
12484                                  && (!dblquote || pc != '"')
12485                                 ) {
12486                                         STPUTC('\\', pout);
12487                                 }
12488                                 if (pc <= 255 /* not PEOA or PEOF */) {
12489                                         break;
12490                                 }
12491                                 /* fall through */
12492
12493                         case PEOF:
12494                         IF_ASH_ALIAS(case PEOA:)
12495                                 raise_error_syntax("EOF in backquote substitution");
12496
12497                         case '\n':
12498                                 nlnoprompt();
12499                                 break;
12500
12501                         default:
12502                                 break;
12503                         }
12504                         STPUTC(pc, pout);
12505                 }
12506  done:
12507                 STPUTC('\0', pout);
12508                 psavelen = pout - (char *)stackblock();
12509                 if (psavelen > 0) {
12510                         pstr = grabstackstr(pout);
12511                         setinputstring(pstr);
12512                 }
12513         }
12514         nlpp = &bqlist;
12515         while (*nlpp)
12516                 nlpp = &(*nlpp)->next;
12517         *nlpp = stzalloc(sizeof(**nlpp));
12518         /* (*nlpp)->next = NULL; - stzalloc did it */
12519
12520         if (oldstyle) {
12521                 saveprompt = doprompt;
12522                 doprompt = 0;
12523         }
12524
12525         n = list(2);
12526
12527         if (oldstyle)
12528                 doprompt = saveprompt;
12529         else if (readtoken() != TRP)
12530                 raise_error_unexpected_syntax(TRP);
12531
12532         (*nlpp)->n = n;
12533         if (oldstyle) {
12534                 /*
12535                  * Start reading from old file again, ignoring any pushed back
12536                  * tokens left from the backquote parsing
12537                  */
12538                 popfile();
12539                 tokpushback = 0;
12540         }
12541         while (stackblocksize() <= savelen)
12542                 growstackblock();
12543         STARTSTACKSTR(out);
12544         if (str) {
12545                 memcpy(out, str, savelen);
12546                 STADJUST(savelen, out);
12547         }
12548         USTPUTC(CTLBACKQ, out);
12549         if (oldstyle)
12550                 goto parsebackq_oldreturn;
12551         goto parsebackq_newreturn;
12552 }
12553
12554 #if ENABLE_FEATURE_SH_MATH
12555 /*
12556  * Parse an arithmetic expansion (indicate start of one and set state)
12557  */
12558 parsearith: {
12559         if (++arinest == 1) {
12560                 prevsyntax = syntax;
12561                 syntax = ARISYNTAX;
12562         }
12563         USTPUTC(CTLARI, out);
12564         goto parsearith_return;
12565 }
12566 #endif
12567 } /* end of readtoken */
12568
12569 /*
12570  * Read the next input token.
12571  * If the token is a word, we set backquotelist to the list of cmds in
12572  *      backquotes.  We set quoteflag to true if any part of the word was
12573  *      quoted.
12574  * If the token is TREDIR, then we set redirnode to a structure containing
12575  *      the redirection.
12576  *
12577  * [Change comment:  here documents and internal procedures]
12578  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12579  *  word parsing code into a separate routine.  In this case, readtoken
12580  *  doesn't need to have any internal procedures, but parseword does.
12581  *  We could also make parseoperator in essence the main routine, and
12582  *  have parseword (readtoken1?) handle both words and redirection.]
12583  */
12584 #define NEW_xxreadtoken
12585 #ifdef NEW_xxreadtoken
12586 /* singles must be first! */
12587 static const char xxreadtoken_chars[7] ALIGN1 = {
12588         '\n', '(', ')', /* singles */
12589         '&', '|', ';',  /* doubles */
12590         0
12591 };
12592
12593 #define xxreadtoken_singles 3
12594 #define xxreadtoken_doubles 3
12595
12596 static const char xxreadtoken_tokens[] ALIGN1 = {
12597         TNL, TLP, TRP,          /* only single occurrence allowed */
12598         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12599         TEOF,                   /* corresponds to trailing nul */
12600         TAND, TOR, TENDCASE     /* if double occurrence */
12601 };
12602
12603 static int
12604 xxreadtoken(void)
12605 {
12606         int c;
12607
12608         if (tokpushback) {
12609                 tokpushback = 0;
12610                 return lasttoken;
12611         }
12612         setprompt_if(needprompt, 2);
12613         for (;;) {                      /* until token or start of word found */
12614                 c = pgetc();
12615                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12616                         continue;
12617
12618                 if (c == '#') {
12619                         while ((c = pgetc()) != '\n' && c != PEOF)
12620                                 continue;
12621                         pungetc();
12622                 } else if (c == '\\') {
12623                         if (pgetc() != '\n') {
12624                                 pungetc();
12625                                 break; /* return readtoken1(...) */
12626                         }
12627                         nlprompt();
12628                 } else {
12629                         const char *p;
12630
12631                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12632                         if (c != PEOF) {
12633                                 if (c == '\n') {
12634                                         nlnoprompt();
12635                                 }
12636
12637                                 p = strchr(xxreadtoken_chars, c);
12638                                 if (p == NULL)
12639                                         break; /* return readtoken1(...) */
12640
12641                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12642                                         int cc = pgetc();
12643                                         if (cc == c) {    /* double occurrence? */
12644                                                 p += xxreadtoken_doubles + 1;
12645                                         } else {
12646                                                 pungetc();
12647 #if BASH_REDIR_OUTPUT
12648                                                 if (c == '&' && cc == '>') /* &> */
12649                                                         break; /* return readtoken1(...) */
12650 #endif
12651                                         }
12652                                 }
12653                         }
12654                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12655                         return lasttoken;
12656                 }
12657         } /* for (;;) */
12658
12659         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12660 }
12661 #else /* old xxreadtoken */
12662 #define RETURN(token)   return lasttoken = token
12663 static int
12664 xxreadtoken(void)
12665 {
12666         int c;
12667
12668         if (tokpushback) {
12669                 tokpushback = 0;
12670                 return lasttoken;
12671         }
12672         setprompt_if(needprompt, 2);
12673         for (;;) {      /* until token or start of word found */
12674                 c = pgetc();
12675                 switch (c) {
12676                 case ' ': case '\t':
12677                 IF_ASH_ALIAS(case PEOA:)
12678                         continue;
12679                 case '#':
12680                         while ((c = pgetc()) != '\n' && c != PEOF)
12681                                 continue;
12682                         pungetc();
12683                         continue;
12684                 case '\\':
12685                         if (pgetc() == '\n') {
12686                                 nlprompt();
12687                                 continue;
12688                         }
12689                         pungetc();
12690                         goto breakloop;
12691                 case '\n':
12692                         nlnoprompt();
12693                         RETURN(TNL);
12694                 case PEOF:
12695                         RETURN(TEOF);
12696                 case '&':
12697                         if (pgetc() == '&')
12698                                 RETURN(TAND);
12699                         pungetc();
12700                         RETURN(TBACKGND);
12701                 case '|':
12702                         if (pgetc() == '|')
12703                                 RETURN(TOR);
12704                         pungetc();
12705                         RETURN(TPIPE);
12706                 case ';':
12707                         if (pgetc() == ';')
12708                                 RETURN(TENDCASE);
12709                         pungetc();
12710                         RETURN(TSEMI);
12711                 case '(':
12712                         RETURN(TLP);
12713                 case ')':
12714                         RETURN(TRP);
12715                 default:
12716                         goto breakloop;
12717                 }
12718         }
12719  breakloop:
12720         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12721 #undef RETURN
12722 }
12723 #endif /* old xxreadtoken */
12724
12725 static int
12726 readtoken(void)
12727 {
12728         int t;
12729         int kwd = checkkwd;
12730 #if DEBUG
12731         smallint alreadyseen = tokpushback;
12732 #endif
12733
12734 #if ENABLE_ASH_ALIAS
12735  top:
12736 #endif
12737
12738         t = xxreadtoken();
12739
12740         /*
12741          * eat newlines
12742          */
12743         if (kwd & CHKNL) {
12744                 while (t == TNL) {
12745                         parseheredoc();
12746                         t = xxreadtoken();
12747                 }
12748         }
12749
12750         if (t != TWORD || quoteflag) {
12751                 goto out;
12752         }
12753
12754         /*
12755          * check for keywords
12756          */
12757         if (kwd & CHKKWD) {
12758                 const char *const *pp;
12759
12760                 pp = findkwd(wordtext);
12761                 if (pp) {
12762                         lasttoken = t = pp - tokname_array;
12763                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12764                         goto out;
12765                 }
12766         }
12767
12768         if (checkkwd & CHKALIAS) {
12769 #if ENABLE_ASH_ALIAS
12770                 struct alias *ap;
12771                 ap = lookupalias(wordtext, 1);
12772                 if (ap != NULL) {
12773                         if (*ap->val) {
12774                                 pushstring(ap->val, ap);
12775                         }
12776                         goto top;
12777                 }
12778 #endif
12779         }
12780  out:
12781         checkkwd = 0;
12782 #if DEBUG
12783         if (!alreadyseen)
12784                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12785         else
12786                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12787 #endif
12788         return t;
12789 }
12790
12791 static int
12792 peektoken(void)
12793 {
12794         int t;
12795
12796         t = readtoken();
12797         tokpushback = 1;
12798         return t;
12799 }
12800
12801 /*
12802  * Read and parse a command.  Returns NODE_EOF on end of file.
12803  * (NULL is a valid parse tree indicating a blank line.)
12804  */
12805 static union node *
12806 parsecmd(int interact)
12807 {
12808         tokpushback = 0;
12809         checkkwd = 0;
12810         heredoclist = 0;
12811         doprompt = interact;
12812         setprompt_if(doprompt, doprompt);
12813         needprompt = 0;
12814         return list(1);
12815 }
12816
12817 /*
12818  * Input any here documents.
12819  */
12820 static void
12821 parseheredoc(void)
12822 {
12823         struct heredoc *here;
12824         union node *n;
12825
12826         here = heredoclist;
12827         heredoclist = NULL;
12828
12829         while (here) {
12830                 setprompt_if(needprompt, 2);
12831                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12832                                 here->eofmark, here->striptabs);
12833                 n = stzalloc(sizeof(struct narg));
12834                 n->narg.type = NARG;
12835                 /*n->narg.next = NULL; - stzalloc did it */
12836                 n->narg.text = wordtext;
12837                 n->narg.backquote = backquotelist;
12838                 here->here->nhere.doc = n;
12839                 here = here->next;
12840         }
12841 }
12842
12843
12844 static const char *
12845 expandstr(const char *ps, int syntax_type)
12846 {
12847         union node n;
12848         int saveprompt;
12849
12850         /* XXX Fix (char *) cast. */
12851         setinputstring((char *)ps);
12852
12853         saveprompt = doprompt;
12854         doprompt = 0;
12855
12856         /* readtoken1() might die horribly.
12857          * Try a prompt with syntactically wrong command:
12858          * PS1='$(date "+%H:%M:%S) > '
12859          */
12860         {
12861                 volatile int saveint;
12862                 struct jmploc *volatile savehandler = exception_handler;
12863                 struct jmploc jmploc;
12864                 SAVE_INT(saveint);
12865                 if (setjmp(jmploc.loc) == 0) {
12866                         exception_handler = &jmploc;
12867                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12868                 }
12869                 exception_handler = savehandler;
12870                 RESTORE_INT(saveint);
12871         }
12872
12873         doprompt = saveprompt;
12874
12875         popfile();
12876
12877         n.narg.type = NARG;
12878         n.narg.next = NULL;
12879         n.narg.text = wordtext;
12880         n.narg.backquote = backquotelist;
12881
12882         expandarg(&n, NULL, EXP_QUOTED);
12883         return stackblock();
12884 }
12885
12886 static inline int
12887 parser_eof(void)
12888 {
12889         return tokpushback && lasttoken == TEOF;
12890 }
12891
12892 /*
12893  * Execute a command or commands contained in a string.
12894  */
12895 static int
12896 evalstring(char *s, int flags)
12897 {
12898         struct jmploc *volatile savehandler;
12899         struct jmploc jmploc;
12900         int ex;
12901
12902         union node *n;
12903         struct stackmark smark;
12904         int status;
12905
12906         s = sstrdup(s);
12907         setinputstring(s);
12908         setstackmark(&smark);
12909
12910         status = 0;
12911         /* On exception inside execution loop, we must popfile().
12912          * Try interactively:
12913          *      readonly a=a
12914          *      command eval "a=b"  # throws "is read only" error
12915          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12916          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12917          */
12918         savehandler = exception_handler;
12919         ex = setjmp(jmploc.loc);
12920         if (ex)
12921                 goto out;
12922         exception_handler = &jmploc;
12923
12924         while ((n = parsecmd(0)) != NODE_EOF) {
12925                 int i;
12926
12927                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12928                 if (n)
12929                         status = i;
12930                 popstackmark(&smark);
12931                 if (evalskip)
12932                         break;
12933         }
12934  out:
12935         popstackmark(&smark);
12936         popfile();
12937         stunalloc(s);
12938
12939         exception_handler = savehandler;
12940         if (ex)
12941                 longjmp(exception_handler->loc, ex);
12942
12943         return status;
12944 }
12945
12946 /*
12947  * The eval command.
12948  */
12949 static int FAST_FUNC
12950 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12951 {
12952         char *p;
12953         char *concat;
12954
12955         if (argv[1]) {
12956                 p = argv[1];
12957                 argv += 2;
12958                 if (argv[0]) {
12959                         STARTSTACKSTR(concat);
12960                         for (;;) {
12961                                 concat = stack_putstr(p, concat);
12962                                 p = *argv++;
12963                                 if (p == NULL)
12964                                         break;
12965                                 STPUTC(' ', concat);
12966                         }
12967                         STPUTC('\0', concat);
12968                         p = grabstackstr(concat);
12969                 }
12970                 return evalstring(p, flags & EV_TESTED);
12971         }
12972         return 0;
12973 }
12974
12975 /*
12976  * Read and execute commands.
12977  * "Top" is nonzero for the top level command loop;
12978  * it turns on prompting if the shell is interactive.
12979  */
12980 static int
12981 cmdloop(int top)
12982 {
12983         union node *n;
12984         struct stackmark smark;
12985         int inter;
12986         int status = 0;
12987         int numeof = 0;
12988
12989         TRACE(("cmdloop(%d) called\n", top));
12990         for (;;) {
12991                 int skip;
12992
12993                 setstackmark(&smark);
12994 #if JOBS
12995                 if (doing_jobctl)
12996                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12997 #endif
12998                 inter = 0;
12999                 if (iflag && top) {
13000                         inter++;
13001                         chkmail();
13002                 }
13003                 n = parsecmd(inter);
13004 #if DEBUG
13005                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13006                         showtree(n);
13007 #endif
13008                 if (n == NODE_EOF) {
13009                         if (!top || numeof >= 50)
13010                                 break;
13011                         if (!stoppedjobs()) {
13012                                 if (!Iflag)
13013                                         break;
13014                                 out2str("\nUse \"exit\" to leave shell.\n");
13015                         }
13016                         numeof++;
13017                 } else if (nflag == 0) {
13018                         int i;
13019
13020                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13021                         job_warning >>= 1;
13022                         numeof = 0;
13023                         i = evaltree(n, 0);
13024                         if (n)
13025                                 status = i;
13026                 }
13027                 popstackmark(&smark);
13028                 skip = evalskip;
13029
13030                 if (skip) {
13031                         evalskip &= ~SKIPFUNC;
13032                         break;
13033                 }
13034         }
13035         return status;
13036 }
13037
13038 /*
13039  * Take commands from a file.  To be compatible we should do a path
13040  * search for the file, which is necessary to find sub-commands.
13041  */
13042 static char *
13043 find_dot_file(char *name)
13044 {
13045         char *fullname;
13046         const char *path = pathval();
13047         struct stat statb;
13048
13049         /* don't try this for absolute or relative paths */
13050         if (strchr(name, '/'))
13051                 return name;
13052
13053         while ((fullname = path_advance(&path, name)) != NULL) {
13054                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13055                         /*
13056                          * Don't bother freeing here, since it will
13057                          * be freed by the caller.
13058                          */
13059                         return fullname;
13060                 }
13061                 if (fullname != name)
13062                         stunalloc(fullname);
13063         }
13064         /* not found in PATH */
13065
13066 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13067         return name;
13068 #else
13069         ash_msg_and_raise_error("%s: not found", name);
13070         /* NOTREACHED */
13071 #endif
13072 }
13073
13074 static int FAST_FUNC
13075 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13076 {
13077         /* "false; . empty_file; echo $?" should print 0, not 1: */
13078         int status = 0;
13079         char *fullname;
13080         char **argv;
13081         char *args_need_save;
13082         volatile struct shparam saveparam;
13083
13084 //???
13085 //      struct strlist *sp;
13086 //      for (sp = cmdenviron; sp; sp = sp->next)
13087 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13088
13089         nextopt(nullstr); /* handle possible "--" */
13090         argv = argptr;
13091
13092         if (!argv[0]) {
13093                 /* bash says: "bash: .: filename argument required" */
13094                 return 2; /* bash compat */
13095         }
13096
13097         /* This aborts if file isn't found, which is POSIXly correct.
13098          * bash returns exitcode 1 instead.
13099          */
13100         fullname = find_dot_file(argv[0]);
13101         argv++;
13102         args_need_save = argv[0];
13103         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13104                 int argc;
13105                 saveparam = shellparam;
13106                 shellparam.malloced = 0;
13107                 argc = 1;
13108                 while (argv[argc])
13109                         argc++;
13110                 shellparam.nparam = argc;
13111                 shellparam.p = argv;
13112         };
13113
13114         /* This aborts if file can't be opened, which is POSIXly correct.
13115          * bash returns exitcode 1 instead.
13116          */
13117         setinputfile(fullname, INPUT_PUSH_FILE);
13118         commandname = fullname;
13119         status = cmdloop(0);
13120         popfile();
13121
13122         if (args_need_save) {
13123                 freeparam(&shellparam);
13124                 shellparam = saveparam;
13125         };
13126
13127         return status;
13128 }
13129
13130 static int FAST_FUNC
13131 exitcmd(int argc UNUSED_PARAM, char **argv)
13132 {
13133         if (stoppedjobs())
13134                 return 0;
13135         if (argv[1])
13136                 exitstatus = number(argv[1]);
13137         raise_exception(EXEXIT);
13138         /* NOTREACHED */
13139 }
13140
13141 /*
13142  * Read a file containing shell functions.
13143  */
13144 static void
13145 readcmdfile(char *name)
13146 {
13147         setinputfile(name, INPUT_PUSH_FILE);
13148         cmdloop(0);
13149         popfile();
13150 }
13151
13152
13153 /* ============ find_command inplementation */
13154
13155 /*
13156  * Resolve a command name.  If you change this routine, you may have to
13157  * change the shellexec routine as well.
13158  */
13159 static void
13160 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13161 {
13162         struct tblentry *cmdp;
13163         int idx;
13164         int prev;
13165         char *fullname;
13166         struct stat statb;
13167         int e;
13168         int updatetbl;
13169         struct builtincmd *bcmd;
13170
13171         /* If name contains a slash, don't use PATH or hash table */
13172         if (strchr(name, '/') != NULL) {
13173                 entry->u.index = -1;
13174                 if (act & DO_ABS) {
13175                         while (stat(name, &statb) < 0) {
13176 #ifdef SYSV
13177                                 if (errno == EINTR)
13178                                         continue;
13179 #endif
13180                                 entry->cmdtype = CMDUNKNOWN;
13181                                 return;
13182                         }
13183                 }
13184                 entry->cmdtype = CMDNORMAL;
13185                 return;
13186         }
13187
13188 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13189
13190         updatetbl = (path == pathval());
13191         if (!updatetbl) {
13192                 act |= DO_ALTPATH;
13193                 if (strstr(path, "%builtin") != NULL)
13194                         act |= DO_ALTBLTIN;
13195         }
13196
13197         /* If name is in the table, check answer will be ok */
13198         cmdp = cmdlookup(name, 0);
13199         if (cmdp != NULL) {
13200                 int bit;
13201
13202                 switch (cmdp->cmdtype) {
13203                 default:
13204 #if DEBUG
13205                         abort();
13206 #endif
13207                 case CMDNORMAL:
13208                         bit = DO_ALTPATH;
13209                         break;
13210                 case CMDFUNCTION:
13211                         bit = DO_NOFUNC;
13212                         break;
13213                 case CMDBUILTIN:
13214                         bit = DO_ALTBLTIN;
13215                         break;
13216                 }
13217                 if (act & bit) {
13218                         updatetbl = 0;
13219                         cmdp = NULL;
13220                 } else if (cmdp->rehash == 0)
13221                         /* if not invalidated by cd, we're done */
13222                         goto success;
13223         }
13224
13225         /* If %builtin not in path, check for builtin next */
13226         bcmd = find_builtin(name);
13227         if (bcmd) {
13228                 if (IS_BUILTIN_REGULAR(bcmd))
13229                         goto builtin_success;
13230                 if (act & DO_ALTPATH) {
13231                         if (!(act & DO_ALTBLTIN))
13232                                 goto builtin_success;
13233                 } else if (builtinloc <= 0) {
13234                         goto builtin_success;
13235                 }
13236         }
13237
13238 #if ENABLE_FEATURE_SH_STANDALONE
13239         {
13240                 int applet_no = find_applet_by_name(name);
13241                 if (applet_no >= 0) {
13242                         entry->cmdtype = CMDNORMAL;
13243                         entry->u.index = -2 - applet_no;
13244                         return;
13245                 }
13246         }
13247 #endif
13248
13249         /* We have to search path. */
13250         prev = -1;              /* where to start */
13251         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13252                 if (cmdp->cmdtype == CMDBUILTIN)
13253                         prev = builtinloc;
13254                 else
13255                         prev = cmdp->param.index;
13256         }
13257
13258         e = ENOENT;
13259         idx = -1;
13260  loop:
13261         while ((fullname = path_advance(&path, name)) != NULL) {
13262                 stunalloc(fullname);
13263                 /* NB: code below will still use fullname
13264                  * despite it being "unallocated" */
13265                 idx++;
13266                 if (pathopt) {
13267                         if (prefix(pathopt, "builtin")) {
13268                                 if (bcmd)
13269                                         goto builtin_success;
13270                                 continue;
13271                         }
13272                         if ((act & DO_NOFUNC)
13273                          || !prefix(pathopt, "func")
13274                         ) {     /* ignore unimplemented options */
13275                                 continue;
13276                         }
13277                 }
13278                 /* if rehash, don't redo absolute path names */
13279                 if (fullname[0] == '/' && idx <= prev) {
13280                         if (idx < prev)
13281                                 continue;
13282                         TRACE(("searchexec \"%s\": no change\n", name));
13283                         goto success;
13284                 }
13285                 while (stat(fullname, &statb) < 0) {
13286 #ifdef SYSV
13287                         if (errno == EINTR)
13288                                 continue;
13289 #endif
13290                         if (errno != ENOENT && errno != ENOTDIR)
13291                                 e = errno;
13292                         goto loop;
13293                 }
13294                 e = EACCES;     /* if we fail, this will be the error */
13295                 if (!S_ISREG(statb.st_mode))
13296                         continue;
13297                 if (pathopt) {          /* this is a %func directory */
13298                         stalloc(strlen(fullname) + 1);
13299                         /* NB: stalloc will return space pointed by fullname
13300                          * (because we don't have any intervening allocations
13301                          * between stunalloc above and this stalloc) */
13302                         readcmdfile(fullname);
13303                         cmdp = cmdlookup(name, 0);
13304                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13305                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13306                         stunalloc(fullname);
13307                         goto success;
13308                 }
13309                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13310                 if (!updatetbl) {
13311                         entry->cmdtype = CMDNORMAL;
13312                         entry->u.index = idx;
13313                         return;
13314                 }
13315                 INT_OFF;
13316                 cmdp = cmdlookup(name, 1);
13317                 cmdp->cmdtype = CMDNORMAL;
13318                 cmdp->param.index = idx;
13319                 INT_ON;
13320                 goto success;
13321         }
13322
13323         /* We failed.  If there was an entry for this command, delete it */
13324         if (cmdp && updatetbl)
13325                 delete_cmd_entry();
13326         if (act & DO_ERR) {
13327 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13328                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13329                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13330                         char *argv[3];
13331                         argv[0] = (char*) "command_not_found_handle";
13332                         argv[1] = name;
13333                         argv[2] = NULL;
13334                         evalfun(hookp->param.func, 2, argv, 0);
13335                         entry->cmdtype = CMDUNKNOWN;
13336                         return;
13337                 }
13338 #endif
13339                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13340         }
13341         entry->cmdtype = CMDUNKNOWN;
13342         return;
13343
13344  builtin_success:
13345         if (!updatetbl) {
13346                 entry->cmdtype = CMDBUILTIN;
13347                 entry->u.cmd = bcmd;
13348                 return;
13349         }
13350         INT_OFF;
13351         cmdp = cmdlookup(name, 1);
13352         cmdp->cmdtype = CMDBUILTIN;
13353         cmdp->param.cmd = bcmd;
13354         INT_ON;
13355  success:
13356         cmdp->rehash = 0;
13357         entry->cmdtype = cmdp->cmdtype;
13358         entry->u = cmdp->param;
13359 }
13360
13361
13362 /*
13363  * The trap builtin.
13364  */
13365 static int FAST_FUNC
13366 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13367 {
13368         char *action;
13369         char **ap;
13370         int signo, exitcode;
13371
13372         nextopt(nullstr);
13373         ap = argptr;
13374         if (!*ap) {
13375                 for (signo = 0; signo < NSIG; signo++) {
13376                         char *tr = trap_ptr[signo];
13377                         if (tr) {
13378                                 /* note: bash adds "SIG", but only if invoked
13379                                  * as "bash". If called as "sh", or if set -o posix,
13380                                  * then it prints short signal names.
13381                                  * We are printing short names: */
13382                                 out1fmt("trap -- %s %s\n",
13383                                                 single_quote(tr),
13384                                                 get_signame(signo));
13385                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13386                  * In this case, we will exit very soon, no need to free(). */
13387                                 /* if (trap_ptr != trap && tp[0]) */
13388                                 /*      free(tr); */
13389                         }
13390                 }
13391                 /*
13392                 if (trap_ptr != trap) {
13393                         free(trap_ptr);
13394                         trap_ptr = trap;
13395                 }
13396                 */
13397                 return 0;
13398         }
13399
13400         /* Why the second check?
13401          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13402          * In this case, NUM is signal no, not an action.
13403          */
13404         action = NULL;
13405         if (ap[1] && !is_number(ap[0]))
13406                 action = *ap++;
13407
13408         exitcode = 0;
13409         while (*ap) {
13410                 signo = get_signum(*ap);
13411                 if (signo < 0) {
13412                         /* Mimic bash message exactly */
13413                         ash_msg("%s: invalid signal specification", *ap);
13414                         exitcode = 1;
13415                         goto next;
13416                 }
13417                 INT_OFF;
13418                 if (action) {
13419                         if (LONE_DASH(action))
13420                                 action = NULL;
13421                         else {
13422                                 if (action[0]) /* not NULL and not "" and not "-" */
13423                                         may_have_traps = 1;
13424                                 action = ckstrdup(action);
13425                         }
13426                 }
13427                 free(trap[signo]);
13428                 trap[signo] = action;
13429                 if (signo != 0)
13430                         setsignal(signo);
13431                 INT_ON;
13432  next:
13433                 ap++;
13434         }
13435         return exitcode;
13436 }
13437
13438
13439 /* ============ Builtins */
13440
13441 #if ENABLE_ASH_HELP
13442 static int FAST_FUNC
13443 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13444 {
13445         unsigned col;
13446         unsigned i;
13447
13448         out1fmt(
13449                 "Built-in commands:\n"
13450                 "------------------\n");
13451         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13452                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13453                                         builtintab[i].name + 1);
13454                 if (col > 60) {
13455                         out1fmt("\n");
13456                         col = 0;
13457                 }
13458         }
13459 # if ENABLE_FEATURE_SH_STANDALONE
13460         {
13461                 const char *a = applet_names;
13462                 while (*a) {
13463                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13464                         if (col > 60) {
13465                                 out1fmt("\n");
13466                                 col = 0;
13467                         }
13468                         while (*a++ != '\0')
13469                                 continue;
13470                 }
13471         }
13472 # endif
13473         newline_and_flush(stdout);
13474         return EXIT_SUCCESS;
13475 }
13476 #endif
13477
13478 #if MAX_HISTORY
13479 static int FAST_FUNC
13480 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13481 {
13482         show_history(line_input_state);
13483         return EXIT_SUCCESS;
13484 }
13485 #endif
13486
13487 /*
13488  * The export and readonly commands.
13489  */
13490 static int FAST_FUNC
13491 exportcmd(int argc UNUSED_PARAM, char **argv)
13492 {
13493         struct var *vp;
13494         char *name;
13495         const char *p;
13496         char **aptr;
13497         char opt;
13498         int flag;
13499         int flag_off;
13500
13501         /* "readonly" in bash accepts, but ignores -n.
13502          * We do the same: it saves a conditional in nextopt's param.
13503          */
13504         flag_off = 0;
13505         while ((opt = nextopt("np")) != '\0') {
13506                 if (opt == 'n')
13507                         flag_off = VEXPORT;
13508         }
13509         flag = VEXPORT;
13510         if (argv[0][0] == 'r') {
13511                 flag = VREADONLY;
13512                 flag_off = 0; /* readonly ignores -n */
13513         }
13514         flag_off = ~flag_off;
13515
13516         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13517         {
13518                 aptr = argptr;
13519                 name = *aptr;
13520                 if (name) {
13521                         do {
13522                                 p = strchr(name, '=');
13523                                 if (p != NULL) {
13524                                         p++;
13525                                 } else {
13526                                         vp = *findvar(hashvar(name), name);
13527                                         if (vp) {
13528                                                 vp->flags = ((vp->flags | flag) & flag_off);
13529                                                 continue;
13530                                         }
13531                                 }
13532                                 setvar(name, p, (flag & flag_off));
13533                         } while ((name = *++aptr) != NULL);
13534                         return 0;
13535                 }
13536         }
13537
13538         /* No arguments. Show the list of exported or readonly vars.
13539          * -n is ignored.
13540          */
13541         showvars(argv[0], flag, 0);
13542         return 0;
13543 }
13544
13545 /*
13546  * Delete a function if it exists.
13547  */
13548 static void
13549 unsetfunc(const char *name)
13550 {
13551         struct tblentry *cmdp;
13552
13553         cmdp = cmdlookup(name, 0);
13554         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13555                 delete_cmd_entry();
13556 }
13557
13558 /*
13559  * The unset builtin command.  We unset the function before we unset the
13560  * variable to allow a function to be unset when there is a readonly variable
13561  * with the same name.
13562  */
13563 static int FAST_FUNC
13564 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13565 {
13566         char **ap;
13567         int i;
13568         int flag = 0;
13569
13570         while ((i = nextopt("vf")) != 0) {
13571                 flag = i;
13572         }
13573
13574         for (ap = argptr; *ap; ap++) {
13575                 if (flag != 'f') {
13576                         unsetvar(*ap);
13577                         continue;
13578                 }
13579                 if (flag != 'v')
13580                         unsetfunc(*ap);
13581         }
13582         return 0;
13583 }
13584
13585 static const unsigned char timescmd_str[] ALIGN1 = {
13586         ' ',  offsetof(struct tms, tms_utime),
13587         '\n', offsetof(struct tms, tms_stime),
13588         ' ',  offsetof(struct tms, tms_cutime),
13589         '\n', offsetof(struct tms, tms_cstime),
13590         0
13591 };
13592 static int FAST_FUNC
13593 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13594 {
13595         unsigned clk_tck;
13596         const unsigned char *p;
13597         struct tms buf;
13598
13599         clk_tck = bb_clk_tck();
13600
13601         times(&buf);
13602         p = timescmd_str;
13603         do {
13604                 unsigned sec, frac;
13605                 unsigned long t;
13606                 t = *(clock_t *)(((char *) &buf) + p[1]);
13607                 sec = t / clk_tck;
13608                 frac = t % clk_tck;
13609                 out1fmt("%um%u.%03us%c",
13610                         sec / 60, sec % 60,
13611                         (frac * 1000) / clk_tck,
13612                         p[0]);
13613                 p += 2;
13614         } while (*p);
13615
13616         return 0;
13617 }
13618
13619 #if ENABLE_FEATURE_SH_MATH
13620 /*
13621  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13622  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13623  *
13624  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13625  */
13626 static int FAST_FUNC
13627 letcmd(int argc UNUSED_PARAM, char **argv)
13628 {
13629         arith_t i;
13630
13631         argv++;
13632         if (!*argv)
13633                 ash_msg_and_raise_error("expression expected");
13634         do {
13635                 i = ash_arith(*argv);
13636         } while (*++argv);
13637
13638         return !i;
13639 }
13640 #endif
13641
13642 /*
13643  * The read builtin. Options:
13644  *      -r              Do not interpret '\' specially
13645  *      -s              Turn off echo (tty only)
13646  *      -n NCHARS       Read NCHARS max
13647  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13648  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13649  *      -u FD           Read from given FD instead of fd 0
13650  *      -d DELIM        End on DELIM char, not newline
13651  * This uses unbuffered input, which may be avoidable in some cases.
13652  * TODO: bash also has:
13653  *      -a ARRAY        Read into array[0],[1],etc
13654  *      -e              Use line editing (tty only)
13655  */
13656 static int FAST_FUNC
13657 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13658 {
13659         char *opt_n = NULL;
13660         char *opt_p = NULL;
13661         char *opt_t = NULL;
13662         char *opt_u = NULL;
13663         char *opt_d = NULL; /* optimized out if !BASH */
13664         int read_flags = 0;
13665         const char *r;
13666         int i;
13667
13668         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13669                 switch (i) {
13670                 case 'p':
13671                         opt_p = optionarg;
13672                         break;
13673                 case 'n':
13674                         opt_n = optionarg;
13675                         break;
13676                 case 's':
13677                         read_flags |= BUILTIN_READ_SILENT;
13678                         break;
13679                 case 't':
13680                         opt_t = optionarg;
13681                         break;
13682                 case 'r':
13683                         read_flags |= BUILTIN_READ_RAW;
13684                         break;
13685                 case 'u':
13686                         opt_u = optionarg;
13687                         break;
13688 #if BASH_READ_D
13689                 case 'd':
13690                         opt_d = optionarg;
13691                         break;
13692 #endif
13693                 default:
13694                         break;
13695                 }
13696         }
13697
13698         /* "read -s" needs to save/restore termios, can't allow ^C
13699          * to jump out of it.
13700          */
13701  again:
13702         INT_OFF;
13703         r = shell_builtin_read(setvar0,
13704                 argptr,
13705                 bltinlookup("IFS"), /* can be NULL */
13706                 read_flags,
13707                 opt_n,
13708                 opt_p,
13709                 opt_t,
13710                 opt_u,
13711                 opt_d
13712         );
13713         INT_ON;
13714
13715         if ((uintptr_t)r == 1 && errno == EINTR) {
13716                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13717                  * Correct behavior is to not exit "read"
13718                  */
13719                 if (pending_sig == 0)
13720                         goto again;
13721         }
13722
13723         if ((uintptr_t)r > 1)
13724                 ash_msg_and_raise_error(r);
13725
13726         return (uintptr_t)r;
13727 }
13728
13729 static int FAST_FUNC
13730 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13731 {
13732         static const char permuser[3] ALIGN1 = "ogu";
13733
13734         mode_t mask;
13735         int symbolic_mode = 0;
13736
13737         while (nextopt("S") != '\0') {
13738                 symbolic_mode = 1;
13739         }
13740
13741         INT_OFF;
13742         mask = umask(0);
13743         umask(mask);
13744         INT_ON;
13745
13746         if (*argptr == NULL) {
13747                 if (symbolic_mode) {
13748                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13749                         char *p = buf;
13750                         int i;
13751
13752                         i = 2;
13753                         for (;;) {
13754                                 *p++ = ',';
13755                                 *p++ = permuser[i];
13756                                 *p++ = '=';
13757                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13758                                 if (!(mask & 0400)) *p++ = 'r';
13759                                 if (!(mask & 0200)) *p++ = 'w';
13760                                 if (!(mask & 0100)) *p++ = 'x';
13761                                 mask <<= 3;
13762                                 if (--i < 0)
13763                                         break;
13764                         }
13765                         *p = '\0';
13766                         puts(buf + 1);
13767                 } else {
13768                         out1fmt("%04o\n", mask);
13769                 }
13770         } else {
13771                 char *modestr = *argptr;
13772                 /* numeric umasks are taken as-is */
13773                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13774                 if (!isdigit(modestr[0]))
13775                         mask ^= 0777;
13776                 mask = bb_parse_mode(modestr, mask);
13777                 if ((unsigned)mask > 0777) {
13778                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13779                 }
13780                 if (!isdigit(modestr[0]))
13781                         mask ^= 0777;
13782                 umask(mask);
13783         }
13784         return 0;
13785 }
13786
13787 static int FAST_FUNC
13788 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13789 {
13790         return shell_builtin_ulimit(argv);
13791 }
13792
13793 /* ============ main() and helpers */
13794
13795 /*
13796  * Called to exit the shell.
13797  */
13798 static void
13799 exitshell(void)
13800 {
13801         struct jmploc loc;
13802         char *p;
13803         int status;
13804
13805 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13806         save_history(line_input_state);
13807 #endif
13808         status = exitstatus;
13809         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13810         if (setjmp(loc.loc)) {
13811                 if (exception_type == EXEXIT)
13812                         status = exitstatus;
13813                 goto out;
13814         }
13815         exception_handler = &loc;
13816         p = trap[0];
13817         if (p) {
13818                 trap[0] = NULL;
13819                 evalskip = 0;
13820                 evalstring(p, 0);
13821                 /*free(p); - we'll exit soon */
13822         }
13823  out:
13824         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13825          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13826          */
13827         setjobctl(0);
13828         flush_stdout_stderr();
13829         _exit(status);
13830         /* NOTREACHED */
13831 }
13832
13833 /* Don't inline: conserve stack of caller from having our locals too */
13834 static NOINLINE void
13835 init(void)
13836 {
13837         /* we will never free this */
13838         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13839         basepf.linno = 1;
13840
13841         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13842         setsignal(SIGCHLD);
13843
13844         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13845          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13846          */
13847         signal(SIGHUP, SIG_DFL);
13848
13849         {
13850                 char **envp;
13851                 const char *p;
13852
13853                 initvar();
13854                 for (envp = environ; envp && *envp; envp++) {
13855 /* Used to have
13856  *                      p = endofname(*envp);
13857  *                      if (p != *envp && *p == '=') {
13858  * here to weed out badly-named variables, but this breaks
13859  * scenarios where people do want them passed to children:
13860  * import os
13861  * os.environ["test-test"]="test"
13862  * if os.fork() == 0:
13863  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13864  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13865  */
13866                         if (strchr(*envp, '=')) {
13867                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13868                         }
13869                 }
13870
13871                 setvareq((char*)defoptindvar, VTEXTFIXED);
13872
13873                 setvar0("PPID", utoa(getppid()));
13874 #if BASH_SHLVL_VAR
13875                 p = lookupvar("SHLVL");
13876                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13877 #endif
13878 #if BASH_HOSTNAME_VAR
13879                 if (!lookupvar("HOSTNAME")) {
13880                         struct utsname uts;
13881                         uname(&uts);
13882                         setvar0("HOSTNAME", uts.nodename);
13883                 }
13884 #endif
13885                 p = lookupvar("PWD");
13886                 if (p) {
13887                         struct stat st1, st2;
13888                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13889                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13890                         ) {
13891                                 p = NULL;
13892                         }
13893                 }
13894                 setpwd(p, 0);
13895         }
13896 }
13897
13898
13899 //usage:#define ash_trivial_usage
13900 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13901 //usage:#define ash_full_usage "\n\n"
13902 //usage:        "Unix shell interpreter"
13903
13904 /*
13905  * Process the shell command line arguments.
13906  */
13907 static int
13908 procargs(char **argv)
13909 {
13910         int i;
13911         const char *xminusc;
13912         char **xargv;
13913         int login_sh;
13914
13915         xargv = argv;
13916         login_sh = xargv[0] && xargv[0][0] == '-';
13917         arg0 = xargv[0];
13918         /* if (xargv[0]) - mmm, this is always true! */
13919                 xargv++;
13920         for (i = 0; i < NOPTS; i++)
13921                 optlist[i] = 2;
13922         argptr = xargv;
13923         if (options(/*cmdline:*/ 1, &login_sh)) {
13924                 /* it already printed err message */
13925                 raise_exception(EXERROR);
13926         }
13927         xargv = argptr;
13928         xminusc = minusc;
13929         if (*xargv == NULL) {
13930                 if (xminusc)
13931                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13932                 sflag = 1;
13933         }
13934         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13935                 iflag = 1;
13936         if (mflag == 2)
13937                 mflag = iflag;
13938         for (i = 0; i < NOPTS; i++)
13939                 if (optlist[i] == 2)
13940                         optlist[i] = 0;
13941 #if DEBUG == 2
13942         debug = 1;
13943 #endif
13944         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13945         if (xminusc) {
13946                 minusc = *xargv++;
13947                 if (*xargv)
13948                         goto setarg0;
13949         } else if (!sflag) {
13950                 setinputfile(*xargv, 0);
13951  setarg0:
13952                 arg0 = *xargv++;
13953                 commandname = arg0;
13954         }
13955
13956         shellparam.p = xargv;
13957 #if ENABLE_ASH_GETOPTS
13958         shellparam.optind = 1;
13959         shellparam.optoff = -1;
13960 #endif
13961         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13962         while (*xargv) {
13963                 shellparam.nparam++;
13964                 xargv++;
13965         }
13966         optschanged();
13967
13968         return login_sh;
13969 }
13970
13971 /*
13972  * Read /etc/profile, ~/.profile, $ENV.
13973  */
13974 static void
13975 read_profile(const char *name)
13976 {
13977         name = expandstr(name, DQSYNTAX);
13978         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13979                 return;
13980         cmdloop(0);
13981         popfile();
13982 }
13983
13984 /*
13985  * This routine is called when an error or an interrupt occurs in an
13986  * interactive shell and control is returned to the main command loop.
13987  * (In dash, this function is auto-generated by build machinery).
13988  */
13989 static void
13990 reset(void)
13991 {
13992         /* from eval.c: */
13993         evalskip = 0;
13994         loopnest = 0;
13995
13996         /* from expand.c: */
13997         ifsfree();
13998
13999         /* from input.c: */
14000         g_parsefile->left_in_buffer = 0;
14001         g_parsefile->left_in_line = 0;      /* clear input buffer */
14002         popallfiles();
14003
14004         /* from redir.c: */
14005         unwindredir(NULL);
14006
14007         /* from var.c: */
14008         unwindlocalvars(NULL);
14009 }
14010
14011 #if PROFILE
14012 static short profile_buf[16384];
14013 extern int etext();
14014 #endif
14015
14016 /*
14017  * Main routine.  We initialize things, parse the arguments, execute
14018  * profiles if we're a login shell, and then call cmdloop to execute
14019  * commands.  The setjmp call sets up the location to jump to when an
14020  * exception occurs.  When an exception occurs the variable "state"
14021  * is used to figure out how far we had gotten.
14022  */
14023 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14024 int ash_main(int argc UNUSED_PARAM, char **argv)
14025 {
14026         volatile smallint state;
14027         struct jmploc jmploc;
14028         struct stackmark smark;
14029         int login_sh;
14030
14031         /* Initialize global data */
14032         INIT_G_misc();
14033         INIT_G_memstack();
14034         INIT_G_var();
14035 #if ENABLE_ASH_ALIAS
14036         INIT_G_alias();
14037 #endif
14038         INIT_G_cmdtable();
14039
14040 #if PROFILE
14041         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14042 #endif
14043
14044 #if ENABLE_FEATURE_EDITING
14045         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14046 #endif
14047         state = 0;
14048         if (setjmp(jmploc.loc)) {
14049                 smallint e;
14050                 smallint s;
14051
14052                 reset();
14053
14054                 e = exception_type;
14055                 s = state;
14056                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14057                         exitshell();
14058                 }
14059                 if (e == EXINT) {
14060                         newline_and_flush(stderr);
14061                 }
14062
14063                 popstackmark(&smark);
14064                 FORCE_INT_ON; /* enable interrupts */
14065                 if (s == 1)
14066                         goto state1;
14067                 if (s == 2)
14068                         goto state2;
14069                 if (s == 3)
14070                         goto state3;
14071                 goto state4;
14072         }
14073         exception_handler = &jmploc;
14074         rootpid = getpid();
14075
14076         init();
14077         setstackmark(&smark);
14078         login_sh = procargs(argv);
14079 #if DEBUG
14080         TRACE(("Shell args: "));
14081         trace_puts_args(argv);
14082 #endif
14083
14084         if (login_sh) {
14085                 const char *hp;
14086
14087                 state = 1;
14088                 read_profile("/etc/profile");
14089  state1:
14090                 state = 2;
14091                 hp = lookupvar("HOME");
14092                 if (hp)
14093                         read_profile("$HOME/.profile");
14094         }
14095  state2:
14096         state = 3;
14097         if (
14098 #ifndef linux
14099          getuid() == geteuid() && getgid() == getegid() &&
14100 #endif
14101          iflag
14102         ) {
14103                 const char *shinit = lookupvar("ENV");
14104                 if (shinit != NULL && *shinit != '\0')
14105                         read_profile(shinit);
14106         }
14107         popstackmark(&smark);
14108  state3:
14109         state = 4;
14110         if (minusc) {
14111                 /* evalstring pushes parsefile stack.
14112                  * Ensure we don't falsely claim that 0 (stdin)
14113                  * is one of stacked source fds.
14114                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14115                 // if (!sflag) g_parsefile->pf_fd = -1;
14116                 // ^^ not necessary since now we special-case fd 0
14117                 // in save_fd_on_redirect()
14118                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14119         }
14120
14121         if (sflag || minusc == NULL) {
14122 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14123                 if (iflag) {
14124                         const char *hp = lookupvar("HISTFILE");
14125                         if (!hp) {
14126                                 hp = lookupvar("HOME");
14127                                 if (hp) {
14128                                         INT_OFF;
14129                                         hp = concat_path_file(hp, ".ash_history");
14130                                         setvar0("HISTFILE", hp);
14131                                         free((char*)hp);
14132                                         INT_ON;
14133                                         hp = lookupvar("HISTFILE");
14134                                 }
14135                         }
14136                         if (hp)
14137                                 line_input_state->hist_file = hp;
14138 # if ENABLE_FEATURE_SH_HISTFILESIZE
14139                         hp = lookupvar("HISTFILESIZE");
14140                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14141 # endif
14142                 }
14143 #endif
14144  state4: /* XXX ??? - why isn't this before the "if" statement */
14145                 cmdloop(1);
14146         }
14147 #if PROFILE
14148         monitor(0);
14149 #endif
14150 #ifdef GPROF
14151         {
14152                 extern void _mcleanup(void);
14153                 _mcleanup();
14154         }
14155 #endif
14156         TRACE(("End of main reached\n"));
14157         exitshell();
14158         /* NOTREACHED */
14159 }
14160
14161
14162 /*-
14163  * Copyright (c) 1989, 1991, 1993, 1994
14164  *      The Regents of the University of California.  All rights reserved.
14165  *
14166  * This code is derived from software contributed to Berkeley by
14167  * Kenneth Almquist.
14168  *
14169  * Redistribution and use in source and binary forms, with or without
14170  * modification, are permitted provided that the following conditions
14171  * are met:
14172  * 1. Redistributions of source code must retain the above copyright
14173  *    notice, this list of conditions and the following disclaimer.
14174  * 2. Redistributions in binary form must reproduce the above copyright
14175  *    notice, this list of conditions and the following disclaimer in the
14176  *    documentation and/or other materials provided with the distribution.
14177  * 3. Neither the name of the University nor the names of its contributors
14178  *    may be used to endorse or promote products derived from this software
14179  *    without specific prior written permission.
14180  *
14181  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14182  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14183  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14184  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14185  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14186  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14187  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14188  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14189  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14190  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14191  * SUCH DAMAGE.
14192  */