ash: make ${v:N:M} more robust for very large M by clamping to MIN/MAX_INT
[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_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
192 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
193 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
194
195 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
196 /* Bionic at least up to version 24 has no glob() */
197 # undef  ENABLE_ASH_INTERNAL_GLOB
198 # define ENABLE_ASH_INTERNAL_GLOB 1
199 #endif
200
201 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
202 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
203 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
204 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
205 # error glob() should unbackslash them and match. uClibc does not unbackslash,
206 # error fails to match dirname, subsequently not expanding <pattern> in it.
207 // Testcase:
208 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
209 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
210 #endif
211
212 #if !ENABLE_ASH_INTERNAL_GLOB
213 # include <glob.h>
214 #endif
215
216 #include "unicode.h"
217 #include "shell_common.h"
218 #if ENABLE_FEATURE_SH_MATH
219 # include "math.h"
220 #else
221 typedef long arith_t;
222 # define ARITH_FMT "%ld"
223 #endif
224 #if ENABLE_ASH_RANDOM_SUPPORT
225 # include "random.h"
226 #else
227 # define CLEAR_RANDOM_T(rnd) ((void)0)
228 #endif
229
230 #include "NUM_APPLETS.h"
231 #if NUM_APPLETS == 1
232 /* STANDALONE does not make sense, and won't compile */
233 # undef CONFIG_FEATURE_SH_STANDALONE
234 # undef ENABLE_FEATURE_SH_STANDALONE
235 # undef IF_FEATURE_SH_STANDALONE
236 # undef IF_NOT_FEATURE_SH_STANDALONE
237 # define ENABLE_FEATURE_SH_STANDALONE 0
238 # define IF_FEATURE_SH_STANDALONE(...)
239 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
240 #endif
241
242 #ifndef PIPE_BUF
243 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
244 #endif
245
246 #if !BB_MMU
247 # error "Do not even bother, ash will not run on NOMMU machine"
248 #endif
249
250
251 /* ============ Hash table sizes. Configurable. */
252
253 #define VTABSIZE 39
254 #define ATABSIZE 39
255 #define CMDTABLESIZE 31         /* should be prime */
256
257
258 /* ============ Shell options */
259
260 static const char *const optletters_optnames[] = {
261         "e"   "errexit",
262         "f"   "noglob",
263         "I"   "ignoreeof",
264         "i"   "interactive",
265         "m"   "monitor",
266         "n"   "noexec",
267         "s"   "stdin",
268         "x"   "xtrace",
269         "v"   "verbose",
270         "C"   "noclobber",
271         "a"   "allexport",
272         "b"   "notify",
273         "u"   "nounset",
274         "\0"  "vi"
275 #if BASH_PIPEFAIL
276         ,"\0"  "pipefail"
277 #endif
278 #if DEBUG
279         ,"\0"  "nolog"
280         ,"\0"  "debug"
281 #endif
282 };
283
284 #define optletters(n)  optletters_optnames[n][0]
285 #define optnames(n)   (optletters_optnames[n] + 1)
286
287 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
288
289
290 /* ============ Misc data */
291
292 #define msg_illnum "Illegal number: %s"
293
294 /*
295  * We enclose jmp_buf in a structure so that we can declare pointers to
296  * jump locations.  The global variable handler contains the location to
297  * jump to when an exception occurs, and the global variable exception_type
298  * contains a code identifying the exception.  To implement nested
299  * exception handlers, the user should save the value of handler on entry
300  * to an inner scope, set handler to point to a jmploc structure for the
301  * inner scope, and restore handler on exit from the scope.
302  */
303 struct jmploc {
304         jmp_buf loc;
305 };
306
307 struct globals_misc {
308         uint8_t exitstatus;     /* exit status of last command */
309         uint8_t back_exitstatus;/* exit status of backquoted command */
310         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
311         int rootpid;            /* pid of main shell */
312         /* shell level: 0 for the main shell, 1 for its children, and so on */
313         int shlvl;
314 #define rootshell (!shlvl)
315         char *minusc;  /* argument to -c option */
316
317         char *curdir; // = nullstr;     /* current working directory */
318         char *physdir; // = nullstr;    /* physical working directory */
319
320         char *arg0; /* value of $0 */
321
322         struct jmploc *exception_handler;
323
324         volatile int suppress_int; /* counter */
325         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
326         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
327         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
328         smallint exception_type; /* kind of exception (0..5) */
329         /* exceptions */
330 #define EXINT 0         /* SIGINT received */
331 #define EXERROR 1       /* a generic error */
332 #define EXEXIT 4        /* exit the shell */
333
334         char nullstr[1];        /* zero length string */
335
336         char optlist[NOPTS];
337 #define eflag optlist[0]
338 #define fflag optlist[1]
339 #define Iflag optlist[2]
340 #define iflag optlist[3]
341 #define mflag optlist[4]
342 #define nflag optlist[5]
343 #define sflag optlist[6]
344 #define xflag optlist[7]
345 #define vflag optlist[8]
346 #define Cflag optlist[9]
347 #define aflag optlist[10]
348 #define bflag optlist[11]
349 #define uflag optlist[12]
350 #define viflag optlist[13]
351 #if BASH_PIPEFAIL
352 # define pipefail optlist[14]
353 #else
354 # define pipefail 0
355 #endif
356 #if DEBUG
357 # define nolog optlist[14 + BASH_PIPEFAIL]
358 # define debug optlist[15 + BASH_PIPEFAIL]
359 #endif
360
361         /* trap handler commands */
362         /*
363          * Sigmode records the current value of the signal handlers for the various
364          * modes.  A value of zero means that the current handler is not known.
365          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
366          */
367         char sigmode[NSIG - 1];
368 #define S_DFL      1            /* default signal handling (SIG_DFL) */
369 #define S_CATCH    2            /* signal is caught */
370 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
371 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
372
373         /* indicates specified signal received */
374         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
375         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
376         char *trap[NSIG];
377         char **trap_ptr;        /* used only by "trap hack" */
378
379         /* Rarely referenced stuff */
380 #if ENABLE_ASH_RANDOM_SUPPORT
381         random_t random_gen;
382 #endif
383         pid_t backgndpid;        /* pid of last background process */
384 };
385 extern struct globals_misc *const ash_ptr_to_globals_misc;
386 #define G_misc (*ash_ptr_to_globals_misc)
387 #define exitstatus        (G_misc.exitstatus )
388 #define back_exitstatus   (G_misc.back_exitstatus )
389 #define job_warning       (G_misc.job_warning)
390 #define rootpid     (G_misc.rootpid    )
391 #define shlvl       (G_misc.shlvl      )
392 #define minusc      (G_misc.minusc     )
393 #define curdir      (G_misc.curdir     )
394 #define physdir     (G_misc.physdir    )
395 #define arg0        (G_misc.arg0       )
396 #define exception_handler (G_misc.exception_handler)
397 #define exception_type    (G_misc.exception_type   )
398 #define suppress_int      (G_misc.suppress_int     )
399 #define pending_int       (G_misc.pending_int      )
400 #define got_sigchld       (G_misc.got_sigchld      )
401 #define pending_sig       (G_misc.pending_sig      )
402 #define nullstr     (G_misc.nullstr    )
403 #define optlist     (G_misc.optlist    )
404 #define sigmode     (G_misc.sigmode    )
405 #define gotsig      (G_misc.gotsig     )
406 #define may_have_traps    (G_misc.may_have_traps   )
407 #define trap        (G_misc.trap       )
408 #define trap_ptr    (G_misc.trap_ptr   )
409 #define random_gen  (G_misc.random_gen )
410 #define backgndpid  (G_misc.backgndpid )
411 #define INIT_G_misc() do { \
412         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
413         barrier(); \
414         curdir = nullstr; \
415         physdir = nullstr; \
416         trap_ptr = trap; \
417 } while (0)
418
419
420 /* ============ DEBUG */
421 #if DEBUG
422 static void trace_printf(const char *fmt, ...);
423 static void trace_vprintf(const char *fmt, va_list va);
424 # define TRACE(param)    trace_printf param
425 # define TRACEV(param)   trace_vprintf param
426 # define close(fd) do { \
427         int dfd = (fd); \
428         if (close(dfd) < 0) \
429                 bb_error_msg("bug on %d: closing %d(0x%x)", \
430                         __LINE__, dfd, dfd); \
431 } while (0)
432 #else
433 # define TRACE(param)
434 # define TRACEV(param)
435 #endif
436
437
438 /* ============ Utility functions */
439 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
440 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
441
442 static int
443 isdigit_str9(const char *str)
444 {
445         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
446         while (--maxlen && isdigit(*str))
447                 str++;
448         return (*str == '\0');
449 }
450
451 static const char *
452 var_end(const char *var)
453 {
454         while (*var)
455                 if (*var++ == '=')
456                         break;
457         return var;
458 }
459
460
461 /* ============ Interrupts / exceptions */
462
463 static void exitshell(void) NORETURN;
464
465 /*
466  * These macros allow the user to suspend the handling of interrupt signals
467  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
468  * much more efficient and portable.  (But hacking the kernel is so much
469  * more fun than worrying about efficiency and portability. :-))
470  */
471 #if DEBUG_INTONOFF
472 # define INT_OFF do { \
473         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
474         suppress_int++; \
475         barrier(); \
476 } while (0)
477 #else
478 # define INT_OFF do { \
479         suppress_int++; \
480         barrier(); \
481 } while (0)
482 #endif
483
484 /*
485  * Called to raise an exception.  Since C doesn't include exceptions, we
486  * just do a longjmp to the exception handler.  The type of exception is
487  * stored in the global variable "exception_type".
488  */
489 static void raise_exception(int) NORETURN;
490 static void
491 raise_exception(int e)
492 {
493 #if DEBUG
494         if (exception_handler == NULL)
495                 abort();
496 #endif
497         INT_OFF;
498         exception_type = e;
499         longjmp(exception_handler->loc, 1);
500 }
501 #if DEBUG
502 #define raise_exception(e) do { \
503         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
504         raise_exception(e); \
505 } while (0)
506 #endif
507
508 /*
509  * Called when a SIGINT is received.  (If the user specifies
510  * that SIGINT is to be trapped or ignored using the trap builtin, then
511  * this routine is not called.)  Suppressint is nonzero when interrupts
512  * are held using the INT_OFF macro.  (The test for iflag is just
513  * defensive programming.)
514  */
515 static void raise_interrupt(void) NORETURN;
516 static void
517 raise_interrupt(void)
518 {
519         pending_int = 0;
520         /* Signal is not automatically unmasked after it is raised,
521          * do it ourself - unmask all signals */
522         sigprocmask_allsigs(SIG_UNBLOCK);
523         /* pending_sig = 0; - now done in signal_handler() */
524
525         if (!(rootshell && iflag)) {
526                 /* Kill ourself with SIGINT */
527                 signal(SIGINT, SIG_DFL);
528                 raise(SIGINT);
529         }
530         /* bash: ^C even on empty command line sets $? */
531         exitstatus = SIGINT + 128;
532         raise_exception(EXINT);
533         /* NOTREACHED */
534 }
535 #if DEBUG
536 #define raise_interrupt() do { \
537         TRACE(("raising interrupt on line %d\n", __LINE__)); \
538         raise_interrupt(); \
539 } while (0)
540 #endif
541
542 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
543 int_on(void)
544 {
545         barrier();
546         if (--suppress_int == 0 && pending_int) {
547                 raise_interrupt();
548         }
549 }
550 #if DEBUG_INTONOFF
551 # define INT_ON do { \
552         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
553         int_on(); \
554 } while (0)
555 #else
556 # define INT_ON int_on()
557 #endif
558 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
559 force_int_on(void)
560 {
561         barrier();
562         suppress_int = 0;
563         if (pending_int)
564                 raise_interrupt();
565 }
566 #define FORCE_INT_ON force_int_on()
567
568 #define SAVE_INT(v) ((v) = suppress_int)
569
570 #define RESTORE_INT(v) do { \
571         barrier(); \
572         suppress_int = (v); \
573         if (suppress_int == 0 && pending_int) \
574                 raise_interrupt(); \
575 } while (0)
576
577
578 /* ============ Stdout/stderr output */
579
580 static void
581 outstr(const char *p, FILE *file)
582 {
583         INT_OFF;
584         fputs(p, file);
585         INT_ON;
586 }
587
588 static void
589 flush_stdout_stderr(void)
590 {
591         INT_OFF;
592         fflush_all();
593         INT_ON;
594 }
595
596 /* Was called outcslow(c,FILE*), but c was always '\n' */
597 static void
598 newline_and_flush(FILE *dest)
599 {
600         INT_OFF;
601         putc('\n', dest);
602         fflush(dest);
603         INT_ON;
604 }
605
606 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
607 static int
608 out1fmt(const char *fmt, ...)
609 {
610         va_list ap;
611         int r;
612
613         INT_OFF;
614         va_start(ap, fmt);
615         r = vprintf(fmt, ap);
616         va_end(ap);
617         INT_ON;
618         return r;
619 }
620
621 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
622 static int
623 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
624 {
625         va_list ap;
626         int ret;
627
628         INT_OFF;
629         va_start(ap, fmt);
630         ret = vsnprintf(outbuf, length, fmt, ap);
631         va_end(ap);
632         INT_ON;
633         return ret;
634 }
635
636 static void
637 out1str(const char *p)
638 {
639         outstr(p, stdout);
640 }
641
642 static void
643 out2str(const char *p)
644 {
645         outstr(p, stderr);
646         flush_stdout_stderr();
647 }
648
649
650 /* ============ Parser structures */
651
652 /* control characters in argument strings */
653 #define CTL_FIRST CTLESC
654 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
655 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
656 #define CTLENDVAR    ((unsigned char)'\203')
657 #define CTLBACKQ     ((unsigned char)'\204')
658 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
659 #define CTLENDARI    ((unsigned char)'\207')
660 #define CTLQUOTEMARK ((unsigned char)'\210')
661 #define CTL_LAST CTLQUOTEMARK
662
663 /* variable substitution byte (follows CTLVAR) */
664 #define VSTYPE  0x0f            /* type of variable substitution */
665 #define VSNUL   0x10            /* colon--treat the empty string as unset */
666
667 /* values of VSTYPE field */
668 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
669 #define VSMINUS         0x2     /* ${var-text} */
670 #define VSPLUS          0x3     /* ${var+text} */
671 #define VSQUESTION      0x4     /* ${var?message} */
672 #define VSASSIGN        0x5     /* ${var=text} */
673 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
674 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
675 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
676 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
677 #define VSLENGTH        0xa     /* ${#var} */
678 #if BASH_SUBSTR
679 #define VSSUBSTR        0xc     /* ${var:position:length} */
680 #endif
681 #if BASH_PATTERN_SUBST
682 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
683 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
684 #endif
685
686 static const char dolatstr[] ALIGN1 = {
687         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
688 };
689 #define DOLATSTRLEN 6
690
691 #define NCMD      0
692 #define NPIPE     1
693 #define NREDIR    2
694 #define NBACKGND  3
695 #define NSUBSHELL 4
696 #define NAND      5
697 #define NOR       6
698 #define NSEMI     7
699 #define NIF       8
700 #define NWHILE    9
701 #define NUNTIL   10
702 #define NFOR     11
703 #define NCASE    12
704 #define NCLIST   13
705 #define NDEFUN   14
706 #define NARG     15
707 #define NTO      16
708 #if BASH_REDIR_OUTPUT
709 #define NTO2     17
710 #endif
711 #define NCLOBBER 18
712 #define NFROM    19
713 #define NFROMTO  20
714 #define NAPPEND  21
715 #define NTOFD    22
716 #define NFROMFD  23
717 #define NHERE    24
718 #define NXHERE   25
719 #define NNOT     26
720 #define N_NUMBER 27
721
722 union node;
723
724 struct ncmd {
725         smallint type; /* Nxxxx */
726         union node *assign;
727         union node *args;
728         union node *redirect;
729 };
730
731 struct npipe {
732         smallint type;
733         smallint pipe_backgnd;
734         struct nodelist *cmdlist;
735 };
736
737 struct nredir {
738         smallint type;
739         union node *n;
740         union node *redirect;
741 };
742
743 struct nbinary {
744         smallint type;
745         union node *ch1;
746         union node *ch2;
747 };
748
749 struct nif {
750         smallint type;
751         union node *test;
752         union node *ifpart;
753         union node *elsepart;
754 };
755
756 struct nfor {
757         smallint type;
758         union node *args;
759         union node *body;
760         char *var;
761 };
762
763 struct ncase {
764         smallint type;
765         union node *expr;
766         union node *cases;
767 };
768
769 struct nclist {
770         smallint type;
771         union node *next;
772         union node *pattern;
773         union node *body;
774 };
775
776 struct narg {
777         smallint type;
778         union node *next;
779         char *text;
780         struct nodelist *backquote;
781 };
782
783 /* nfile and ndup layout must match!
784  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
785  * that it is actually NTO2 (>&file), and change its type.
786  */
787 struct nfile {
788         smallint type;
789         union node *next;
790         int fd;
791         int _unused_dupfd;
792         union node *fname;
793         char *expfname;
794 };
795
796 struct ndup {
797         smallint type;
798         union node *next;
799         int fd;
800         int dupfd;
801         union node *vname;
802         char *_unused_expfname;
803 };
804
805 struct nhere {
806         smallint type;
807         union node *next;
808         int fd;
809         union node *doc;
810 };
811
812 struct nnot {
813         smallint type;
814         union node *com;
815 };
816
817 union node {
818         smallint type;
819         struct ncmd ncmd;
820         struct npipe npipe;
821         struct nredir nredir;
822         struct nbinary nbinary;
823         struct nif nif;
824         struct nfor nfor;
825         struct ncase ncase;
826         struct nclist nclist;
827         struct narg narg;
828         struct nfile nfile;
829         struct ndup ndup;
830         struct nhere nhere;
831         struct nnot nnot;
832 };
833
834 /*
835  * NODE_EOF is returned by parsecmd when it encounters an end of file.
836  * It must be distinct from NULL.
837  */
838 #define NODE_EOF ((union node *) -1L)
839
840 struct nodelist {
841         struct nodelist *next;
842         union node *n;
843 };
844
845 struct funcnode {
846         int count;
847         union node n;
848 };
849
850 /*
851  * Free a parse tree.
852  */
853 static void
854 freefunc(struct funcnode *f)
855 {
856         if (f && --f->count < 0)
857                 free(f);
858 }
859
860
861 /* ============ Debugging output */
862
863 #if DEBUG
864
865 static FILE *tracefile;
866
867 static void
868 trace_printf(const char *fmt, ...)
869 {
870         va_list va;
871
872         if (debug != 1)
873                 return;
874         if (DEBUG_TIME)
875                 fprintf(tracefile, "%u ", (int) time(NULL));
876         if (DEBUG_PID)
877                 fprintf(tracefile, "[%u] ", (int) getpid());
878         if (DEBUG_SIG)
879                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
880         va_start(va, fmt);
881         vfprintf(tracefile, fmt, va);
882         va_end(va);
883 }
884
885 static void
886 trace_vprintf(const char *fmt, va_list va)
887 {
888         if (debug != 1)
889                 return;
890         vfprintf(tracefile, fmt, va);
891         fprintf(tracefile, "\n");
892 }
893
894 static void
895 trace_puts(const char *s)
896 {
897         if (debug != 1)
898                 return;
899         fputs(s, tracefile);
900 }
901
902 static void
903 trace_puts_quoted(char *s)
904 {
905         char *p;
906         char c;
907
908         if (debug != 1)
909                 return;
910         putc('"', tracefile);
911         for (p = s; *p; p++) {
912                 switch ((unsigned char)*p) {
913                 case '\n': c = 'n'; goto backslash;
914                 case '\t': c = 't'; goto backslash;
915                 case '\r': c = 'r'; goto backslash;
916                 case '\"': c = '\"'; goto backslash;
917                 case '\\': c = '\\'; goto backslash;
918                 case CTLESC: c = 'e'; goto backslash;
919                 case CTLVAR: c = 'v'; goto backslash;
920                 case CTLBACKQ: c = 'q'; goto backslash;
921  backslash:
922                         putc('\\', tracefile);
923                         putc(c, tracefile);
924                         break;
925                 default:
926                         if (*p >= ' ' && *p <= '~')
927                                 putc(*p, tracefile);
928                         else {
929                                 putc('\\', tracefile);
930                                 putc((*p >> 6) & 03, tracefile);
931                                 putc((*p >> 3) & 07, tracefile);
932                                 putc(*p & 07, tracefile);
933                         }
934                         break;
935                 }
936         }
937         putc('"', tracefile);
938 }
939
940 static void
941 trace_puts_args(char **ap)
942 {
943         if (debug != 1)
944                 return;
945         if (!*ap)
946                 return;
947         while (1) {
948                 trace_puts_quoted(*ap);
949                 if (!*++ap) {
950                         putc('\n', tracefile);
951                         break;
952                 }
953                 putc(' ', tracefile);
954         }
955 }
956
957 static void
958 opentrace(void)
959 {
960         char s[100];
961 #ifdef O_APPEND
962         int flags;
963 #endif
964
965         if (debug != 1) {
966                 if (tracefile)
967                         fflush(tracefile);
968                 /* leave open because libedit might be using it */
969                 return;
970         }
971         strcpy(s, "./trace");
972         if (tracefile) {
973                 if (!freopen(s, "a", tracefile)) {
974                         fprintf(stderr, "Can't re-open %s\n", s);
975                         debug = 0;
976                         return;
977                 }
978         } else {
979                 tracefile = fopen(s, "a");
980                 if (tracefile == NULL) {
981                         fprintf(stderr, "Can't open %s\n", s);
982                         debug = 0;
983                         return;
984                 }
985         }
986 #ifdef O_APPEND
987         flags = fcntl(fileno(tracefile), F_GETFL);
988         if (flags >= 0)
989                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
990 #endif
991         setlinebuf(tracefile);
992         fputs("\nTracing started.\n", tracefile);
993 }
994
995 static void
996 indent(int amount, char *pfx, FILE *fp)
997 {
998         int i;
999
1000         for (i = 0; i < amount; i++) {
1001                 if (pfx && i == amount - 1)
1002                         fputs(pfx, fp);
1003                 putc('\t', fp);
1004         }
1005 }
1006
1007 /* little circular references here... */
1008 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1009
1010 static void
1011 sharg(union node *arg, FILE *fp)
1012 {
1013         char *p;
1014         struct nodelist *bqlist;
1015         unsigned char subtype;
1016
1017         if (arg->type != NARG) {
1018                 out1fmt("<node type %d>\n", arg->type);
1019                 abort();
1020         }
1021         bqlist = arg->narg.backquote;
1022         for (p = arg->narg.text; *p; p++) {
1023                 switch ((unsigned char)*p) {
1024                 case CTLESC:
1025                         p++;
1026                         putc(*p, fp);
1027                         break;
1028                 case CTLVAR:
1029                         putc('$', fp);
1030                         putc('{', fp);
1031                         subtype = *++p;
1032                         if (subtype == VSLENGTH)
1033                                 putc('#', fp);
1034
1035                         while (*p != '=') {
1036                                 putc(*p, fp);
1037                                 p++;
1038                         }
1039
1040                         if (subtype & VSNUL)
1041                                 putc(':', fp);
1042
1043                         switch (subtype & VSTYPE) {
1044                         case VSNORMAL:
1045                                 putc('}', fp);
1046                                 break;
1047                         case VSMINUS:
1048                                 putc('-', fp);
1049                                 break;
1050                         case VSPLUS:
1051                                 putc('+', fp);
1052                                 break;
1053                         case VSQUESTION:
1054                                 putc('?', fp);
1055                                 break;
1056                         case VSASSIGN:
1057                                 putc('=', fp);
1058                                 break;
1059                         case VSTRIMLEFT:
1060                                 putc('#', fp);
1061                                 break;
1062                         case VSTRIMLEFTMAX:
1063                                 putc('#', fp);
1064                                 putc('#', fp);
1065                                 break;
1066                         case VSTRIMRIGHT:
1067                                 putc('%', fp);
1068                                 break;
1069                         case VSTRIMRIGHTMAX:
1070                                 putc('%', fp);
1071                                 putc('%', fp);
1072                                 break;
1073                         case VSLENGTH:
1074                                 break;
1075                         default:
1076                                 out1fmt("<subtype %d>", subtype);
1077                         }
1078                         break;
1079                 case CTLENDVAR:
1080                         putc('}', fp);
1081                         break;
1082                 case CTLBACKQ:
1083                         putc('$', fp);
1084                         putc('(', fp);
1085                         shtree(bqlist->n, -1, NULL, fp);
1086                         putc(')', fp);
1087                         break;
1088                 default:
1089                         putc(*p, fp);
1090                         break;
1091                 }
1092         }
1093 }
1094
1095 static void
1096 shcmd(union node *cmd, FILE *fp)
1097 {
1098         union node *np;
1099         int first;
1100         const char *s;
1101         int dftfd;
1102
1103         first = 1;
1104         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1105                 if (!first)
1106                         putc(' ', fp);
1107                 sharg(np, fp);
1108                 first = 0;
1109         }
1110         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1111                 if (!first)
1112                         putc(' ', fp);
1113                 dftfd = 0;
1114                 switch (np->nfile.type) {
1115                 case NTO:      s = ">>"+1; dftfd = 1; break;
1116                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1117                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1118 #if BASH_REDIR_OUTPUT
1119                 case NTO2:
1120 #endif
1121                 case NTOFD:    s = ">&"; dftfd = 1; break;
1122                 case NFROM:    s = "<"; break;
1123                 case NFROMFD:  s = "<&"; break;
1124                 case NFROMTO:  s = "<>"; break;
1125                 default:       s = "*error*"; break;
1126                 }
1127                 if (np->nfile.fd != dftfd)
1128                         fprintf(fp, "%d", np->nfile.fd);
1129                 fputs(s, fp);
1130                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1131                         fprintf(fp, "%d", np->ndup.dupfd);
1132                 } else {
1133                         sharg(np->nfile.fname, fp);
1134                 }
1135                 first = 0;
1136         }
1137 }
1138
1139 static void
1140 shtree(union node *n, int ind, char *pfx, FILE *fp)
1141 {
1142         struct nodelist *lp;
1143         const char *s;
1144
1145         if (n == NULL)
1146                 return;
1147
1148         indent(ind, pfx, fp);
1149
1150         if (n == NODE_EOF) {
1151                 fputs("<EOF>", fp);
1152                 return;
1153         }
1154
1155         switch (n->type) {
1156         case NSEMI:
1157                 s = "; ";
1158                 goto binop;
1159         case NAND:
1160                 s = " && ";
1161                 goto binop;
1162         case NOR:
1163                 s = " || ";
1164  binop:
1165                 shtree(n->nbinary.ch1, ind, NULL, fp);
1166                 /* if (ind < 0) */
1167                         fputs(s, fp);
1168                 shtree(n->nbinary.ch2, ind, NULL, fp);
1169                 break;
1170         case NCMD:
1171                 shcmd(n, fp);
1172                 if (ind >= 0)
1173                         putc('\n', fp);
1174                 break;
1175         case NPIPE:
1176                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1177                         shtree(lp->n, 0, NULL, fp);
1178                         if (lp->next)
1179                                 fputs(" | ", fp);
1180                 }
1181                 if (n->npipe.pipe_backgnd)
1182                         fputs(" &", fp);
1183                 if (ind >= 0)
1184                         putc('\n', fp);
1185                 break;
1186         default:
1187                 fprintf(fp, "<node type %d>", n->type);
1188                 if (ind >= 0)
1189                         putc('\n', fp);
1190                 break;
1191         }
1192 }
1193
1194 static void
1195 showtree(union node *n)
1196 {
1197         trace_puts("showtree called\n");
1198         shtree(n, 1, NULL, stderr);
1199 }
1200
1201 #endif /* DEBUG */
1202
1203
1204 /* ============ Parser data */
1205
1206 /*
1207  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1208  */
1209 struct strlist {
1210         struct strlist *next;
1211         char *text;
1212 };
1213
1214 struct alias;
1215
1216 struct strpush {
1217         struct strpush *prev;   /* preceding string on stack */
1218         char *prev_string;
1219         int prev_left_in_line;
1220 #if ENABLE_ASH_ALIAS
1221         struct alias *ap;       /* if push was associated with an alias */
1222 #endif
1223         char *string;           /* remember the string since it may change */
1224
1225         /* Remember last two characters for pungetc. */
1226         int lastc[2];
1227
1228         /* Number of outstanding calls to pungetc. */
1229         int unget;
1230 };
1231
1232 /*
1233  * The parsefile structure pointed to by the global variable parsefile
1234  * contains information about the current file being read.
1235  */
1236 struct parsefile {
1237         struct parsefile *prev; /* preceding file on stack */
1238         int linno;              /* current line */
1239         int pf_fd;              /* file descriptor (or -1 if string) */
1240         int left_in_line;       /* number of chars left in this line */
1241         int left_in_buffer;     /* number of chars left in this buffer past the line */
1242         char *next_to_pgetc;    /* next char in buffer */
1243         char *buf;              /* input buffer */
1244         struct strpush *strpush; /* for pushing strings at this level */
1245         struct strpush basestrpush; /* so pushing one is fast */
1246
1247         /* Remember last two characters for pungetc. */
1248         int lastc[2];
1249
1250         /* Number of outstanding calls to pungetc. */
1251         int unget;
1252 };
1253
1254 static struct parsefile basepf;        /* top level input file */
1255 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1256 static int startlinno;                 /* line # where last token started */
1257 static char *commandname;              /* currently executing command */
1258
1259
1260 /* ============ Message printing */
1261
1262 static void
1263 ash_vmsg(const char *msg, va_list ap)
1264 {
1265         fprintf(stderr, "%s: ", arg0);
1266         if (commandname) {
1267                 if (strcmp(arg0, commandname))
1268                         fprintf(stderr, "%s: ", commandname);
1269                 if (!iflag || g_parsefile->pf_fd > 0)
1270                         fprintf(stderr, "line %d: ", startlinno);
1271         }
1272         vfprintf(stderr, msg, ap);
1273         newline_and_flush(stderr);
1274 }
1275
1276 /*
1277  * Exverror is called to raise the error exception.  If the second argument
1278  * is not NULL then error prints an error message using printf style
1279  * formatting.  It then raises the error exception.
1280  */
1281 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1282 static void
1283 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1284 {
1285 #if DEBUG
1286         if (msg) {
1287                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1288                 TRACEV((msg, ap));
1289         } else
1290                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1291         if (msg)
1292 #endif
1293                 ash_vmsg(msg, ap);
1294
1295         flush_stdout_stderr();
1296         raise_exception(cond);
1297         /* NOTREACHED */
1298 }
1299
1300 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1301 static void
1302 ash_msg_and_raise_error(const char *msg, ...)
1303 {
1304         va_list ap;
1305
1306         exitstatus = 2;
1307
1308         va_start(ap, msg);
1309         ash_vmsg_and_raise(EXERROR, msg, ap);
1310         /* NOTREACHED */
1311         va_end(ap);
1312 }
1313
1314 /*
1315  * 'fmt' must be a string literal.
1316  */
1317 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1318
1319 static void raise_error_syntax(const char *) NORETURN;
1320 static void
1321 raise_error_syntax(const char *msg)
1322 {
1323         ash_msg_and_raise_error("syntax error: %s", msg);
1324         /* NOTREACHED */
1325 }
1326
1327 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1328 static void
1329 ash_msg_and_raise(int cond, const char *msg, ...)
1330 {
1331         va_list ap;
1332
1333         va_start(ap, msg);
1334         ash_vmsg_and_raise(cond, msg, ap);
1335         /* NOTREACHED */
1336         va_end(ap);
1337 }
1338
1339 /*
1340  * error/warning routines for external builtins
1341  */
1342 static void
1343 ash_msg(const char *fmt, ...)
1344 {
1345         va_list ap;
1346
1347         va_start(ap, fmt);
1348         ash_vmsg(fmt, ap);
1349         va_end(ap);
1350 }
1351
1352 /*
1353  * Return a string describing an error.  The returned string may be a
1354  * pointer to a static buffer that will be overwritten on the next call.
1355  * Action describes the operation that got the error.
1356  */
1357 static const char *
1358 errmsg(int e, const char *em)
1359 {
1360         if (e == ENOENT || e == ENOTDIR) {
1361                 return em;
1362         }
1363         return strerror(e);
1364 }
1365
1366
1367 /* ============ Memory allocation */
1368
1369 #if 0
1370 /* I consider these wrappers nearly useless:
1371  * ok, they return you to nearest exception handler, but
1372  * how much memory do you leak in the process, making
1373  * memory starvation worse?
1374  */
1375 static void *
1376 ckrealloc(void * p, size_t nbytes)
1377 {
1378         p = realloc(p, nbytes);
1379         if (!p)
1380                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1381         return p;
1382 }
1383
1384 static void *
1385 ckmalloc(size_t nbytes)
1386 {
1387         return ckrealloc(NULL, nbytes);
1388 }
1389
1390 static void *
1391 ckzalloc(size_t nbytes)
1392 {
1393         return memset(ckmalloc(nbytes), 0, nbytes);
1394 }
1395
1396 static char *
1397 ckstrdup(const char *s)
1398 {
1399         char *p = strdup(s);
1400         if (!p)
1401                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1402         return p;
1403 }
1404 #else
1405 /* Using bbox equivalents. They exit if out of memory */
1406 # define ckrealloc xrealloc
1407 # define ckmalloc  xmalloc
1408 # define ckzalloc  xzalloc
1409 # define ckstrdup  xstrdup
1410 #endif
1411
1412 /*
1413  * It appears that grabstackstr() will barf with such alignments
1414  * because stalloc() will return a string allocated in a new stackblock.
1415  */
1416 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1417 enum {
1418         /* Most machines require the value returned from malloc to be aligned
1419          * in some way.  The following macro will get this right
1420          * on many machines.  */
1421         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1422         /* Minimum size of a block */
1423         MINSIZE = SHELL_ALIGN(504),
1424 };
1425
1426 struct stack_block {
1427         struct stack_block *prev;
1428         char space[MINSIZE];
1429 };
1430
1431 struct stackmark {
1432         struct stack_block *stackp;
1433         char *stacknxt;
1434         size_t stacknleft;
1435 };
1436
1437
1438 struct globals_memstack {
1439         struct stack_block *g_stackp; // = &stackbase;
1440         char *g_stacknxt; // = stackbase.space;
1441         char *sstrend; // = stackbase.space + MINSIZE;
1442         size_t g_stacknleft; // = MINSIZE;
1443         struct stack_block stackbase;
1444 };
1445 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1446 #define G_memstack (*ash_ptr_to_globals_memstack)
1447 #define g_stackp     (G_memstack.g_stackp    )
1448 #define g_stacknxt   (G_memstack.g_stacknxt  )
1449 #define sstrend      (G_memstack.sstrend     )
1450 #define g_stacknleft (G_memstack.g_stacknleft)
1451 #define stackbase    (G_memstack.stackbase   )
1452 #define INIT_G_memstack() do { \
1453         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1454         barrier(); \
1455         g_stackp = &stackbase; \
1456         g_stacknxt = stackbase.space; \
1457         g_stacknleft = MINSIZE; \
1458         sstrend = stackbase.space + MINSIZE; \
1459 } while (0)
1460
1461
1462 #define stackblock()     ((void *)g_stacknxt)
1463 #define stackblocksize() g_stacknleft
1464
1465 /*
1466  * Parse trees for commands are allocated in lifo order, so we use a stack
1467  * to make this more efficient, and also to avoid all sorts of exception
1468  * handling code to handle interrupts in the middle of a parse.
1469  *
1470  * The size 504 was chosen because the Ultrix malloc handles that size
1471  * well.
1472  */
1473 static void *
1474 stalloc(size_t nbytes)
1475 {
1476         char *p;
1477         size_t aligned;
1478
1479         aligned = SHELL_ALIGN(nbytes);
1480         if (aligned > g_stacknleft) {
1481                 size_t len;
1482                 size_t blocksize;
1483                 struct stack_block *sp;
1484
1485                 blocksize = aligned;
1486                 if (blocksize < MINSIZE)
1487                         blocksize = MINSIZE;
1488                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1489                 if (len < blocksize)
1490                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1491                 INT_OFF;
1492                 sp = ckmalloc(len);
1493                 sp->prev = g_stackp;
1494                 g_stacknxt = sp->space;
1495                 g_stacknleft = blocksize;
1496                 sstrend = g_stacknxt + blocksize;
1497                 g_stackp = sp;
1498                 INT_ON;
1499         }
1500         p = g_stacknxt;
1501         g_stacknxt += aligned;
1502         g_stacknleft -= aligned;
1503         return p;
1504 }
1505
1506 static void *
1507 stzalloc(size_t nbytes)
1508 {
1509         return memset(stalloc(nbytes), 0, nbytes);
1510 }
1511
1512 static void
1513 stunalloc(void *p)
1514 {
1515 #if DEBUG
1516         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1517                 write(STDERR_FILENO, "stunalloc\n", 10);
1518                 abort();
1519         }
1520 #endif
1521         g_stacknleft += g_stacknxt - (char *)p;
1522         g_stacknxt = p;
1523 }
1524
1525 /*
1526  * Like strdup but works with the ash stack.
1527  */
1528 static char *
1529 sstrdup(const char *p)
1530 {
1531         size_t len = strlen(p) + 1;
1532         return memcpy(stalloc(len), p, len);
1533 }
1534
1535 static inline void
1536 grabstackblock(size_t len)
1537 {
1538         stalloc(len);
1539 }
1540
1541 static void
1542 pushstackmark(struct stackmark *mark, size_t len)
1543 {
1544         mark->stackp = g_stackp;
1545         mark->stacknxt = g_stacknxt;
1546         mark->stacknleft = g_stacknleft;
1547         grabstackblock(len);
1548 }
1549
1550 static void
1551 setstackmark(struct stackmark *mark)
1552 {
1553         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1554 }
1555
1556 static void
1557 popstackmark(struct stackmark *mark)
1558 {
1559         struct stack_block *sp;
1560
1561         if (!mark->stackp)
1562                 return;
1563
1564         INT_OFF;
1565         while (g_stackp != mark->stackp) {
1566                 sp = g_stackp;
1567                 g_stackp = sp->prev;
1568                 free(sp);
1569         }
1570         g_stacknxt = mark->stacknxt;
1571         g_stacknleft = mark->stacknleft;
1572         sstrend = mark->stacknxt + mark->stacknleft;
1573         INT_ON;
1574 }
1575
1576 /*
1577  * When the parser reads in a string, it wants to stick the string on the
1578  * stack and only adjust the stack pointer when it knows how big the
1579  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1580  * of space on top of the stack and stackblocklen returns the length of
1581  * this block.  Growstackblock will grow this space by at least one byte,
1582  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1583  * part of the block that has been used.
1584  */
1585 static void
1586 growstackblock(void)
1587 {
1588         size_t newlen;
1589
1590         newlen = g_stacknleft * 2;
1591         if (newlen < g_stacknleft)
1592                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1593         if (newlen < 128)
1594                 newlen += 128;
1595
1596         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1597                 struct stack_block *sp;
1598                 struct stack_block *prevstackp;
1599                 size_t grosslen;
1600
1601                 INT_OFF;
1602                 sp = g_stackp;
1603                 prevstackp = sp->prev;
1604                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1605                 sp = ckrealloc(sp, grosslen);
1606                 sp->prev = prevstackp;
1607                 g_stackp = sp;
1608                 g_stacknxt = sp->space;
1609                 g_stacknleft = newlen;
1610                 sstrend = sp->space + newlen;
1611                 INT_ON;
1612         } else {
1613                 char *oldspace = g_stacknxt;
1614                 size_t oldlen = g_stacknleft;
1615                 char *p = stalloc(newlen);
1616
1617                 /* free the space we just allocated */
1618                 g_stacknxt = memcpy(p, oldspace, oldlen);
1619                 g_stacknleft += newlen;
1620         }
1621 }
1622
1623 /*
1624  * The following routines are somewhat easier to use than the above.
1625  * The user declares a variable of type STACKSTR, which may be declared
1626  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1627  * the user uses the macro STPUTC to add characters to the string.  In
1628  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1629  * grown as necessary.  When the user is done, she can just leave the
1630  * string there and refer to it using stackblock().  Or she can allocate
1631  * the space for it using grabstackstr().  If it is necessary to allow
1632  * someone else to use the stack temporarily and then continue to grow
1633  * the string, the user should use grabstack to allocate the space, and
1634  * then call ungrabstr(p) to return to the previous mode of operation.
1635  *
1636  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1637  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1638  * is space for at least one character.
1639  */
1640 static void *
1641 growstackstr(void)
1642 {
1643         size_t len = stackblocksize();
1644         growstackblock();
1645         return (char *)stackblock() + len;
1646 }
1647
1648 /*
1649  * Called from CHECKSTRSPACE.
1650  */
1651 static char *
1652 makestrspace(size_t newlen, char *p)
1653 {
1654         size_t len = p - g_stacknxt;
1655         size_t size;
1656
1657         for (;;) {
1658                 size_t nleft;
1659
1660                 size = stackblocksize();
1661                 nleft = size - len;
1662                 if (nleft >= newlen)
1663                         break;
1664                 growstackblock();
1665         }
1666         return (char *)stackblock() + len;
1667 }
1668
1669 static char *
1670 stack_nputstr(const char *s, size_t n, char *p)
1671 {
1672         p = makestrspace(n, p);
1673         p = (char *)mempcpy(p, s, n);
1674         return p;
1675 }
1676
1677 static char *
1678 stack_putstr(const char *s, char *p)
1679 {
1680         return stack_nputstr(s, strlen(s), p);
1681 }
1682
1683 static char *
1684 _STPUTC(int c, char *p)
1685 {
1686         if (p == sstrend)
1687                 p = growstackstr();
1688         *p++ = c;
1689         return p;
1690 }
1691
1692 #define STARTSTACKSTR(p)        ((p) = stackblock())
1693 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1694 #define CHECKSTRSPACE(n, p) do { \
1695         char *q = (p); \
1696         size_t l = (n); \
1697         size_t m = sstrend - q; \
1698         if (l > m) \
1699                 (p) = makestrspace(l, q); \
1700 } while (0)
1701 #define USTPUTC(c, p)           (*(p)++ = (c))
1702 #define STACKSTRNUL(p) do { \
1703         if ((p) == sstrend) \
1704                 (p) = growstackstr(); \
1705         *(p) = '\0'; \
1706 } while (0)
1707 #define STUNPUTC(p)             (--(p))
1708 #define STTOPC(p)               ((p)[-1])
1709 #define STADJUST(amount, p)     ((p) += (amount))
1710
1711 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1712 #define ungrabstackstr(s, p)    stunalloc(s)
1713 #define stackstrend()           ((void *)sstrend)
1714
1715
1716 /* ============ String helpers */
1717
1718 /*
1719  * prefix -- see if pfx is a prefix of string.
1720  */
1721 static char *
1722 prefix(const char *string, const char *pfx)
1723 {
1724         while (*pfx) {
1725                 if (*pfx++ != *string++)
1726                         return NULL;
1727         }
1728         return (char *) string;
1729 }
1730
1731 /*
1732  * Check for a valid number.  This should be elsewhere.
1733  */
1734 static int
1735 is_number(const char *p)
1736 {
1737         do {
1738                 if (!isdigit(*p))
1739                         return 0;
1740         } while (*++p != '\0');
1741         return 1;
1742 }
1743
1744 /*
1745  * Convert a string of digits to an integer, printing an error message on
1746  * failure.
1747  */
1748 static int
1749 number(const char *s)
1750 {
1751         if (!is_number(s))
1752                 ash_msg_and_raise_error(msg_illnum, s);
1753         return atoi(s);
1754 }
1755
1756 /*
1757  * Produce a single quoted string suitable as input to the shell.
1758  * The return string is allocated on the stack.
1759  */
1760 static char *
1761 single_quote(const char *s)
1762 {
1763         char *p;
1764
1765         STARTSTACKSTR(p);
1766
1767         do {
1768                 char *q;
1769                 size_t len;
1770
1771                 len = strchrnul(s, '\'') - s;
1772
1773                 q = p = makestrspace(len + 3, p);
1774
1775                 *q++ = '\'';
1776                 q = (char *)mempcpy(q, s, len);
1777                 *q++ = '\'';
1778                 s += len;
1779
1780                 STADJUST(q - p, p);
1781
1782                 if (*s != '\'')
1783                         break;
1784                 len = 0;
1785                 do len++; while (*++s == '\'');
1786
1787                 q = p = makestrspace(len + 3, p);
1788
1789                 *q++ = '"';
1790                 q = (char *)mempcpy(q, s - len, len);
1791                 *q++ = '"';
1792
1793                 STADJUST(q - p, p);
1794         } while (*s);
1795
1796         USTPUTC('\0', p);
1797
1798         return stackblock();
1799 }
1800
1801 /*
1802  * Produce a possibly single quoted string suitable as input to the shell.
1803  * If quoting was done, the return string is allocated on the stack,
1804  * otherwise a pointer to the original string is returned.
1805  */
1806 static const char *
1807 maybe_single_quote(const char *s)
1808 {
1809         const char *p = s;
1810
1811         while (*p) {
1812                 /* Assuming ACSII */
1813                 /* quote ctrl_chars space !"#$%&'()* */
1814                 if (*p < '+')
1815                         goto need_quoting;
1816                 /* quote ;<=>? */
1817                 if (*p >= ';' && *p <= '?')
1818                         goto need_quoting;
1819                 /* quote `[\ */
1820                 if (*p == '`')
1821                         goto need_quoting;
1822                 if (*p == '[')
1823                         goto need_quoting;
1824                 if (*p == '\\')
1825                         goto need_quoting;
1826                 /* quote {|}~ DEL and high bytes */
1827                 if (*p > 'z')
1828                         goto need_quoting;
1829                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1830                 /* TODO: maybe avoid quoting % */
1831                 p++;
1832         }
1833         return s;
1834
1835  need_quoting:
1836         return single_quote(s);
1837 }
1838
1839
1840 /* ============ nextopt */
1841
1842 static char **argptr;                  /* argument list for builtin commands */
1843 static char *optionarg;                /* set by nextopt (like getopt) */
1844 static char *optptr;                   /* used by nextopt */
1845
1846 /*
1847  * XXX - should get rid of. Have all builtins use getopt(3).
1848  * The library getopt must have the BSD extension static variable
1849  * "optreset", otherwise it can't be used within the shell safely.
1850  *
1851  * Standard option processing (a la getopt) for builtin routines.
1852  * The only argument that is passed to nextopt is the option string;
1853  * the other arguments are unnecessary. It returns the character,
1854  * or '\0' on end of input.
1855  */
1856 static int
1857 nextopt(const char *optstring)
1858 {
1859         char *p;
1860         const char *q;
1861         char c;
1862
1863         p = optptr;
1864         if (p == NULL || *p == '\0') {
1865                 /* We ate entire "-param", take next one */
1866                 p = *argptr;
1867                 if (p == NULL)
1868                         return '\0';
1869                 if (*p != '-')
1870                         return '\0';
1871                 if (*++p == '\0') /* just "-" ? */
1872                         return '\0';
1873                 argptr++;
1874                 if (LONE_DASH(p)) /* "--" ? */
1875                         return '\0';
1876                 /* p => next "-param" */
1877         }
1878         /* p => some option char in the middle of a "-param" */
1879         c = *p++;
1880         for (q = optstring; *q != c;) {
1881                 if (*q == '\0')
1882                         ash_msg_and_raise_error("illegal option -%c", c);
1883                 if (*++q == ':')
1884                         q++;
1885         }
1886         if (*++q == ':') {
1887                 if (*p == '\0') {
1888                         p = *argptr++;
1889                         if (p == NULL)
1890                                 ash_msg_and_raise_error("no arg for -%c option", c);
1891                 }
1892                 optionarg = p;
1893                 p = NULL;
1894         }
1895         optptr = p;
1896         return c;
1897 }
1898
1899
1900 /* ============ Shell variables */
1901
1902 struct shparam {
1903         int nparam;             /* # of positional parameters (without $0) */
1904 #if ENABLE_ASH_GETOPTS
1905         int optind;             /* next parameter to be processed by getopts */
1906         int optoff;             /* used by getopts */
1907 #endif
1908         unsigned char malloced; /* if parameter list dynamically allocated */
1909         char **p;               /* parameter list */
1910 };
1911
1912 /*
1913  * Free the list of positional parameters.
1914  */
1915 static void
1916 freeparam(volatile struct shparam *param)
1917 {
1918         if (param->malloced) {
1919                 char **ap, **ap1;
1920                 ap = ap1 = param->p;
1921                 while (*ap)
1922                         free(*ap++);
1923                 free(ap1);
1924         }
1925 }
1926
1927 #if ENABLE_ASH_GETOPTS
1928 static void FAST_FUNC getoptsreset(const char *value);
1929 #endif
1930
1931 struct var {
1932         struct var *next;               /* next entry in hash list */
1933         int flags;                      /* flags are defined above */
1934         const char *var_text;           /* name=value */
1935         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1936                                         /* the variable gets set/unset */
1937 };
1938
1939 struct localvar {
1940         struct localvar *next;          /* next local variable in list */
1941         struct var *vp;                 /* the variable that was made local */
1942         int flags;                      /* saved flags */
1943         const char *text;               /* saved text */
1944 };
1945
1946 /* flags */
1947 #define VEXPORT         0x01    /* variable is exported */
1948 #define VREADONLY       0x02    /* variable cannot be modified */
1949 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1950 #define VTEXTFIXED      0x08    /* text is statically allocated */
1951 #define VSTACK          0x10    /* text is allocated on the stack */
1952 #define VUNSET          0x20    /* the variable is not set */
1953 #define VNOFUNC         0x40    /* don't call the callback function */
1954 #define VNOSET          0x80    /* do not set variable - just readonly test */
1955 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1956 #if ENABLE_ASH_RANDOM_SUPPORT
1957 # define VDYNAMIC       0x200   /* dynamic variable */
1958 #else
1959 # define VDYNAMIC       0
1960 #endif
1961
1962
1963 /* Need to be before varinit_data[] */
1964 #if ENABLE_LOCALE_SUPPORT
1965 static void FAST_FUNC
1966 change_lc_all(const char *value)
1967 {
1968         if (value && *value != '\0')
1969                 setlocale(LC_ALL, value);
1970 }
1971 static void FAST_FUNC
1972 change_lc_ctype(const char *value)
1973 {
1974         if (value && *value != '\0')
1975                 setlocale(LC_CTYPE, value);
1976 }
1977 #endif
1978 #if ENABLE_ASH_MAIL
1979 static void chkmail(void);
1980 static void changemail(const char *var_value) FAST_FUNC;
1981 #else
1982 # define chkmail()  ((void)0)
1983 #endif
1984 static void changepath(const char *) FAST_FUNC;
1985 #if ENABLE_ASH_RANDOM_SUPPORT
1986 static void change_random(const char *) FAST_FUNC;
1987 #endif
1988
1989 static const struct {
1990         int flags;
1991         const char *var_text;
1992         void (*var_func)(const char *) FAST_FUNC;
1993 } varinit_data[] = {
1994         /*
1995          * Note: VEXPORT would not work correctly here for NOFORK applets:
1996          * some environment strings may be constant.
1997          */
1998         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1999 #if ENABLE_ASH_MAIL
2000         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2001         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2002 #endif
2003         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2004         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2005         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2006         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2007 #if ENABLE_ASH_GETOPTS
2008         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2009 #endif
2010 #if ENABLE_ASH_RANDOM_SUPPORT
2011         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2012 #endif
2013 #if ENABLE_LOCALE_SUPPORT
2014         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2015         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2016 #endif
2017 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2018         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2019 #endif
2020 };
2021
2022 struct redirtab;
2023
2024 struct globals_var {
2025         struct shparam shellparam;      /* $@ current positional parameters */
2026         struct redirtab *redirlist;
2027         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2028         struct var *vartab[VTABSIZE];
2029         struct var varinit[ARRAY_SIZE(varinit_data)];
2030 };
2031 extern struct globals_var *const ash_ptr_to_globals_var;
2032 #define G_var (*ash_ptr_to_globals_var)
2033 #define shellparam    (G_var.shellparam   )
2034 //#define redirlist     (G_var.redirlist    )
2035 #define preverrout_fd (G_var.preverrout_fd)
2036 #define vartab        (G_var.vartab       )
2037 #define varinit       (G_var.varinit      )
2038 #define INIT_G_var() do { \
2039         unsigned i; \
2040         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2041         barrier(); \
2042         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2043                 varinit[i].flags    = varinit_data[i].flags; \
2044                 varinit[i].var_text = varinit_data[i].var_text; \
2045                 varinit[i].var_func = varinit_data[i].var_func; \
2046         } \
2047 } while (0)
2048
2049 #define vifs      varinit[0]
2050 #if ENABLE_ASH_MAIL
2051 # define vmail    (&vifs)[1]
2052 # define vmpath   (&vmail)[1]
2053 # define vpath    (&vmpath)[1]
2054 #else
2055 # define vpath    (&vifs)[1]
2056 #endif
2057 #define vps1      (&vpath)[1]
2058 #define vps2      (&vps1)[1]
2059 #define vps4      (&vps2)[1]
2060 #if ENABLE_ASH_GETOPTS
2061 # define voptind  (&vps4)[1]
2062 # if ENABLE_ASH_RANDOM_SUPPORT
2063 #  define vrandom (&voptind)[1]
2064 # endif
2065 #else
2066 # if ENABLE_ASH_RANDOM_SUPPORT
2067 #  define vrandom (&vps4)[1]
2068 # endif
2069 #endif
2070
2071 /*
2072  * The following macros access the values of the above variables.
2073  * They have to skip over the name.  They return the null string
2074  * for unset variables.
2075  */
2076 #define ifsval()        (vifs.var_text + 4)
2077 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2078 #if ENABLE_ASH_MAIL
2079 # define mailval()      (vmail.var_text + 5)
2080 # define mpathval()     (vmpath.var_text + 9)
2081 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2082 #endif
2083 #define pathval()       (vpath.var_text + 5)
2084 #define ps1val()        (vps1.var_text + 4)
2085 #define ps2val()        (vps2.var_text + 4)
2086 #define ps4val()        (vps4.var_text + 4)
2087 #if ENABLE_ASH_GETOPTS
2088 # define optindval()    (voptind.var_text + 7)
2089 #endif
2090
2091 #if ENABLE_ASH_GETOPTS
2092 static void FAST_FUNC
2093 getoptsreset(const char *value)
2094 {
2095         shellparam.optind = 1;
2096         if (is_number(value))
2097                 shellparam.optind = number(value) ?: 1;
2098         shellparam.optoff = -1;
2099 }
2100 #endif
2101
2102 /*
2103  * Compares two strings up to the first = or '\0'.  The first
2104  * string must be terminated by '='; the second may be terminated by
2105  * either '=' or '\0'.
2106  */
2107 static int
2108 varcmp(const char *p, const char *q)
2109 {
2110         int c, d;
2111
2112         while ((c = *p) == (d = *q)) {
2113                 if (c == '\0' || c == '=')
2114                         goto out;
2115                 p++;
2116                 q++;
2117         }
2118         if (c == '=')
2119                 c = '\0';
2120         if (d == '=')
2121                 d = '\0';
2122  out:
2123         return c - d;
2124 }
2125
2126 /*
2127  * Find the appropriate entry in the hash table from the name.
2128  */
2129 static struct var **
2130 hashvar(const char *p)
2131 {
2132         unsigned hashval;
2133
2134         hashval = ((unsigned char) *p) << 4;
2135         while (*p && *p != '=')
2136                 hashval += (unsigned char) *p++;
2137         return &vartab[hashval % VTABSIZE];
2138 }
2139
2140 static int
2141 vpcmp(const void *a, const void *b)
2142 {
2143         return varcmp(*(const char **)a, *(const char **)b);
2144 }
2145
2146 /*
2147  * This routine initializes the builtin variables.
2148  */
2149 static void
2150 initvar(void)
2151 {
2152         struct var *vp;
2153         struct var *end;
2154         struct var **vpp;
2155
2156         /*
2157          * PS1 depends on uid
2158          */
2159 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2160         vps1.var_text = "PS1=\\w \\$ ";
2161 #else
2162         if (!geteuid())
2163                 vps1.var_text = "PS1=# ";
2164 #endif
2165         vp = varinit;
2166         end = vp + ARRAY_SIZE(varinit);
2167         do {
2168                 vpp = hashvar(vp->var_text);
2169                 vp->next = *vpp;
2170                 *vpp = vp;
2171         } while (++vp < end);
2172 }
2173
2174 static struct var **
2175 findvar(struct var **vpp, const char *name)
2176 {
2177         for (; *vpp; vpp = &(*vpp)->next) {
2178                 if (varcmp((*vpp)->var_text, name) == 0) {
2179                         break;
2180                 }
2181         }
2182         return vpp;
2183 }
2184
2185 /*
2186  * Find the value of a variable.  Returns NULL if not set.
2187  */
2188 static const char* FAST_FUNC
2189 lookupvar(const char *name)
2190 {
2191         struct var *v;
2192
2193         v = *findvar(hashvar(name), name);
2194         if (v) {
2195 #if ENABLE_ASH_RANDOM_SUPPORT
2196         /*
2197          * Dynamic variables are implemented roughly the same way they are
2198          * in bash. Namely, they're "special" so long as they aren't unset.
2199          * As soon as they're unset, they're no longer dynamic, and dynamic
2200          * lookup will no longer happen at that point. -- PFM.
2201          */
2202                 if (v->flags & VDYNAMIC)
2203                         v->var_func(NULL);
2204 #endif
2205                 if (!(v->flags & VUNSET))
2206                         return var_end(v->var_text);
2207         }
2208         return NULL;
2209 }
2210
2211 #if ENABLE_UNICODE_SUPPORT
2212 static void
2213 reinit_unicode_for_ash(void)
2214 {
2215         /* Unicode support should be activated even if LANG is set
2216          * _during_ shell execution, not only if it was set when
2217          * shell was started. Therefore, re-check LANG every time:
2218          */
2219         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2220          || ENABLE_UNICODE_USING_LOCALE
2221         ) {
2222                 const char *s = lookupvar("LC_ALL");
2223                 if (!s) s = lookupvar("LC_CTYPE");
2224                 if (!s) s = lookupvar("LANG");
2225                 reinit_unicode(s);
2226         }
2227 }
2228 #else
2229 # define reinit_unicode_for_ash() ((void)0)
2230 #endif
2231
2232 /*
2233  * Search the environment of a builtin command.
2234  */
2235 static ALWAYS_INLINE const char *
2236 bltinlookup(const char *name)
2237 {
2238         return lookupvar(name);
2239 }
2240
2241 /*
2242  * Same as setvar except that the variable and value are passed in
2243  * the first argument as name=value.  Since the first argument will
2244  * be actually stored in the table, it should not be a string that
2245  * will go away.
2246  * Called with interrupts off.
2247  */
2248 static struct var *
2249 setvareq(char *s, int flags)
2250 {
2251         struct var *vp, **vpp;
2252
2253         vpp = hashvar(s);
2254         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2255         vpp = findvar(vpp, s);
2256         vp = *vpp;
2257         if (vp) {
2258                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2259                         const char *n;
2260
2261                         if (flags & VNOSAVE)
2262                                 free(s);
2263                         n = vp->var_text;
2264                         exitstatus = 1;
2265                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2266                 }
2267
2268                 if (flags & VNOSET)
2269                         goto out;
2270
2271                 if (vp->var_func && !(flags & VNOFUNC))
2272                         vp->var_func(var_end(s));
2273
2274                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2275                         free((char*)vp->var_text);
2276
2277                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2278                         *vpp = vp->next;
2279                         free(vp);
2280  out_free:
2281                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2282                                 free(s);
2283                         goto out;
2284                 }
2285
2286                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2287         } else {
2288                 /* variable s is not found */
2289                 if (flags & VNOSET)
2290                         goto out;
2291                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2292                         goto out_free;
2293                 vp = ckzalloc(sizeof(*vp));
2294                 vp->next = *vpp;
2295                 /*vp->func = NULL; - ckzalloc did it */
2296                 *vpp = vp;
2297         }
2298         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2299                 s = ckstrdup(s);
2300         vp->var_text = s;
2301         vp->flags = flags;
2302
2303  out:
2304         return vp;
2305 }
2306
2307 /*
2308  * Set the value of a variable.  The flags argument is ored with the
2309  * flags of the variable.  If val is NULL, the variable is unset.
2310  */
2311 static struct var *
2312 setvar(const char *name, const char *val, int flags)
2313 {
2314         const char *q;
2315         char *p;
2316         char *nameeq;
2317         size_t namelen;
2318         size_t vallen;
2319         struct var *vp;
2320
2321         q = endofname(name);
2322         p = strchrnul(q, '=');
2323         namelen = p - name;
2324         if (!namelen || p != q)
2325                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2326         vallen = 0;
2327         if (val == NULL) {
2328                 flags |= VUNSET;
2329         } else {
2330                 vallen = strlen(val);
2331         }
2332
2333         INT_OFF;
2334         nameeq = ckmalloc(namelen + vallen + 2);
2335         p = mempcpy(nameeq, name, namelen);
2336         if (val) {
2337                 *p++ = '=';
2338                 p = mempcpy(p, val, vallen);
2339         }
2340         *p = '\0';
2341         vp = setvareq(nameeq, flags | VNOSAVE);
2342         INT_ON;
2343
2344         return vp;
2345 }
2346
2347 static void FAST_FUNC
2348 setvar0(const char *name, const char *val)
2349 {
2350         setvar(name, val, 0);
2351 }
2352
2353 /*
2354  * Unset the specified variable.
2355  */
2356 static void
2357 unsetvar(const char *s)
2358 {
2359         setvar(s, NULL, 0);
2360 }
2361
2362 /*
2363  * Process a linked list of variable assignments.
2364  */
2365 static void
2366 listsetvar(struct strlist *list_set_var, int flags)
2367 {
2368         struct strlist *lp = list_set_var;
2369
2370         if (!lp)
2371                 return;
2372         INT_OFF;
2373         do {
2374                 setvareq(lp->text, flags);
2375                 lp = lp->next;
2376         } while (lp);
2377         INT_ON;
2378 }
2379
2380 /*
2381  * Generate a list of variables satisfying the given conditions.
2382  */
2383 #if !ENABLE_FEATURE_SH_NOFORK
2384 # define listvars(on, off, lp, end) listvars(on, off, end)
2385 #endif
2386 static char **
2387 listvars(int on, int off, struct strlist *lp, char ***end)
2388 {
2389         struct var **vpp;
2390         struct var *vp;
2391         char **ep;
2392         int mask;
2393
2394         STARTSTACKSTR(ep);
2395         vpp = vartab;
2396         mask = on | off;
2397         do {
2398                 for (vp = *vpp; vp; vp = vp->next) {
2399                         if ((vp->flags & mask) == on) {
2400 #if ENABLE_FEATURE_SH_NOFORK
2401                                 /* If variable with the same name is both
2402                                  * exported and temporarily set for a command:
2403                                  *  export ZVAR=5
2404                                  *  ZVAR=6 printenv
2405                                  * then "ZVAR=6" will be both in vartab and
2406                                  * lp lists. Do not pass it twice to printenv.
2407                                  */
2408                                 struct strlist *lp1 = lp;
2409                                 while (lp1) {
2410                                         if (strcmp(lp1->text, vp->var_text) == 0)
2411                                                 goto skip;
2412                                         lp1 = lp1->next;
2413                                 }
2414 #endif
2415                                 if (ep == stackstrend())
2416                                         ep = growstackstr();
2417                                 *ep++ = (char*)vp->var_text;
2418 #if ENABLE_FEATURE_SH_NOFORK
2419  skip: ;
2420 #endif
2421                         }
2422                 }
2423         } while (++vpp < vartab + VTABSIZE);
2424
2425 #if ENABLE_FEATURE_SH_NOFORK
2426         while (lp) {
2427                 if (ep == stackstrend())
2428                         ep = growstackstr();
2429                 *ep++ = lp->text;
2430                 lp = lp->next;
2431         }
2432 #endif
2433
2434         if (ep == stackstrend())
2435                 ep = growstackstr();
2436         if (end)
2437                 *end = ep;
2438         *ep++ = NULL;
2439         return grabstackstr(ep);
2440 }
2441
2442
2443 /* ============ Path search helper
2444  *
2445  * The variable path (passed by reference) should be set to the start
2446  * of the path before the first call; path_advance will update
2447  * this value as it proceeds.  Successive calls to path_advance will return
2448  * the possible path expansions in sequence.  If an option (indicated by
2449  * a percent sign) appears in the path entry then the global variable
2450  * pathopt will be set to point to it; otherwise pathopt will be set to
2451  * NULL.
2452  */
2453 static const char *pathopt;     /* set by path_advance */
2454
2455 static char *
2456 path_advance(const char **path, const char *name)
2457 {
2458         const char *p;
2459         char *q;
2460         const char *start;
2461         size_t len;
2462
2463         if (*path == NULL)
2464                 return NULL;
2465         start = *path;
2466         for (p = start; *p && *p != ':' && *p != '%'; p++)
2467                 continue;
2468         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2469         while (stackblocksize() < len)
2470                 growstackblock();
2471         q = stackblock();
2472         if (p != start) {
2473                 q = mempcpy(q, start, p - start);
2474                 *q++ = '/';
2475         }
2476         strcpy(q, name);
2477         pathopt = NULL;
2478         if (*p == '%') {
2479                 pathopt = ++p;
2480                 while (*p && *p != ':')
2481                         p++;
2482         }
2483         if (*p == ':')
2484                 *path = p + 1;
2485         else
2486                 *path = NULL;
2487         return stalloc(len);
2488 }
2489
2490
2491 /* ============ Prompt */
2492
2493 static smallint doprompt;                   /* if set, prompt the user */
2494 static smallint needprompt;                 /* true if interactive and at start of line */
2495
2496 #if ENABLE_FEATURE_EDITING
2497 static line_input_t *line_input_state;
2498 static const char *cmdedit_prompt;
2499 static void
2500 putprompt(const char *s)
2501 {
2502         if (ENABLE_ASH_EXPAND_PRMT) {
2503                 free((char*)cmdedit_prompt);
2504                 cmdedit_prompt = ckstrdup(s);
2505                 return;
2506         }
2507         cmdedit_prompt = s;
2508 }
2509 #else
2510 static void
2511 putprompt(const char *s)
2512 {
2513         out2str(s);
2514 }
2515 #endif
2516
2517 /* expandstr() needs parsing machinery, so it is far away ahead... */
2518 static const char *expandstr(const char *ps, int syntax_type);
2519 /* Values for syntax param */
2520 #define BASESYNTAX 0    /* not in quotes */
2521 #define DQSYNTAX   1    /* in double quotes */
2522 #define SQSYNTAX   2    /* in single quotes */
2523 #define ARISYNTAX  3    /* in arithmetic */
2524 #if ENABLE_ASH_EXPAND_PRMT
2525 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2526 #endif
2527 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2528
2529 /*
2530  * called by editline -- any expansions to the prompt should be added here.
2531  */
2532 static void
2533 setprompt_if(smallint do_set, int whichprompt)
2534 {
2535         const char *prompt;
2536         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2537
2538         if (!do_set)
2539                 return;
2540
2541         needprompt = 0;
2542
2543         switch (whichprompt) {
2544         case 1:
2545                 prompt = ps1val();
2546                 break;
2547         case 2:
2548                 prompt = ps2val();
2549                 break;
2550         default:                        /* 0 */
2551                 prompt = nullstr;
2552         }
2553 #if ENABLE_ASH_EXPAND_PRMT
2554         pushstackmark(&smark, stackblocksize());
2555         putprompt(expandstr(prompt, PSSYNTAX));
2556         popstackmark(&smark);
2557 #else
2558         putprompt(prompt);
2559 #endif
2560 }
2561
2562
2563 /* ============ The cd and pwd commands */
2564
2565 #define CD_PHYSICAL 1
2566 #define CD_PRINT 2
2567
2568 static int
2569 cdopt(void)
2570 {
2571         int flags = 0;
2572         int i, j;
2573
2574         j = 'L';
2575         while ((i = nextopt("LP")) != '\0') {
2576                 if (i != j) {
2577                         flags ^= CD_PHYSICAL;
2578                         j = i;
2579                 }
2580         }
2581
2582         return flags;
2583 }
2584
2585 /*
2586  * Update curdir (the name of the current directory) in response to a
2587  * cd command.
2588  */
2589 static const char *
2590 updatepwd(const char *dir)
2591 {
2592         char *new;
2593         char *p;
2594         char *cdcomppath;
2595         const char *lim;
2596
2597         cdcomppath = sstrdup(dir);
2598         STARTSTACKSTR(new);
2599         if (*dir != '/') {
2600                 if (curdir == nullstr)
2601                         return 0;
2602                 new = stack_putstr(curdir, new);
2603         }
2604         new = makestrspace(strlen(dir) + 2, new);
2605         lim = (char *)stackblock() + 1;
2606         if (*dir != '/') {
2607                 if (new[-1] != '/')
2608                         USTPUTC('/', new);
2609                 if (new > lim && *lim == '/')
2610                         lim++;
2611         } else {
2612                 USTPUTC('/', new);
2613                 cdcomppath++;
2614                 if (dir[1] == '/' && dir[2] != '/') {
2615                         USTPUTC('/', new);
2616                         cdcomppath++;
2617                         lim++;
2618                 }
2619         }
2620         p = strtok(cdcomppath, "/");
2621         while (p) {
2622                 switch (*p) {
2623                 case '.':
2624                         if (p[1] == '.' && p[2] == '\0') {
2625                                 while (new > lim) {
2626                                         STUNPUTC(new);
2627                                         if (new[-1] == '/')
2628                                                 break;
2629                                 }
2630                                 break;
2631                         }
2632                         if (p[1] == '\0')
2633                                 break;
2634                         /* fall through */
2635                 default:
2636                         new = stack_putstr(p, new);
2637                         USTPUTC('/', new);
2638                 }
2639                 p = strtok(NULL, "/");
2640         }
2641         if (new > lim)
2642                 STUNPUTC(new);
2643         *new = 0;
2644         return stackblock();
2645 }
2646
2647 /*
2648  * Find out what the current directory is. If we already know the current
2649  * directory, this routine returns immediately.
2650  */
2651 static char *
2652 getpwd(void)
2653 {
2654         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2655         return dir ? dir : nullstr;
2656 }
2657
2658 static void
2659 setpwd(const char *val, int setold)
2660 {
2661         char *oldcur, *dir;
2662
2663         oldcur = dir = curdir;
2664
2665         if (setold) {
2666                 setvar("OLDPWD", oldcur, VEXPORT);
2667         }
2668         INT_OFF;
2669         if (physdir != nullstr) {
2670                 if (physdir != oldcur)
2671                         free(physdir);
2672                 physdir = nullstr;
2673         }
2674         if (oldcur == val || !val) {
2675                 char *s = getpwd();
2676                 physdir = s;
2677                 if (!val)
2678                         dir = s;
2679         } else
2680                 dir = ckstrdup(val);
2681         if (oldcur != dir && oldcur != nullstr) {
2682                 free(oldcur);
2683         }
2684         curdir = dir;
2685         INT_ON;
2686         setvar("PWD", dir, VEXPORT);
2687 }
2688
2689 static void hashcd(void);
2690
2691 /*
2692  * Actually do the chdir.  We also call hashcd to let other routines
2693  * know that the current directory has changed.
2694  */
2695 static int
2696 docd(const char *dest, int flags)
2697 {
2698         const char *dir = NULL;
2699         int err;
2700
2701         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2702
2703         INT_OFF;
2704         if (!(flags & CD_PHYSICAL)) {
2705                 dir = updatepwd(dest);
2706                 if (dir)
2707                         dest = dir;
2708         }
2709         err = chdir(dest);
2710         if (err)
2711                 goto out;
2712         setpwd(dir, 1);
2713         hashcd();
2714  out:
2715         INT_ON;
2716         return err;
2717 }
2718
2719 static int FAST_FUNC
2720 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2721 {
2722         const char *dest;
2723         const char *path;
2724         const char *p;
2725         char c;
2726         struct stat statb;
2727         int flags;
2728
2729         flags = cdopt();
2730         dest = *argptr;
2731         if (!dest)
2732                 dest = bltinlookup("HOME");
2733         else if (LONE_DASH(dest)) {
2734                 dest = bltinlookup("OLDPWD");
2735                 flags |= CD_PRINT;
2736         }
2737         if (!dest)
2738                 dest = nullstr;
2739         if (*dest == '/')
2740                 goto step6;
2741         if (*dest == '.') {
2742                 c = dest[1];
2743  dotdot:
2744                 switch (c) {
2745                 case '\0':
2746                 case '/':
2747                         goto step6;
2748                 case '.':
2749                         c = dest[2];
2750                         if (c != '.')
2751                                 goto dotdot;
2752                 }
2753         }
2754         if (!*dest)
2755                 dest = ".";
2756         path = bltinlookup("CDPATH");
2757         while (path) {
2758                 c = *path;
2759                 p = path_advance(&path, dest);
2760                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2761                         if (c && c != ':')
2762                                 flags |= CD_PRINT;
2763  docd:
2764                         if (!docd(p, flags))
2765                                 goto out;
2766                         goto err;
2767                 }
2768         }
2769
2770  step6:
2771         p = dest;
2772         goto docd;
2773
2774  err:
2775         ash_msg_and_raise_perror("can't cd to %s", dest);
2776         /* NOTREACHED */
2777  out:
2778         if (flags & CD_PRINT)
2779                 out1fmt("%s\n", curdir);
2780         return 0;
2781 }
2782
2783 static int FAST_FUNC
2784 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2785 {
2786         int flags;
2787         const char *dir = curdir;
2788
2789         flags = cdopt();
2790         if (flags) {
2791                 if (physdir == nullstr)
2792                         setpwd(dir, 0);
2793                 dir = physdir;
2794         }
2795         out1fmt("%s\n", dir);
2796         return 0;
2797 }
2798
2799
2800 /* ============ ... */
2801
2802
2803 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2804
2805 /* Syntax classes */
2806 #define CWORD     0             /* character is nothing special */
2807 #define CNL       1             /* newline character */
2808 #define CBACK     2             /* a backslash character */
2809 #define CSQUOTE   3             /* single quote */
2810 #define CDQUOTE   4             /* double quote */
2811 #define CENDQUOTE 5             /* a terminating quote */
2812 #define CBQUOTE   6             /* backwards single quote */
2813 #define CVAR      7             /* a dollar sign */
2814 #define CENDVAR   8             /* a '}' character */
2815 #define CLP       9             /* a left paren in arithmetic */
2816 #define CRP      10             /* a right paren in arithmetic */
2817 #define CENDFILE 11             /* end of file */
2818 #define CCTL     12             /* like CWORD, except it must be escaped */
2819 #define CSPCL    13             /* these terminate a word */
2820 #define CIGN     14             /* character should be ignored */
2821
2822 #define PEOF     256
2823 #if ENABLE_ASH_ALIAS
2824 # define PEOA    257
2825 #endif
2826
2827 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2828
2829 #if ENABLE_FEATURE_SH_MATH
2830 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2831 #else
2832 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2833 #endif
2834 static const uint16_t S_I_T[] ALIGN2 = {
2835 #if ENABLE_ASH_ALIAS
2836         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2837 #endif
2838         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2839         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2840         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2841         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2842         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2843         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2844         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2845         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2846         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2847         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2848         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2849 #if !USE_SIT_FUNCTION
2850         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2851         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2852         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2853 #endif
2854 #undef SIT_ITEM
2855 };
2856 /* Constants below must match table above */
2857 enum {
2858 #if ENABLE_ASH_ALIAS
2859         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2860 #endif
2861         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2862         CNL_CNL_CNL_CNL                    , /*  2 */
2863         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2864         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2865         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2866         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2867         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2868         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2869         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2870         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2871         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2872         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2873         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2874         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2875 };
2876
2877 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2878  * caller must ensure proper cast on it if c is *char_ptr!
2879  */
2880 #if USE_SIT_FUNCTION
2881
2882 static int
2883 SIT(int c, int syntax)
2884 {
2885         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2886         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2887         /*
2888          * This causes '/' to be prepended with CTLESC in dquoted string,
2889          * making "./file"* treated incorrectly because we feed
2890          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2891          * The "homegrown" glob implementation is okay with that,
2892          * but glibc one isn't. With '/' always treated as CWORD,
2893          * both work fine.
2894          */
2895 # if ENABLE_ASH_ALIAS
2896         static const uint8_t syntax_index_table[] ALIGN1 = {
2897                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2898                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2899                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2900                 11, 3                           /* "}~" */
2901         };
2902 # else
2903         static const uint8_t syntax_index_table[] ALIGN1 = {
2904                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2905                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2906                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2907                 10, 2                           /* "}~" */
2908         };
2909 # endif
2910         const char *s;
2911         int indx;
2912
2913         if (c == PEOF)
2914                 return CENDFILE;
2915 # if ENABLE_ASH_ALIAS
2916         if (c == PEOA)
2917                 indx = 0;
2918         else
2919 # endif
2920         {
2921                 /* Cast is purely for paranoia here,
2922                  * just in case someone passed signed char to us */
2923                 if ((unsigned char)c >= CTL_FIRST
2924                  && (unsigned char)c <= CTL_LAST
2925                 ) {
2926                         return CCTL;
2927                 }
2928                 s = strchrnul(spec_symbls, c);
2929                 if (*s == '\0')
2930                         return CWORD;
2931                 indx = syntax_index_table[s - spec_symbls];
2932         }
2933         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2934 }
2935
2936 #else   /* !USE_SIT_FUNCTION */
2937
2938 static const uint8_t syntax_index_table[] ALIGN1 = {
2939         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2940         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2941         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2942         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2943         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2944         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2945         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2946         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2947         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2948         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2949         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2950         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2951         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2952         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2953         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2954         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2955         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2956         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2957         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2958         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2959         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2960         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2961         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2962         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2963         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2964         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2965         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2966         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2967         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2968         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2969         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2970         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2971         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2972         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2973         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2974         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2975         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2976         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2977         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2979         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2980         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2981         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2982         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2983         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2985         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2986         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2987 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2988         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3000         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3001         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3002         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3003         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3004         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3005         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3006         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3009         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3010         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3011         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3012         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3013         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3014         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3015         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3016         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3017         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3018         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3019         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3020         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3021         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3022         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3023         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3024         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3025         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3026         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3027         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3028         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3029         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3030         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3031         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3032         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3033         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3034         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3035         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3036         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3037         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3038         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3039         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3040         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3041         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3042         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3043         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3044         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3045         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3046         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3047         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3048         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3049         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3050         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3051         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3052         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3053         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3054         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3055         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3056         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3057         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3058         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3059         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3060         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3061         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3062         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3063         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3064         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3065         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3066         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3067         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3068         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3069         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3070         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3071         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3072         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3073         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3074         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3075         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3076         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3077         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3078         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3197         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3198 # if ENABLE_ASH_ALIAS
3199         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3200 # endif
3201 };
3202
3203 #if 1
3204 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3205 #else /* debug version, caught one signed char bug */
3206 # define SIT(c, syntax) \
3207         ({ \
3208                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3209                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3210                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3211                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3212                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3213         })
3214 #endif
3215
3216 #endif  /* !USE_SIT_FUNCTION */
3217
3218
3219 /* ============ Alias handling */
3220
3221 #if ENABLE_ASH_ALIAS
3222
3223 #define ALIASINUSE 1
3224 #define ALIASDEAD  2
3225
3226 struct alias {
3227         struct alias *next;
3228         char *name;
3229         char *val;
3230         int flag;
3231 };
3232
3233
3234 static struct alias **atab; // [ATABSIZE];
3235 #define INIT_G_alias() do { \
3236         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3237 } while (0)
3238
3239
3240 static struct alias **
3241 __lookupalias(const char *name)
3242 {
3243         unsigned int hashval;
3244         struct alias **app;
3245         const char *p;
3246         unsigned int ch;
3247
3248         p = name;
3249
3250         ch = (unsigned char)*p;
3251         hashval = ch << 4;
3252         while (ch) {
3253                 hashval += ch;
3254                 ch = (unsigned char)*++p;
3255         }
3256         app = &atab[hashval % ATABSIZE];
3257
3258         for (; *app; app = &(*app)->next) {
3259                 if (strcmp(name, (*app)->name) == 0) {
3260                         break;
3261                 }
3262         }
3263
3264         return app;
3265 }
3266
3267 static struct alias *
3268 lookupalias(const char *name, int check)
3269 {
3270         struct alias *ap = *__lookupalias(name);
3271
3272         if (check && ap && (ap->flag & ALIASINUSE))
3273                 return NULL;
3274         return ap;
3275 }
3276
3277 static struct alias *
3278 freealias(struct alias *ap)
3279 {
3280         struct alias *next;
3281
3282         if (ap->flag & ALIASINUSE) {
3283                 ap->flag |= ALIASDEAD;
3284                 return ap;
3285         }
3286
3287         next = ap->next;
3288         free(ap->name);
3289         free(ap->val);
3290         free(ap);
3291         return next;
3292 }
3293
3294 static void
3295 setalias(const char *name, const char *val)
3296 {
3297         struct alias *ap, **app;
3298
3299         app = __lookupalias(name);
3300         ap = *app;
3301         INT_OFF;
3302         if (ap) {
3303                 if (!(ap->flag & ALIASINUSE)) {
3304                         free(ap->val);
3305                 }
3306                 ap->val = ckstrdup(val);
3307                 ap->flag &= ~ALIASDEAD;
3308         } else {
3309                 /* not found */
3310                 ap = ckzalloc(sizeof(struct alias));
3311                 ap->name = ckstrdup(name);
3312                 ap->val = ckstrdup(val);
3313                 /*ap->flag = 0; - ckzalloc did it */
3314                 /*ap->next = NULL;*/
3315                 *app = ap;
3316         }
3317         INT_ON;
3318 }
3319
3320 static int
3321 unalias(const char *name)
3322 {
3323         struct alias **app;
3324
3325         app = __lookupalias(name);
3326
3327         if (*app) {
3328                 INT_OFF;
3329                 *app = freealias(*app);
3330                 INT_ON;
3331                 return 0;
3332         }
3333
3334         return 1;
3335 }
3336
3337 static void
3338 rmaliases(void)
3339 {
3340         struct alias *ap, **app;
3341         int i;
3342
3343         INT_OFF;
3344         for (i = 0; i < ATABSIZE; i++) {
3345                 app = &atab[i];
3346                 for (ap = *app; ap; ap = *app) {
3347                         *app = freealias(*app);
3348                         if (ap == *app) {
3349                                 app = &ap->next;
3350                         }
3351                 }
3352         }
3353         INT_ON;
3354 }
3355
3356 static void
3357 printalias(const struct alias *ap)
3358 {
3359         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3360 }
3361
3362 /*
3363  * TODO - sort output
3364  */
3365 static int FAST_FUNC
3366 aliascmd(int argc UNUSED_PARAM, char **argv)
3367 {
3368         char *n, *v;
3369         int ret = 0;
3370         struct alias *ap;
3371
3372         if (!argv[1]) {
3373                 int i;
3374
3375                 for (i = 0; i < ATABSIZE; i++) {
3376                         for (ap = atab[i]; ap; ap = ap->next) {
3377                                 printalias(ap);
3378                         }
3379                 }
3380                 return 0;
3381         }
3382         while ((n = *++argv) != NULL) {
3383                 v = strchr(n+1, '=');
3384                 if (v == NULL) { /* n+1: funny ksh stuff */
3385                         ap = *__lookupalias(n);
3386                         if (ap == NULL) {
3387                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3388                                 ret = 1;
3389                         } else
3390                                 printalias(ap);
3391                 } else {
3392                         *v++ = '\0';
3393                         setalias(n, v);
3394                 }
3395         }
3396
3397         return ret;
3398 }
3399
3400 static int FAST_FUNC
3401 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3402 {
3403         int i;
3404
3405         while (nextopt("a") != '\0') {
3406                 rmaliases();
3407                 return 0;
3408         }
3409         for (i = 0; *argptr; argptr++) {
3410                 if (unalias(*argptr)) {
3411                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3412                         i = 1;
3413                 }
3414         }
3415
3416         return i;
3417 }
3418
3419 #endif /* ASH_ALIAS */
3420
3421
3422 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3423 #define FORK_FG    0
3424 #define FORK_BG    1
3425 #define FORK_NOJOB 2
3426
3427 /* mode flags for showjob(s) */
3428 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3429 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3430 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3431 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3432
3433 /*
3434  * A job structure contains information about a job.  A job is either a
3435  * single process or a set of processes contained in a pipeline.  In the
3436  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3437  * array of pids.
3438  */
3439 struct procstat {
3440         pid_t   ps_pid;         /* process id */
3441         int     ps_status;      /* last process status from wait() */
3442         char    *ps_cmd;        /* text of command being run */
3443 };
3444
3445 struct job {
3446         struct procstat ps0;    /* status of process */
3447         struct procstat *ps;    /* status or processes when more than one */
3448 #if JOBS
3449         int stopstatus;         /* status of a stopped job */
3450 #endif
3451         unsigned nprocs;        /* number of processes */
3452
3453 #define JOBRUNNING      0       /* at least one proc running */
3454 #define JOBSTOPPED      1       /* all procs are stopped */
3455 #define JOBDONE         2       /* all procs are completed */
3456         unsigned
3457                 state: 8,
3458 #if JOBS
3459                 sigint: 1,      /* job was killed by SIGINT */
3460                 jobctl: 1,      /* job running under job control */
3461 #endif
3462                 waited: 1,      /* true if this entry has been waited for */
3463                 used: 1,        /* true if this entry is in used */
3464                 changed: 1;     /* true if status has changed */
3465         struct job *prev_job;   /* previous job */
3466 };
3467
3468 static struct job *makejob(/*union node *,*/ int);
3469 static int forkshell(struct job *, union node *, int);
3470 static int waitforjob(struct job *);
3471
3472 #if !JOBS
3473 enum { doing_jobctl = 0 };
3474 #define setjobctl(on) do {} while (0)
3475 #else
3476 static smallint doing_jobctl; //references:8
3477 static void setjobctl(int);
3478 #endif
3479
3480 /*
3481  * Ignore a signal.
3482  */
3483 static void
3484 ignoresig(int signo)
3485 {
3486         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3487         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3488                 /* No, need to do it */
3489                 signal(signo, SIG_IGN);
3490         }
3491         sigmode[signo - 1] = S_HARD_IGN;
3492 }
3493
3494 /*
3495  * Only one usage site - in setsignal()
3496  */
3497 static void
3498 signal_handler(int signo)
3499 {
3500         if (signo == SIGCHLD) {
3501                 got_sigchld = 1;
3502                 if (!trap[SIGCHLD])
3503                         return;
3504         }
3505
3506         gotsig[signo - 1] = 1;
3507         pending_sig = signo;
3508
3509         if (signo == SIGINT && !trap[SIGINT]) {
3510                 if (!suppress_int) {
3511                         pending_sig = 0;
3512                         raise_interrupt(); /* does not return */
3513                 }
3514                 pending_int = 1;
3515         }
3516 }
3517
3518 /*
3519  * Set the signal handler for the specified signal.  The routine figures
3520  * out what it should be set to.
3521  */
3522 static void
3523 setsignal(int signo)
3524 {
3525         char *t;
3526         char cur_act, new_act;
3527         struct sigaction act;
3528
3529         t = trap[signo];
3530         new_act = S_DFL;
3531         if (t != NULL) { /* trap for this sig is set */
3532                 new_act = S_CATCH;
3533                 if (t[0] == '\0') /* trap is "": ignore this sig */
3534                         new_act = S_IGN;
3535         }
3536
3537         if (rootshell && new_act == S_DFL) {
3538                 switch (signo) {
3539                 case SIGINT:
3540                         if (iflag || minusc || sflag == 0)
3541                                 new_act = S_CATCH;
3542                         break;
3543                 case SIGQUIT:
3544 #if DEBUG
3545                         if (debug)
3546                                 break;
3547 #endif
3548                         /* man bash:
3549                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3550                          * commands run by bash have signal handlers
3551                          * set to the values inherited by the shell
3552                          * from its parent". */
3553                         new_act = S_IGN;
3554                         break;
3555                 case SIGTERM:
3556                         if (iflag)
3557                                 new_act = S_IGN;
3558                         break;
3559 #if JOBS
3560                 case SIGTSTP:
3561                 case SIGTTOU:
3562                         if (mflag)
3563                                 new_act = S_IGN;
3564                         break;
3565 #endif
3566                 }
3567         }
3568         /* if !rootshell, we reset SIGQUIT to DFL,
3569          * whereas we have to restore it to what shell got on entry.
3570          * This is handled by the fact that if signal was IGNored on entry,
3571          * then cur_act is S_HARD_IGN and we never change its sigaction
3572          * (see code below).
3573          */
3574
3575         if (signo == SIGCHLD)
3576                 new_act = S_CATCH;
3577
3578         t = &sigmode[signo - 1];
3579         cur_act = *t;
3580         if (cur_act == 0) {
3581                 /* current setting is not yet known */
3582                 if (sigaction(signo, NULL, &act)) {
3583                         /* pretend it worked; maybe we should give a warning,
3584                          * but other shells don't. We don't alter sigmode,
3585                          * so we retry every time.
3586                          * btw, in Linux it never fails. --vda */
3587                         return;
3588                 }
3589                 if (act.sa_handler == SIG_IGN) {
3590                         cur_act = S_HARD_IGN;
3591                         if (mflag
3592                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3593                         ) {
3594                                 cur_act = S_IGN;   /* don't hard ignore these */
3595                         }
3596                 }
3597                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3598                         /* installing SIG_DFL over SIG_DFL is a no-op */
3599                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3600                         *t = S_DFL;
3601                         return;
3602                 }
3603         }
3604         if (cur_act == S_HARD_IGN || cur_act == new_act)
3605                 return;
3606
3607         *t = new_act;
3608
3609         act.sa_handler = SIG_DFL;
3610         switch (new_act) {
3611         case S_CATCH:
3612                 act.sa_handler = signal_handler;
3613                 break;
3614         case S_IGN:
3615                 act.sa_handler = SIG_IGN;
3616                 break;
3617         }
3618         /* flags and mask matter only if !DFL and !IGN, but we do it
3619          * for all cases for more deterministic behavior:
3620          */
3621         act.sa_flags = 0; //TODO: why not SA_RESTART?
3622         sigfillset(&act.sa_mask);
3623
3624         sigaction_set(signo, &act);
3625 }
3626
3627 /* mode flags for set_curjob */
3628 #define CUR_DELETE 2
3629 #define CUR_RUNNING 1
3630 #define CUR_STOPPED 0
3631
3632 #if JOBS
3633 /* pgrp of shell on invocation */
3634 static int initialpgrp; //references:2
3635 static int ttyfd = -1; //5
3636 #endif
3637 /* array of jobs */
3638 static struct job *jobtab; //5
3639 /* size of array */
3640 static unsigned njobs; //4
3641 /* current job */
3642 static struct job *curjob; //lots
3643 /* number of presumed living untracked jobs */
3644 static int jobless; //4
3645
3646 #if 0
3647 /* Bash has a feature: it restores termios after a successful wait for
3648  * a foreground job which had at least one stopped or sigkilled member.
3649  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3650  * properly restoring tty state. Should we do this too?
3651  * A reproducer: ^Z an interactive python:
3652  *
3653  * # python
3654  * Python 2.7.12 (...)
3655  * >>> ^Z
3656  *      { python leaves tty in -icanon -echo state. We do survive that... }
3657  *  [1]+  Stopped                    python
3658  *      { ...however, next program (python #2) does not survive it well: }
3659  * # python
3660  * Python 2.7.12 (...)
3661  * >>> Traceback (most recent call last):
3662  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3663  *   File "<stdin>", line 1, in <module>
3664  * NameError: name 'qwerty' is not defined
3665  *
3666  * The implementation below is modeled on bash code and seems to work.
3667  * However, I'm not sure we should do this. For one: what if I'd fg
3668  * the stopped python instead? It'll be confused by "restored" tty state.
3669  */
3670 static struct termios shell_tty_info;
3671 static void
3672 get_tty_state(void)
3673 {
3674         if (rootshell && ttyfd >= 0)
3675                 tcgetattr(ttyfd, &shell_tty_info);
3676 }
3677 static void
3678 set_tty_state(void)
3679 {
3680         /* if (rootshell) - caller ensures this */
3681         if (ttyfd >= 0)
3682                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3683 }
3684 static int
3685 job_signal_status(struct job *jp)
3686 {
3687         int status;
3688         unsigned i;
3689         struct procstat *ps = jp->ps;
3690         for (i = 0; i < jp->nprocs; i++) {
3691                 status = ps[i].ps_status;
3692                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3693                         return status;
3694         }
3695         return 0;
3696 }
3697 static void
3698 restore_tty_if_stopped_or_signaled(struct job *jp)
3699 {
3700 //TODO: check what happens if we come from waitforjob() in expbackq()
3701         if (rootshell) {
3702                 int s = job_signal_status(jp);
3703                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3704                         set_tty_state();
3705         }
3706 }
3707 #else
3708 # define get_tty_state() ((void)0)
3709 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3710 #endif
3711
3712 static void
3713 set_curjob(struct job *jp, unsigned mode)
3714 {
3715         struct job *jp1;
3716         struct job **jpp, **curp;
3717
3718         /* first remove from list */
3719         jpp = curp = &curjob;
3720         while (1) {
3721                 jp1 = *jpp;
3722                 if (jp1 == jp)
3723                         break;
3724                 jpp = &jp1->prev_job;
3725         }
3726         *jpp = jp1->prev_job;
3727
3728         /* Then re-insert in correct position */
3729         jpp = curp;
3730         switch (mode) {
3731         default:
3732 #if DEBUG
3733                 abort();
3734 #endif
3735         case CUR_DELETE:
3736                 /* job being deleted */
3737                 break;
3738         case CUR_RUNNING:
3739                 /* newly created job or backgrounded job,
3740                  * put after all stopped jobs.
3741                  */
3742                 while (1) {
3743                         jp1 = *jpp;
3744 #if JOBS
3745                         if (!jp1 || jp1->state != JOBSTOPPED)
3746 #endif
3747                                 break;
3748                         jpp = &jp1->prev_job;
3749                 }
3750                 /* FALLTHROUGH */
3751 #if JOBS
3752         case CUR_STOPPED:
3753 #endif
3754                 /* newly stopped job - becomes curjob */
3755                 jp->prev_job = *jpp;
3756                 *jpp = jp;
3757                 break;
3758         }
3759 }
3760
3761 #if JOBS || DEBUG
3762 static int
3763 jobno(const struct job *jp)
3764 {
3765         return jp - jobtab + 1;
3766 }
3767 #endif
3768
3769 /*
3770  * Convert a job name to a job structure.
3771  */
3772 #if !JOBS
3773 #define getjob(name, getctl) getjob(name)
3774 #endif
3775 static struct job *
3776 getjob(const char *name, int getctl)
3777 {
3778         struct job *jp;
3779         struct job *found;
3780         const char *err_msg = "%s: no such job";
3781         unsigned num;
3782         int c;
3783         const char *p;
3784         char *(*match)(const char *, const char *);
3785
3786         jp = curjob;
3787         p = name;
3788         if (!p)
3789                 goto currentjob;
3790
3791         if (*p != '%')
3792                 goto err;
3793
3794         c = *++p;
3795         if (!c)
3796                 goto currentjob;
3797
3798         if (!p[1]) {
3799                 if (c == '+' || c == '%') {
3800  currentjob:
3801                         err_msg = "No current job";
3802                         goto check;
3803                 }
3804                 if (c == '-') {
3805                         if (jp)
3806                                 jp = jp->prev_job;
3807                         err_msg = "No previous job";
3808  check:
3809                         if (!jp)
3810                                 goto err;
3811                         goto gotit;
3812                 }
3813         }
3814
3815         if (is_number(p)) {
3816                 num = atoi(p);
3817                 if (num > 0 && num <= njobs) {
3818                         jp = jobtab + num - 1;
3819                         if (jp->used)
3820                                 goto gotit;
3821                         goto err;
3822                 }
3823         }
3824
3825         match = prefix;
3826         if (*p == '?') {
3827                 match = strstr;
3828                 p++;
3829         }
3830
3831         found = NULL;
3832         while (jp) {
3833                 if (match(jp->ps[0].ps_cmd, p)) {
3834                         if (found)
3835                                 goto err;
3836                         found = jp;
3837                         err_msg = "%s: ambiguous";
3838                 }
3839                 jp = jp->prev_job;
3840         }
3841         if (!found)
3842                 goto err;
3843         jp = found;
3844
3845  gotit:
3846 #if JOBS
3847         err_msg = "job %s not created under job control";
3848         if (getctl && jp->jobctl == 0)
3849                 goto err;
3850 #endif
3851         return jp;
3852  err:
3853         ash_msg_and_raise_error(err_msg, name);
3854 }
3855
3856 /*
3857  * Mark a job structure as unused.
3858  */
3859 static void
3860 freejob(struct job *jp)
3861 {
3862         struct procstat *ps;
3863         int i;
3864
3865         INT_OFF;
3866         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3867                 if (ps->ps_cmd != nullstr)
3868                         free(ps->ps_cmd);
3869         }
3870         if (jp->ps != &jp->ps0)
3871                 free(jp->ps);
3872         jp->used = 0;
3873         set_curjob(jp, CUR_DELETE);
3874         INT_ON;
3875 }
3876
3877 #if JOBS
3878 static void
3879 xtcsetpgrp(int fd, pid_t pgrp)
3880 {
3881         if (tcsetpgrp(fd, pgrp))
3882                 ash_msg_and_raise_perror("can't set tty process group");
3883 }
3884
3885 /*
3886  * Turn job control on and off.
3887  *
3888  * Note:  This code assumes that the third arg to ioctl is a character
3889  * pointer, which is true on Berkeley systems but not System V.  Since
3890  * System V doesn't have job control yet, this isn't a problem now.
3891  *
3892  * Called with interrupts off.
3893  */
3894 static void
3895 setjobctl(int on)
3896 {
3897         int fd;
3898         int pgrp;
3899
3900         if (on == doing_jobctl || rootshell == 0)
3901                 return;
3902         if (on) {
3903                 int ofd;
3904                 ofd = fd = open(_PATH_TTY, O_RDWR);
3905                 if (fd < 0) {
3906         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3907          * That sometimes helps to acquire controlling tty.
3908          * Obviously, a workaround for bugs when someone
3909          * failed to provide a controlling tty to bash! :) */
3910                         fd = 2;
3911                         while (!isatty(fd))
3912                                 if (--fd < 0)
3913                                         goto out;
3914                 }
3915                 /* fd is a tty at this point */
3916                 fd = fcntl(fd, F_DUPFD, 10);
3917                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3918                         close(ofd);
3919                 if (fd < 0)
3920                         goto out; /* F_DUPFD failed */
3921                 close_on_exec_on(fd);
3922                 while (1) { /* while we are in the background */
3923                         pgrp = tcgetpgrp(fd);
3924                         if (pgrp < 0) {
3925  out:
3926                                 ash_msg("can't access tty; job control turned off");
3927                                 mflag = on = 0;
3928                                 goto close;
3929                         }
3930                         if (pgrp == getpgrp())
3931                                 break;
3932                         killpg(0, SIGTTIN);
3933                 }
3934                 initialpgrp = pgrp;
3935
3936                 setsignal(SIGTSTP);
3937                 setsignal(SIGTTOU);
3938                 setsignal(SIGTTIN);
3939                 pgrp = rootpid;
3940                 setpgid(0, pgrp);
3941                 xtcsetpgrp(fd, pgrp);
3942         } else {
3943                 /* turning job control off */
3944                 fd = ttyfd;
3945                 pgrp = initialpgrp;
3946                 /* was xtcsetpgrp, but this can make exiting ash
3947                  * loop forever if pty is already deleted */
3948                 tcsetpgrp(fd, pgrp);
3949                 setpgid(0, pgrp);
3950                 setsignal(SIGTSTP);
3951                 setsignal(SIGTTOU);
3952                 setsignal(SIGTTIN);
3953  close:
3954                 if (fd >= 0)
3955                         close(fd);
3956                 fd = -1;
3957         }
3958         ttyfd = fd;
3959         doing_jobctl = on;
3960 }
3961
3962 static int FAST_FUNC
3963 killcmd(int argc, char **argv)
3964 {
3965         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3966                 int i = 1;
3967                 do {
3968                         if (argv[i][0] == '%') {
3969                                 /*
3970                                  * "kill %N" - job kill
3971                                  * Converting to pgrp / pid kill
3972                                  */
3973                                 struct job *jp;
3974                                 char *dst;
3975                                 int j, n;
3976
3977                                 jp = getjob(argv[i], 0);
3978                                 /*
3979                                  * In jobs started under job control, we signal
3980                                  * entire process group by kill -PGRP_ID.
3981                                  * This happens, f.e., in interactive shell.
3982                                  *
3983                                  * Otherwise, we signal each child via
3984                                  * kill PID1 PID2 PID3.
3985                                  * Testcases:
3986                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3987                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3988                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3989                                  */
3990                                 n = jp->nprocs; /* can't be 0 (I hope) */
3991                                 if (jp->jobctl)
3992                                         n = 1;
3993                                 dst = alloca(n * sizeof(int)*4);
3994                                 argv[i] = dst;
3995                                 for (j = 0; j < n; j++) {
3996                                         struct procstat *ps = &jp->ps[j];
3997                                         /* Skip non-running and not-stopped members
3998                                          * (i.e. dead members) of the job
3999                                          */
4000                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4001                                                 continue;
4002                                         /*
4003                                          * kill_main has matching code to expect
4004                                          * leading space. Needed to not confuse
4005                                          * negative pids with "kill -SIGNAL_NO" syntax
4006                                          */
4007                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4008                                 }
4009                                 *dst = '\0';
4010                         }
4011                 } while (argv[++i]);
4012         }
4013         return kill_main(argc, argv);
4014 }
4015
4016 static void
4017 showpipe(struct job *jp /*, FILE *out*/)
4018 {
4019         struct procstat *ps;
4020         struct procstat *psend;
4021
4022         psend = jp->ps + jp->nprocs;
4023         for (ps = jp->ps + 1; ps < psend; ps++)
4024                 printf(" | %s", ps->ps_cmd);
4025         newline_and_flush(stdout);
4026         flush_stdout_stderr();
4027 }
4028
4029
4030 static int
4031 restartjob(struct job *jp, int mode)
4032 {
4033         struct procstat *ps;
4034         int i;
4035         int status;
4036         pid_t pgid;
4037
4038         INT_OFF;
4039         if (jp->state == JOBDONE)
4040                 goto out;
4041         jp->state = JOBRUNNING;
4042         pgid = jp->ps[0].ps_pid;
4043         if (mode == FORK_FG) {
4044                 get_tty_state();
4045                 xtcsetpgrp(ttyfd, pgid);
4046         }
4047         killpg(pgid, SIGCONT);
4048         ps = jp->ps;
4049         i = jp->nprocs;
4050         do {
4051                 if (WIFSTOPPED(ps->ps_status)) {
4052                         ps->ps_status = -1;
4053                 }
4054                 ps++;
4055         } while (--i);
4056  out:
4057         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4058         INT_ON;
4059         return status;
4060 }
4061
4062 static int FAST_FUNC
4063 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4064 {
4065         struct job *jp;
4066         int mode;
4067         int retval;
4068
4069         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4070         nextopt(nullstr);
4071         argv = argptr;
4072         do {
4073                 jp = getjob(*argv, 1);
4074                 if (mode == FORK_BG) {
4075                         set_curjob(jp, CUR_RUNNING);
4076                         printf("[%d] ", jobno(jp));
4077                 }
4078                 out1str(jp->ps[0].ps_cmd);
4079                 showpipe(jp /*, stdout*/);
4080                 retval = restartjob(jp, mode);
4081         } while (*argv && *++argv);
4082         return retval;
4083 }
4084 #endif
4085
4086 static int
4087 sprint_status48(char *s, int status, int sigonly)
4088 {
4089         int col;
4090         int st;
4091
4092         col = 0;
4093         if (!WIFEXITED(status)) {
4094 #if JOBS
4095                 if (WIFSTOPPED(status))
4096                         st = WSTOPSIG(status);
4097                 else
4098 #endif
4099                         st = WTERMSIG(status);
4100                 if (sigonly) {
4101                         if (st == SIGINT || st == SIGPIPE)
4102                                 goto out;
4103 #if JOBS
4104                         if (WIFSTOPPED(status))
4105                                 goto out;
4106 #endif
4107                 }
4108                 st &= 0x7f;
4109 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4110                 col = fmtstr(s, 32, strsignal(st));
4111                 if (WCOREDUMP(status)) {
4112                         strcpy(s + col, " (core dumped)");
4113                         col += sizeof(" (core dumped)")-1;
4114                 }
4115         } else if (!sigonly) {
4116                 st = WEXITSTATUS(status);
4117                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4118         }
4119  out:
4120         return col;
4121 }
4122
4123 static int
4124 wait_block_or_sig(int *status)
4125 {
4126         int pid;
4127
4128         do {
4129                 sigset_t mask;
4130
4131                 /* Poll all children for changes in their state */
4132                 got_sigchld = 0;
4133                 /* if job control is active, accept stopped processes too */
4134                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4135                 if (pid != 0)
4136                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4137
4138                 /* Children exist, but none are ready. Sleep until interesting signal */
4139 #if 1
4140                 sigfillset(&mask);
4141                 sigprocmask(SIG_SETMASK, &mask, &mask);
4142                 while (!got_sigchld && !pending_sig)
4143                         sigsuspend(&mask);
4144                 sigprocmask(SIG_SETMASK, &mask, NULL);
4145 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4146                 while (!got_sigchld && !pending_sig)
4147                         pause();
4148 #endif
4149
4150                 /* If it was SIGCHLD, poll children again */
4151         } while (got_sigchld);
4152
4153         return pid;
4154 }
4155
4156 #define DOWAIT_NONBLOCK 0
4157 #define DOWAIT_BLOCK    1
4158 #define DOWAIT_BLOCK_OR_SIG 2
4159
4160 static int
4161 dowait(int block, struct job *job)
4162 {
4163         int pid;
4164         int status;
4165         struct job *jp;
4166         struct job *thisjob = NULL;
4167
4168         TRACE(("dowait(0x%x) called\n", block));
4169
4170         /* It's wrong to call waitpid() outside of INT_OFF region:
4171          * signal can arrive just after syscall return and handler can
4172          * longjmp away, losing stop/exit notification processing.
4173          * Thus, for "jobs" builtin, and for waiting for a fg job,
4174          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4175          *
4176          * However, for "wait" builtin it is wrong to simply call waitpid()
4177          * in INT_OFF region: "wait" needs to wait for any running job
4178          * to change state, but should exit on any trap too.
4179          * In INT_OFF region, a signal just before syscall entry can set
4180          * pending_sig variables, but we can't check them, and we would
4181          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4182          *
4183          * Because of this, we run inside INT_OFF, but use a special routine
4184          * which combines waitpid() and sigsuspend().
4185          * This is the reason why we need to have a handler for SIGCHLD:
4186          * SIG_DFL handler does not wake sigsuspend().
4187          */
4188         INT_OFF;
4189         if (block == DOWAIT_BLOCK_OR_SIG) {
4190                 pid = wait_block_or_sig(&status);
4191         } else {
4192                 int wait_flags = 0;
4193                 if (block == DOWAIT_NONBLOCK)
4194                         wait_flags = WNOHANG;
4195                 /* if job control is active, accept stopped processes too */
4196                 if (doing_jobctl)
4197                         wait_flags |= WUNTRACED;
4198                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4199                 pid = waitpid(-1, &status, wait_flags);
4200         }
4201         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4202                                 pid, status, errno, strerror(errno)));
4203         if (pid <= 0)
4204                 goto out;
4205
4206         thisjob = NULL;
4207         for (jp = curjob; jp; jp = jp->prev_job) {
4208                 int jobstate;
4209                 struct procstat *ps;
4210                 struct procstat *psend;
4211                 if (jp->state == JOBDONE)
4212                         continue;
4213                 jobstate = JOBDONE;
4214                 ps = jp->ps;
4215                 psend = ps + jp->nprocs;
4216                 do {
4217                         if (ps->ps_pid == pid) {
4218                                 TRACE(("Job %d: changing status of proc %d "
4219                                         "from 0x%x to 0x%x\n",
4220                                         jobno(jp), pid, ps->ps_status, status));
4221                                 ps->ps_status = status;
4222                                 thisjob = jp;
4223                         }
4224                         if (ps->ps_status == -1)
4225                                 jobstate = JOBRUNNING;
4226 #if JOBS
4227                         if (jobstate == JOBRUNNING)
4228                                 continue;
4229                         if (WIFSTOPPED(ps->ps_status)) {
4230                                 jp->stopstatus = ps->ps_status;
4231                                 jobstate = JOBSTOPPED;
4232                         }
4233 #endif
4234                 } while (++ps < psend);
4235                 if (!thisjob)
4236                         continue;
4237
4238                 /* Found the job where one of its processes changed its state.
4239                  * Is there at least one live and running process in this job? */
4240                 if (jobstate != JOBRUNNING) {
4241                         /* No. All live processes in the job are stopped
4242                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4243                          */
4244                         thisjob->changed = 1;
4245                         if (thisjob->state != jobstate) {
4246                                 TRACE(("Job %d: changing state from %d to %d\n",
4247                                         jobno(thisjob), thisjob->state, jobstate));
4248                                 thisjob->state = jobstate;
4249 #if JOBS
4250                                 if (jobstate == JOBSTOPPED)
4251                                         set_curjob(thisjob, CUR_STOPPED);
4252 #endif
4253                         }
4254                 }
4255                 goto out;
4256         }
4257         /* The process wasn't found in job list */
4258 #if JOBS
4259         if (!WIFSTOPPED(status))
4260                 jobless--;
4261 #endif
4262  out:
4263         INT_ON;
4264
4265         if (thisjob && thisjob == job) {
4266                 char s[48 + 1];
4267                 int len;
4268
4269                 len = sprint_status48(s, status, 1);
4270                 if (len) {
4271                         s[len] = '\n';
4272                         s[len + 1] = '\0';
4273                         out2str(s);
4274                 }
4275         }
4276         return pid;
4277 }
4278
4279 #if JOBS
4280 static void
4281 showjob(struct job *jp, int mode)
4282 {
4283         struct procstat *ps;
4284         struct procstat *psend;
4285         int col;
4286         int indent_col;
4287         char s[16 + 16 + 48];
4288         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4289
4290         ps = jp->ps;
4291
4292         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4293                 /* just output process (group) id of pipeline */
4294                 fprintf(out, "%d\n", ps->ps_pid);
4295                 return;
4296         }
4297
4298         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4299         indent_col = col;
4300
4301         if (jp == curjob)
4302                 s[col - 3] = '+';
4303         else if (curjob && jp == curjob->prev_job)
4304                 s[col - 3] = '-';
4305
4306         if (mode & SHOW_PIDS)
4307                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4308
4309         psend = ps + jp->nprocs;
4310
4311         if (jp->state == JOBRUNNING) {
4312                 strcpy(s + col, "Running");
4313                 col += sizeof("Running") - 1;
4314         } else {
4315                 int status = psend[-1].ps_status;
4316                 if (jp->state == JOBSTOPPED)
4317                         status = jp->stopstatus;
4318                 col += sprint_status48(s + col, status, 0);
4319         }
4320         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4321
4322         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4323          * or prints several "PID             | <cmdN>" lines,
4324          * depending on SHOW_PIDS bit.
4325          * We do not print status of individual processes
4326          * between PID and <cmdN>. bash does it, but not very well:
4327          * first line shows overall job status, not process status,
4328          * making it impossible to know 1st process status.
4329          */
4330         goto start;
4331         do {
4332                 /* for each process */
4333                 s[0] = '\0';
4334                 col = 33;
4335                 if (mode & SHOW_PIDS)
4336                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4337  start:
4338                 fprintf(out, "%s%*c%s%s",
4339                                 s,
4340                                 33 - col >= 0 ? 33 - col : 0, ' ',
4341                                 ps == jp->ps ? "" : "| ",
4342                                 ps->ps_cmd
4343                 );
4344         } while (++ps != psend);
4345         newline_and_flush(out);
4346
4347         jp->changed = 0;
4348
4349         if (jp->state == JOBDONE) {
4350                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4351                 freejob(jp);
4352         }
4353 }
4354
4355 /*
4356  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4357  * statuses have changed since the last call to showjobs.
4358  */
4359 static void
4360 showjobs(int mode)
4361 {
4362         struct job *jp;
4363
4364         TRACE(("showjobs(0x%x) called\n", mode));
4365
4366         /* Handle all finished jobs */
4367         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4368                 continue;
4369
4370         for (jp = curjob; jp; jp = jp->prev_job) {
4371                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4372                         showjob(jp, mode);
4373                 }
4374         }
4375 }
4376
4377 static int FAST_FUNC
4378 jobscmd(int argc UNUSED_PARAM, char **argv)
4379 {
4380         int mode, m;
4381
4382         mode = 0;
4383         while ((m = nextopt("lp")) != '\0') {
4384                 if (m == 'l')
4385                         mode |= SHOW_PIDS;
4386                 else
4387                         mode |= SHOW_ONLY_PGID;
4388         }
4389
4390         argv = argptr;
4391         if (*argv) {
4392                 do
4393                         showjob(getjob(*argv, 0), mode);
4394                 while (*++argv);
4395         } else {
4396                 showjobs(mode);
4397         }
4398
4399         return 0;
4400 }
4401 #endif /* JOBS */
4402
4403 /* Called only on finished or stopped jobs (no members are running) */
4404 static int
4405 getstatus(struct job *job)
4406 {
4407         int status;
4408         int retval;
4409         struct procstat *ps;
4410
4411         /* Fetch last member's status */
4412         ps = job->ps + job->nprocs - 1;
4413         status = ps->ps_status;
4414         if (pipefail) {
4415                 /* "set -o pipefail" mode: use last _nonzero_ status */
4416                 while (status == 0 && --ps >= job->ps)
4417                         status = ps->ps_status;
4418         }
4419
4420         retval = WEXITSTATUS(status);
4421         if (!WIFEXITED(status)) {
4422 #if JOBS
4423                 retval = WSTOPSIG(status);
4424                 if (!WIFSTOPPED(status))
4425 #endif
4426                 {
4427                         /* XXX: limits number of signals */
4428                         retval = WTERMSIG(status);
4429 #if JOBS
4430                         if (retval == SIGINT)
4431                                 job->sigint = 1;
4432 #endif
4433                 }
4434                 retval += 128;
4435         }
4436         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4437                 jobno(job), job->nprocs, status, retval));
4438         return retval;
4439 }
4440
4441 static int FAST_FUNC
4442 waitcmd(int argc UNUSED_PARAM, char **argv)
4443 {
4444         struct job *job;
4445         int retval;
4446         struct job *jp;
4447
4448         nextopt(nullstr);
4449         retval = 0;
4450
4451         argv = argptr;
4452         if (!*argv) {
4453                 /* wait for all jobs */
4454                 for (;;) {
4455                         jp = curjob;
4456                         while (1) {
4457                                 if (!jp) /* no running procs */
4458                                         goto ret;
4459                                 if (jp->state == JOBRUNNING)
4460                                         break;
4461                                 jp->waited = 1;
4462                                 jp = jp->prev_job;
4463                         }
4464         /* man bash:
4465          * "When bash is waiting for an asynchronous command via
4466          * the wait builtin, the reception of a signal for which a trap
4467          * has been set will cause the wait builtin to return immediately
4468          * with an exit status greater than 128, immediately after which
4469          * the trap is executed."
4470          */
4471                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4472         /* if child sends us a signal *and immediately exits*,
4473          * dowait() returns pid > 0. Check this case,
4474          * not "if (dowait() < 0)"!
4475          */
4476                         if (pending_sig)
4477                                 goto sigout;
4478                 }
4479         }
4480
4481         retval = 127;
4482         do {
4483                 if (**argv != '%') {
4484                         pid_t pid = number(*argv);
4485                         job = curjob;
4486                         while (1) {
4487                                 if (!job)
4488                                         goto repeat;
4489                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4490                                         break;
4491                                 job = job->prev_job;
4492                         }
4493                 } else {
4494                         job = getjob(*argv, 0);
4495                 }
4496                 /* loop until process terminated or stopped */
4497                 while (job->state == JOBRUNNING) {
4498                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4499                         if (pending_sig)
4500                                 goto sigout;
4501                 }
4502                 job->waited = 1;
4503                 retval = getstatus(job);
4504  repeat: ;
4505         } while (*++argv);
4506
4507  ret:
4508         return retval;
4509  sigout:
4510         retval = 128 + pending_sig;
4511         return retval;
4512 }
4513
4514 static struct job *
4515 growjobtab(void)
4516 {
4517         size_t len;
4518         ptrdiff_t offset;
4519         struct job *jp, *jq;
4520
4521         len = njobs * sizeof(*jp);
4522         jq = jobtab;
4523         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4524
4525         offset = (char *)jp - (char *)jq;
4526         if (offset) {
4527                 /* Relocate pointers */
4528                 size_t l = len;
4529
4530                 jq = (struct job *)((char *)jq + l);
4531                 while (l) {
4532                         l -= sizeof(*jp);
4533                         jq--;
4534 #define joff(p) ((struct job *)((char *)(p) + l))
4535 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4536                         if (joff(jp)->ps == &jq->ps0)
4537                                 jmove(joff(jp)->ps);
4538                         if (joff(jp)->prev_job)
4539                                 jmove(joff(jp)->prev_job);
4540                 }
4541                 if (curjob)
4542                         jmove(curjob);
4543 #undef joff
4544 #undef jmove
4545         }
4546
4547         njobs += 4;
4548         jobtab = jp;
4549         jp = (struct job *)((char *)jp + len);
4550         jq = jp + 3;
4551         do {
4552                 jq->used = 0;
4553         } while (--jq >= jp);
4554         return jp;
4555 }
4556
4557 /*
4558  * Return a new job structure.
4559  * Called with interrupts off.
4560  */
4561 static struct job *
4562 makejob(/*union node *node,*/ int nprocs)
4563 {
4564         int i;
4565         struct job *jp;
4566
4567         for (i = njobs, jp = jobtab; ; jp++) {
4568                 if (--i < 0) {
4569                         jp = growjobtab();
4570                         break;
4571                 }
4572                 if (jp->used == 0)
4573                         break;
4574                 if (jp->state != JOBDONE || !jp->waited)
4575                         continue;
4576 #if JOBS
4577                 if (doing_jobctl)
4578                         continue;
4579 #endif
4580                 freejob(jp);
4581                 break;
4582         }
4583         memset(jp, 0, sizeof(*jp));
4584 #if JOBS
4585         /* jp->jobctl is a bitfield.
4586          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4587         if (doing_jobctl)
4588                 jp->jobctl = 1;
4589 #endif
4590         jp->prev_job = curjob;
4591         curjob = jp;
4592         jp->used = 1;
4593         jp->ps = &jp->ps0;
4594         if (nprocs > 1) {
4595                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4596         }
4597         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4598                                 jobno(jp)));
4599         return jp;
4600 }
4601
4602 #if JOBS
4603 /*
4604  * Return a string identifying a command (to be printed by the
4605  * jobs command).
4606  */
4607 static char *cmdnextc;
4608
4609 static void
4610 cmdputs(const char *s)
4611 {
4612         static const char vstype[VSTYPE + 1][3] = {
4613                 "", "}", "-", "+", "?", "=",
4614                 "%", "%%", "#", "##"
4615                 IF_BASH_SUBSTR(, ":")
4616                 IF_BASH_PATTERN_SUBST(, "/", "//")
4617         };
4618
4619         const char *p, *str;
4620         char cc[2];
4621         char *nextc;
4622         unsigned char c;
4623         unsigned char subtype = 0;
4624         int quoted = 0;
4625
4626         cc[1] = '\0';
4627         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4628         p = s;
4629         while ((c = *p++) != '\0') {
4630                 str = NULL;
4631                 switch (c) {
4632                 case CTLESC:
4633                         c = *p++;
4634                         break;
4635                 case CTLVAR:
4636                         subtype = *p++;
4637                         if ((subtype & VSTYPE) == VSLENGTH)
4638                                 str = "${#";
4639                         else
4640                                 str = "${";
4641                         goto dostr;
4642                 case CTLENDVAR:
4643                         str = "\"}" + !(quoted & 1);
4644                         quoted >>= 1;
4645                         subtype = 0;
4646                         goto dostr;
4647                 case CTLBACKQ:
4648                         str = "$(...)";
4649                         goto dostr;
4650 #if ENABLE_FEATURE_SH_MATH
4651                 case CTLARI:
4652                         str = "$((";
4653                         goto dostr;
4654                 case CTLENDARI:
4655                         str = "))";
4656                         goto dostr;
4657 #endif
4658                 case CTLQUOTEMARK:
4659                         quoted ^= 1;
4660                         c = '"';
4661                         break;
4662                 case '=':
4663                         if (subtype == 0)
4664                                 break;
4665                         if ((subtype & VSTYPE) != VSNORMAL)
4666                                 quoted <<= 1;
4667                         str = vstype[subtype & VSTYPE];
4668                         if (subtype & VSNUL)
4669                                 c = ':';
4670                         else
4671                                 goto checkstr;
4672                         break;
4673                 case '\'':
4674                 case '\\':
4675                 case '"':
4676                 case '$':
4677                         /* These can only happen inside quotes */
4678                         cc[0] = c;
4679                         str = cc;
4680 //FIXME:
4681 // $ true $$ &
4682 // $ <cr>
4683 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4684                         c = '\\';
4685                         break;
4686                 default:
4687                         break;
4688                 }
4689                 USTPUTC(c, nextc);
4690  checkstr:
4691                 if (!str)
4692                         continue;
4693  dostr:
4694                 while ((c = *str++) != '\0') {
4695                         USTPUTC(c, nextc);
4696                 }
4697         } /* while *p++ not NUL */
4698
4699         if (quoted & 1) {
4700                 USTPUTC('"', nextc);
4701         }
4702         *nextc = 0;
4703         cmdnextc = nextc;
4704 }
4705
4706 /* cmdtxt() and cmdlist() call each other */
4707 static void cmdtxt(union node *n);
4708
4709 static void
4710 cmdlist(union node *np, int sep)
4711 {
4712         for (; np; np = np->narg.next) {
4713                 if (!sep)
4714                         cmdputs(" ");
4715                 cmdtxt(np);
4716                 if (sep && np->narg.next)
4717                         cmdputs(" ");
4718         }
4719 }
4720
4721 static void
4722 cmdtxt(union node *n)
4723 {
4724         union node *np;
4725         struct nodelist *lp;
4726         const char *p;
4727
4728         if (!n)
4729                 return;
4730         switch (n->type) {
4731         default:
4732 #if DEBUG
4733                 abort();
4734 #endif
4735         case NPIPE:
4736                 lp = n->npipe.cmdlist;
4737                 for (;;) {
4738                         cmdtxt(lp->n);
4739                         lp = lp->next;
4740                         if (!lp)
4741                                 break;
4742                         cmdputs(" | ");
4743                 }
4744                 break;
4745         case NSEMI:
4746                 p = "; ";
4747                 goto binop;
4748         case NAND:
4749                 p = " && ";
4750                 goto binop;
4751         case NOR:
4752                 p = " || ";
4753  binop:
4754                 cmdtxt(n->nbinary.ch1);
4755                 cmdputs(p);
4756                 n = n->nbinary.ch2;
4757                 goto donode;
4758         case NREDIR:
4759         case NBACKGND:
4760                 n = n->nredir.n;
4761                 goto donode;
4762         case NNOT:
4763                 cmdputs("!");
4764                 n = n->nnot.com;
4765  donode:
4766                 cmdtxt(n);
4767                 break;
4768         case NIF:
4769                 cmdputs("if ");
4770                 cmdtxt(n->nif.test);
4771                 cmdputs("; then ");
4772                 if (n->nif.elsepart) {
4773                         cmdtxt(n->nif.ifpart);
4774                         cmdputs("; else ");
4775                         n = n->nif.elsepart;
4776                 } else {
4777                         n = n->nif.ifpart;
4778                 }
4779                 p = "; fi";
4780                 goto dotail;
4781         case NSUBSHELL:
4782                 cmdputs("(");
4783                 n = n->nredir.n;
4784                 p = ")";
4785                 goto dotail;
4786         case NWHILE:
4787                 p = "while ";
4788                 goto until;
4789         case NUNTIL:
4790                 p = "until ";
4791  until:
4792                 cmdputs(p);
4793                 cmdtxt(n->nbinary.ch1);
4794                 n = n->nbinary.ch2;
4795                 p = "; done";
4796  dodo:
4797                 cmdputs("; do ");
4798  dotail:
4799                 cmdtxt(n);
4800                 goto dotail2;
4801         case NFOR:
4802                 cmdputs("for ");
4803                 cmdputs(n->nfor.var);
4804                 cmdputs(" in ");
4805                 cmdlist(n->nfor.args, 1);
4806                 n = n->nfor.body;
4807                 p = "; done";
4808                 goto dodo;
4809         case NDEFUN:
4810                 cmdputs(n->narg.text);
4811                 p = "() { ... }";
4812                 goto dotail2;
4813         case NCMD:
4814                 cmdlist(n->ncmd.args, 1);
4815                 cmdlist(n->ncmd.redirect, 0);
4816                 break;
4817         case NARG:
4818                 p = n->narg.text;
4819  dotail2:
4820                 cmdputs(p);
4821                 break;
4822         case NHERE:
4823         case NXHERE:
4824                 p = "<<...";
4825                 goto dotail2;
4826         case NCASE:
4827                 cmdputs("case ");
4828                 cmdputs(n->ncase.expr->narg.text);
4829                 cmdputs(" in ");
4830                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4831                         cmdtxt(np->nclist.pattern);
4832                         cmdputs(") ");
4833                         cmdtxt(np->nclist.body);
4834                         cmdputs(";; ");
4835                 }
4836                 p = "esac";
4837                 goto dotail2;
4838         case NTO:
4839                 p = ">";
4840                 goto redir;
4841         case NCLOBBER:
4842                 p = ">|";
4843                 goto redir;
4844         case NAPPEND:
4845                 p = ">>";
4846                 goto redir;
4847 #if BASH_REDIR_OUTPUT
4848         case NTO2:
4849 #endif
4850         case NTOFD:
4851                 p = ">&";
4852                 goto redir;
4853         case NFROM:
4854                 p = "<";
4855                 goto redir;
4856         case NFROMFD:
4857                 p = "<&";
4858                 goto redir;
4859         case NFROMTO:
4860                 p = "<>";
4861  redir:
4862                 cmdputs(utoa(n->nfile.fd));
4863                 cmdputs(p);
4864                 if (n->type == NTOFD || n->type == NFROMFD) {
4865                         if (n->ndup.dupfd >= 0)
4866                                 cmdputs(utoa(n->ndup.dupfd));
4867                         else
4868                                 cmdputs("-");
4869                         break;
4870                 }
4871                 n = n->nfile.fname;
4872                 goto donode;
4873         }
4874 }
4875
4876 static char *
4877 commandtext(union node *n)
4878 {
4879         char *name;
4880
4881         STARTSTACKSTR(cmdnextc);
4882         cmdtxt(n);
4883         name = stackblock();
4884         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4885         return ckstrdup(name);
4886 }
4887 #endif /* JOBS */
4888
4889 /*
4890  * Fork off a subshell.  If we are doing job control, give the subshell its
4891  * own process group.  Jp is a job structure that the job is to be added to.
4892  * N is the command that will be evaluated by the child.  Both jp and n may
4893  * be NULL.  The mode parameter can be one of the following:
4894  *      FORK_FG - Fork off a foreground process.
4895  *      FORK_BG - Fork off a background process.
4896  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4897  *                   process group even if job control is on.
4898  *
4899  * When job control is turned off, background processes have their standard
4900  * input redirected to /dev/null (except for the second and later processes
4901  * in a pipeline).
4902  *
4903  * Called with interrupts off.
4904  */
4905 /*
4906  * Clear traps on a fork.
4907  */
4908 static void
4909 clear_traps(void)
4910 {
4911         char **tp;
4912
4913         INT_OFF;
4914         for (tp = trap; tp < &trap[NSIG]; tp++) {
4915                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4916                         if (trap_ptr == trap)
4917                                 free(*tp);
4918                         /* else: it "belongs" to trap_ptr vector, don't free */
4919                         *tp = NULL;
4920                         if ((tp - trap) != 0)
4921                                 setsignal(tp - trap);
4922                 }
4923         }
4924         may_have_traps = 0;
4925         INT_ON;
4926 }
4927
4928 /* Lives far away from here, needed for forkchild */
4929 static void closescript(void);
4930
4931 /* Called after fork(), in child */
4932 /* jp and n are NULL when called by openhere() for heredoc support */
4933 static NOINLINE void
4934 forkchild(struct job *jp, union node *n, int mode)
4935 {
4936         int oldlvl;
4937
4938         TRACE(("Child shell %d\n", getpid()));
4939         oldlvl = shlvl;
4940         shlvl++;
4941
4942         /* man bash: "Non-builtin commands run by bash have signal handlers
4943          * set to the values inherited by the shell from its parent".
4944          * Do we do it correctly? */
4945
4946         closescript();
4947
4948         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4949          && n && n->type == NCMD        /* is it single cmd? */
4950         /* && n->ncmd.args->type == NARG - always true? */
4951          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4952          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4953         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4954         ) {
4955                 TRACE(("Trap hack\n"));
4956                 /* Awful hack for `trap` or $(trap).
4957                  *
4958                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4959                  * contains an example where "trap" is executed in a subshell:
4960                  *
4961                  * save_traps=$(trap)
4962                  * ...
4963                  * eval "$save_traps"
4964                  *
4965                  * Standard does not say that "trap" in subshell shall print
4966                  * parent shell's traps. It only says that its output
4967                  * must have suitable form, but then, in the above example
4968                  * (which is not supposed to be normative), it implies that.
4969                  *
4970                  * bash (and probably other shell) does implement it
4971                  * (traps are reset to defaults, but "trap" still shows them),
4972                  * but as a result, "trap" logic is hopelessly messed up:
4973                  *
4974                  * # trap
4975                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4976                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4977                  * # true | trap   <--- trap is in subshell - no output (ditto)
4978                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4979                  * trap -- 'echo Ho' SIGWINCH
4980                  * # echo `(trap)`         <--- in subshell in subshell - output
4981                  * trap -- 'echo Ho' SIGWINCH
4982                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4983                  * trap -- 'echo Ho' SIGWINCH
4984                  *
4985                  * The rules when to forget and when to not forget traps
4986                  * get really complex and nonsensical.
4987                  *
4988                  * Our solution: ONLY bare $(trap) or `trap` is special.
4989                  */
4990                 /* Save trap handler strings for trap builtin to print */
4991                 trap_ptr = xmemdup(trap, sizeof(trap));
4992                 /* Fall through into clearing traps */
4993         }
4994         clear_traps();
4995 #if JOBS
4996         /* do job control only in root shell */
4997         doing_jobctl = 0;
4998         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4999                 pid_t pgrp;
5000
5001                 if (jp->nprocs == 0)
5002                         pgrp = getpid();
5003                 else
5004                         pgrp = jp->ps[0].ps_pid;
5005                 /* this can fail because we are doing it in the parent also */
5006                 setpgid(0, pgrp);
5007                 if (mode == FORK_FG)
5008                         xtcsetpgrp(ttyfd, pgrp);
5009                 setsignal(SIGTSTP);
5010                 setsignal(SIGTTOU);
5011         } else
5012 #endif
5013         if (mode == FORK_BG) {
5014                 /* man bash: "When job control is not in effect,
5015                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5016                 ignoresig(SIGINT);
5017                 ignoresig(SIGQUIT);
5018                 if (jp->nprocs == 0) {
5019                         close(0);
5020                         if (open(bb_dev_null, O_RDONLY) != 0)
5021                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5022                 }
5023         }
5024         if (oldlvl == 0) {
5025                 if (iflag) { /* why if iflag only? */
5026                         setsignal(SIGINT);
5027                         setsignal(SIGTERM);
5028                 }
5029                 /* man bash:
5030                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5031                  * commands run by bash have signal handlers
5032                  * set to the values inherited by the shell
5033                  * from its parent".
5034                  * Take care of the second rule: */
5035                 setsignal(SIGQUIT);
5036         }
5037 #if JOBS
5038         if (n && n->type == NCMD
5039          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5040         ) {
5041                 TRACE(("Job hack\n"));
5042                 /* "jobs": we do not want to clear job list for it,
5043                  * instead we remove only _its_ own_ job from job list.
5044                  * This makes "jobs .... | cat" more useful.
5045                  */
5046                 freejob(curjob);
5047                 return;
5048         }
5049 #endif
5050         for (jp = curjob; jp; jp = jp->prev_job)
5051                 freejob(jp);
5052         jobless = 0;
5053 }
5054
5055 /* Called after fork(), in parent */
5056 #if !JOBS
5057 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5058 #endif
5059 static void
5060 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5061 {
5062         TRACE(("In parent shell: child = %d\n", pid));
5063         if (!jp) {
5064                 /* jp is NULL when called by openhere() for heredoc support */
5065                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5066                         continue;
5067                 jobless++;
5068                 return;
5069         }
5070 #if JOBS
5071         if (mode != FORK_NOJOB && jp->jobctl) {
5072                 int pgrp;
5073
5074                 if (jp->nprocs == 0)
5075                         pgrp = pid;
5076                 else
5077                         pgrp = jp->ps[0].ps_pid;
5078                 /* This can fail because we are doing it in the child also */
5079                 setpgid(pid, pgrp);
5080         }
5081 #endif
5082         if (mode == FORK_BG) {
5083                 backgndpid = pid;               /* set $! */
5084                 set_curjob(jp, CUR_RUNNING);
5085         }
5086         if (jp) {
5087                 struct procstat *ps = &jp->ps[jp->nprocs++];
5088                 ps->ps_pid = pid;
5089                 ps->ps_status = -1;
5090                 ps->ps_cmd = nullstr;
5091 #if JOBS
5092                 if (doing_jobctl && n)
5093                         ps->ps_cmd = commandtext(n);
5094 #endif
5095         }
5096 }
5097
5098 /* jp and n are NULL when called by openhere() for heredoc support */
5099 static int
5100 forkshell(struct job *jp, union node *n, int mode)
5101 {
5102         int pid;
5103
5104         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5105         pid = fork();
5106         if (pid < 0) {
5107                 TRACE(("Fork failed, errno=%d", errno));
5108                 if (jp)
5109                         freejob(jp);
5110                 ash_msg_and_raise_perror("can't fork");
5111         }
5112         if (pid == 0) {
5113                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5114                 forkchild(jp, n, mode);
5115         } else {
5116                 forkparent(jp, n, mode, pid);
5117         }
5118         return pid;
5119 }
5120
5121 /*
5122  * Wait for job to finish.
5123  *
5124  * Under job control we have the problem that while a child process
5125  * is running interrupts generated by the user are sent to the child
5126  * but not to the shell.  This means that an infinite loop started by
5127  * an interactive user may be hard to kill.  With job control turned off,
5128  * an interactive user may place an interactive program inside a loop.
5129  * If the interactive program catches interrupts, the user doesn't want
5130  * these interrupts to also abort the loop.  The approach we take here
5131  * is to have the shell ignore interrupt signals while waiting for a
5132  * foreground process to terminate, and then send itself an interrupt
5133  * signal if the child process was terminated by an interrupt signal.
5134  * Unfortunately, some programs want to do a bit of cleanup and then
5135  * exit on interrupt; unless these processes terminate themselves by
5136  * sending a signal to themselves (instead of calling exit) they will
5137  * confuse this approach.
5138  *
5139  * Called with interrupts off.
5140  */
5141 static int
5142 waitforjob(struct job *jp)
5143 {
5144         int st;
5145
5146         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5147
5148         INT_OFF;
5149         while (jp->state == JOBRUNNING) {
5150                 /* In non-interactive shells, we _can_ get
5151                  * a keyboard signal here and be EINTRed,
5152                  * but we just loop back, waiting for command to complete.
5153                  *
5154                  * man bash:
5155                  * "If bash is waiting for a command to complete and receives
5156                  * a signal for which a trap has been set, the trap
5157                  * will not be executed until the command completes."
5158                  *
5159                  * Reality is that even if trap is not set, bash
5160                  * will not act on the signal until command completes.
5161                  * Try this. sleep5intoff.c:
5162                  * #include <signal.h>
5163                  * #include <unistd.h>
5164                  * int main() {
5165                  *         sigset_t set;
5166                  *         sigemptyset(&set);
5167                  *         sigaddset(&set, SIGINT);
5168                  *         sigaddset(&set, SIGQUIT);
5169                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5170                  *         sleep(5);
5171                  *         return 0;
5172                  * }
5173                  * $ bash -c './sleep5intoff; echo hi'
5174                  * ^C^C^C^C <--- pressing ^C once a second
5175                  * $ _
5176                  * $ bash -c './sleep5intoff; echo hi'
5177                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5178                  * $ _
5179                  */
5180                 dowait(DOWAIT_BLOCK, jp);
5181         }
5182         INT_ON;
5183
5184         st = getstatus(jp);
5185 #if JOBS
5186         if (jp->jobctl) {
5187                 xtcsetpgrp(ttyfd, rootpid);
5188                 restore_tty_if_stopped_or_signaled(jp);
5189
5190                 /*
5191                  * This is truly gross.
5192                  * If we're doing job control, then we did a TIOCSPGRP which
5193                  * caused us (the shell) to no longer be in the controlling
5194                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5195                  * intuit from the subprocess exit status whether a SIGINT
5196                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5197                  */
5198                 if (jp->sigint) /* TODO: do the same with all signals */
5199                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5200         }
5201         if (jp->state == JOBDONE)
5202 #endif
5203                 freejob(jp);
5204         return st;
5205 }
5206
5207 /*
5208  * return 1 if there are stopped jobs, otherwise 0
5209  */
5210 static int
5211 stoppedjobs(void)
5212 {
5213         struct job *jp;
5214         int retval;
5215
5216         retval = 0;
5217         if (job_warning)
5218                 goto out;
5219         jp = curjob;
5220         if (jp && jp->state == JOBSTOPPED) {
5221                 out2str("You have stopped jobs.\n");
5222                 job_warning = 2;
5223                 retval++;
5224         }
5225  out:
5226         return retval;
5227 }
5228
5229
5230 /*
5231  * Code for dealing with input/output redirection.
5232  */
5233
5234 #undef EMPTY
5235 #undef CLOSED
5236 #define EMPTY -2                /* marks an unused slot in redirtab */
5237 #define CLOSED -1               /* marks a slot of previously-closed fd */
5238
5239 /*
5240  * Handle here documents.  Normally we fork off a process to write the
5241  * data to a pipe.  If the document is short, we can stuff the data in
5242  * the pipe without forking.
5243  */
5244 /* openhere needs this forward reference */
5245 static void expandhere(union node *arg, int fd);
5246 static int
5247 openhere(union node *redir)
5248 {
5249         int pip[2];
5250         size_t len = 0;
5251
5252         if (pipe(pip) < 0)
5253                 ash_msg_and_raise_perror("can't create pipe");
5254         if (redir->type == NHERE) {
5255                 len = strlen(redir->nhere.doc->narg.text);
5256                 if (len <= PIPE_BUF) {
5257                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5258                         goto out;
5259                 }
5260         }
5261         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5262                 /* child */
5263                 close(pip[0]);
5264                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5265                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5266                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5267                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5268                 signal(SIGPIPE, SIG_DFL);
5269                 if (redir->type == NHERE)
5270                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5271                 else /* NXHERE */
5272                         expandhere(redir->nhere.doc, pip[1]);
5273                 _exit(EXIT_SUCCESS);
5274         }
5275  out:
5276         close(pip[1]);
5277         return pip[0];
5278 }
5279
5280 static int
5281 openredirect(union node *redir)
5282 {
5283         struct stat sb;
5284         char *fname;
5285         int f;
5286
5287         switch (redir->nfile.type) {
5288 /* Can't happen, our single caller does this itself */
5289 //      case NTOFD:
5290 //      case NFROMFD:
5291 //              return -1;
5292         case NHERE:
5293         case NXHERE:
5294                 return openhere(redir);
5295         }
5296
5297         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5298          * allocated space. Do it only when we know it is safe.
5299          */
5300         fname = redir->nfile.expfname;
5301
5302         switch (redir->nfile.type) {
5303         default:
5304 #if DEBUG
5305                 abort();
5306 #endif
5307         case NFROM:
5308                 f = open(fname, O_RDONLY);
5309                 if (f < 0)
5310                         goto eopen;
5311                 break;
5312         case NFROMTO:
5313                 f = open(fname, O_RDWR|O_CREAT, 0666);
5314                 if (f < 0)
5315                         goto ecreate;
5316                 break;
5317         case NTO:
5318 #if BASH_REDIR_OUTPUT
5319         case NTO2:
5320 #endif
5321                 /* Take care of noclobber mode. */
5322                 if (Cflag) {
5323                         if (stat(fname, &sb) < 0) {
5324                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5325                                 if (f < 0)
5326                                         goto ecreate;
5327                         } else if (!S_ISREG(sb.st_mode)) {
5328                                 f = open(fname, O_WRONLY, 0666);
5329                                 if (f < 0)
5330                                         goto ecreate;
5331                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5332                                         close(f);
5333                                         errno = EEXIST;
5334                                         goto ecreate;
5335                                 }
5336                         } else {
5337                                 errno = EEXIST;
5338                                 goto ecreate;
5339                         }
5340                         break;
5341                 }
5342                 /* FALLTHROUGH */
5343         case NCLOBBER:
5344                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5345                 if (f < 0)
5346                         goto ecreate;
5347                 break;
5348         case NAPPEND:
5349                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5350                 if (f < 0)
5351                         goto ecreate;
5352                 break;
5353         }
5354
5355         return f;
5356  ecreate:
5357         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5358  eopen:
5359         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5360 }
5361
5362 /*
5363  * Copy a file descriptor to be >= 10. Throws exception on error.
5364  */
5365 static int
5366 savefd(int from)
5367 {
5368         int newfd;
5369         int err;
5370
5371         newfd = fcntl(from, F_DUPFD, 10);
5372         err = newfd < 0 ? errno : 0;
5373         if (err != EBADF) {
5374                 if (err)
5375                         ash_msg_and_raise_perror("%d", from);
5376                 close(from);
5377                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5378         }
5379
5380         return newfd;
5381 }
5382 static int
5383 dup2_or_raise(int from, int to)
5384 {
5385         int newfd;
5386
5387         newfd = (from != to) ? dup2(from, to) : to;
5388         if (newfd < 0) {
5389                 /* Happens when source fd is not open: try "echo >&99" */
5390                 ash_msg_and_raise_perror("%d", from);
5391         }
5392         return newfd;
5393 }
5394 static int
5395 fcntl_F_DUPFD(int fd, int avoid_fd)
5396 {
5397         int newfd;
5398  repeat:
5399         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5400         if (newfd < 0) {
5401                 if (errno == EBUSY)
5402                         goto repeat;
5403                 if (errno == EINTR)
5404                         goto repeat;
5405         }
5406         return newfd;
5407 }
5408 static int
5409 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5410 {
5411         int newfd;
5412  repeat:
5413         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5414         if (newfd < 0) {
5415                 if (errno == EBUSY)
5416                         goto repeat;
5417                 if (errno == EINTR)
5418                         goto repeat;
5419                 /* fd was not open? */
5420                 if (errno == EBADF)
5421                         return fd;
5422                 ash_msg_and_raise_perror("%d", newfd);
5423         }
5424         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5425         close(fd);
5426         return newfd;
5427 }
5428
5429 /* Struct def and variable are moved down to the first usage site */
5430 struct squirrel {
5431         int orig_fd;
5432         int moved_to;
5433 };
5434 struct redirtab {
5435         struct redirtab *next;
5436         int pair_count;
5437         struct squirrel two_fd[];
5438 };
5439 #define redirlist (G_var.redirlist)
5440
5441 static void
5442 add_squirrel_closed(struct redirtab *sq, int fd)
5443 {
5444         int i;
5445
5446         if (!sq)
5447                 return;
5448
5449         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5450                 /* If we collide with an already moved fd... */
5451                 if (fd == sq->two_fd[i].orig_fd) {
5452                         /* Examples:
5453                          * "echo 3>FILE 3>&- 3>FILE"
5454                          * "echo 3>&- 3>FILE"
5455                          * No need for last redirect to insert
5456                          * another "need to close 3" indicator.
5457                          */
5458                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5459                         return;
5460                 }
5461         }
5462         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5463         sq->two_fd[i].orig_fd = fd;
5464         sq->two_fd[i].moved_to = CLOSED;
5465 }
5466
5467 static int
5468 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5469 {
5470         int i, new_fd;
5471
5472         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5473                 avoid_fd = 9;
5474
5475 #if JOBS
5476         if (fd == ttyfd) {
5477                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5478                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5479                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5480                 return 1; /* "we closed fd" */
5481         }
5482 #endif
5483         /* Are we called from redirect(0)? E.g. redirect
5484          * in a forked child. No need to save fds,
5485          * we aren't going to use them anymore, ok to trash.
5486          */
5487         if (!sq)
5488                 return 0;
5489
5490         /* If this one of script's fds? */
5491         if (fd != 0) {
5492                 struct parsefile *pf = g_parsefile;
5493                 while (pf) {
5494                         /* We skip fd == 0 case because of the following:
5495                          * $ ash  # running ash interactively
5496                          * $ . ./script.sh
5497                          * and in script.sh: "exec 9>&0".
5498                          * Even though top-level pf_fd _is_ 0,
5499                          * it's still ok to use it: "read" builtin uses it,
5500                          * why should we cripple "exec" builtin?
5501                          */
5502                         if (fd == pf->pf_fd) {
5503                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5504                                 return 1; /* "we closed fd" */
5505                         }
5506                         pf = pf->prev;
5507                 }
5508         }
5509
5510         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5511
5512         /* First: do we collide with some already moved fds? */
5513         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5514                 /* If we collide with an already moved fd... */
5515                 if (fd == sq->two_fd[i].moved_to) {
5516                         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5517                         sq->two_fd[i].moved_to = new_fd;
5518                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5519                         if (new_fd < 0) /* what? */
5520                                 xfunc_die();
5521                         return 0; /* "we did not close fd" */
5522                 }
5523                 if (fd == sq->two_fd[i].orig_fd) {
5524                         /* Example: echo Hello >/dev/null 1>&2 */
5525                         TRACE(("redirect_fd %d: already moved\n", fd));
5526                         return 0; /* "we did not close fd" */
5527                 }
5528         }
5529
5530         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5531         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5532         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5533         if (new_fd < 0) {
5534                 if (errno != EBADF)
5535                         xfunc_die();
5536                 /* new_fd = CLOSED; - already is -1 */
5537         }
5538         sq->two_fd[i].moved_to = new_fd;
5539         sq->two_fd[i].orig_fd = fd;
5540
5541         /* if we move stderr, let "set -x" code know */
5542         if (fd == preverrout_fd)
5543                 preverrout_fd = new_fd;
5544
5545         return 0; /* "we did not close fd" */
5546 }
5547
5548 static int
5549 internally_opened_fd(int fd, struct redirtab *sq)
5550 {
5551         int i;
5552 #if JOBS
5553         if (fd == ttyfd)
5554                 return 1;
5555 #endif
5556         /* If this one of script's fds? */
5557         if (fd != 0) {
5558                 struct parsefile *pf = g_parsefile;
5559                 while (pf) {
5560                         if (fd == pf->pf_fd)
5561                                 return 1;
5562                         pf = pf->prev;
5563                 }
5564         }
5565
5566         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5567                 if (fd == sq->two_fd[i].moved_to)
5568                         return 1;
5569         }
5570         return 0;
5571 }
5572
5573 /*
5574  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5575  * old file descriptors are stashed away so that the redirection can be
5576  * undone by calling popredir.
5577  */
5578 /* flags passed to redirect */
5579 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5580 static void
5581 redirect(union node *redir, int flags)
5582 {
5583         struct redirtab *sv;
5584
5585         if (!redir)
5586                 return;
5587
5588         sv = NULL;
5589         INT_OFF;
5590         if (flags & REDIR_PUSH)
5591                 sv = redirlist;
5592         do {
5593                 int fd;
5594                 int newfd;
5595                 int close_fd;
5596                 int closed;
5597
5598                 fd = redir->nfile.fd;
5599                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5600                         //bb_error_msg("doing %d > %d", fd, newfd);
5601                         newfd = redir->ndup.dupfd;
5602                         close_fd = -1;
5603                 } else {
5604                         newfd = openredirect(redir); /* always >= 0 */
5605                         if (fd == newfd) {
5606                                 /* open() gave us precisely the fd we wanted.
5607                                  * This means that this fd was not busy
5608                                  * (not opened to anywhere).
5609                                  * Remember to close it on restore:
5610                                  */
5611                                 add_squirrel_closed(sv, fd);
5612                                 continue;
5613                         }
5614                         close_fd = newfd;
5615                 }
5616
5617                 if (fd == newfd)
5618                         continue;
5619
5620                 /* if "N>FILE": move newfd to fd */
5621                 /* if "N>&M": dup newfd to fd */
5622                 /* if "N>&-": close fd (newfd is -1) */
5623
5624  IF_BASH_REDIR_OUTPUT(redirect_more:)
5625
5626                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5627                 if (newfd == -1) {
5628                         /* "N>&-" means "close me" */
5629                         if (!closed) {
5630                                 /* ^^^ optimization: saving may already
5631                                  * have closed it. If not... */
5632                                 close(fd);
5633                         }
5634                 } else {
5635                         /* if newfd is a script fd or saved fd, simulate EBADF */
5636                         if (internally_opened_fd(newfd, sv)) {
5637                                 errno = EBADF;
5638                                 ash_msg_and_raise_perror("%d", newfd);
5639                         }
5640                         dup2_or_raise(newfd, fd);
5641                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5642                                 close(close_fd);
5643 #if BASH_REDIR_OUTPUT
5644                         if (redir->nfile.type == NTO2 && fd == 1) {
5645                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5646                                 fd = 2;
5647                                 newfd = 1;
5648                                 close_fd = -1;
5649                                 goto redirect_more;
5650                         }
5651 #endif
5652                 }
5653         } while ((redir = redir->nfile.next) != NULL);
5654         INT_ON;
5655
5656 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5657 #define REDIR_SAVEFD2 0
5658         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5659         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5660         // not only for calls with flags containing REDIR_SAVEFD2.
5661         // We do this unconditionally (see save_fd_on_redirect()).
5662         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5663         //      preverrout_fd = copied_fd2;
5664 }
5665
5666 static int
5667 redirectsafe(union node *redir, int flags)
5668 {
5669         int err;
5670         volatile int saveint;
5671         struct jmploc *volatile savehandler = exception_handler;
5672         struct jmploc jmploc;
5673
5674         SAVE_INT(saveint);
5675         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5676         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5677         if (!err) {
5678                 exception_handler = &jmploc;
5679                 redirect(redir, flags);
5680         }
5681         exception_handler = savehandler;
5682         if (err && exception_type != EXERROR)
5683                 longjmp(exception_handler->loc, 1);
5684         RESTORE_INT(saveint);
5685         return err;
5686 }
5687
5688 static struct redirtab*
5689 pushredir(union node *redir)
5690 {
5691         struct redirtab *sv;
5692         int i;
5693
5694         if (!redir)
5695                 return redirlist;
5696
5697         i = 0;
5698         do {
5699                 i++;
5700 #if BASH_REDIR_OUTPUT
5701                 if (redir->nfile.type == NTO2)
5702                         i++;
5703 #endif
5704                 redir = redir->nfile.next;
5705         } while (redir);
5706
5707         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5708         sv->pair_count = i;
5709         while (--i >= 0)
5710                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5711         sv->next = redirlist;
5712         redirlist = sv;
5713         return sv->next;
5714 }
5715
5716 /*
5717  * Undo the effects of the last redirection.
5718  */
5719 static void
5720 popredir(int drop)
5721 {
5722         struct redirtab *rp;
5723         int i;
5724
5725         if (redirlist == NULL)
5726                 return;
5727         INT_OFF;
5728         rp = redirlist;
5729         for (i = 0; i < rp->pair_count; i++) {
5730                 int fd = rp->two_fd[i].orig_fd;
5731                 int copy = rp->two_fd[i].moved_to;
5732                 if (copy == CLOSED) {
5733                         if (!drop)
5734                                 close(fd);
5735                         continue;
5736                 }
5737                 if (copy != EMPTY) {
5738                         if (!drop) {
5739                                 /*close(fd);*/
5740                                 dup2_or_raise(copy, fd);
5741                         }
5742                         close(copy);
5743                 }
5744         }
5745         redirlist = rp->next;
5746         free(rp);
5747         INT_ON;
5748 }
5749
5750 static void
5751 unwindredir(struct redirtab *stop)
5752 {
5753         while (redirlist != stop)
5754                 popredir(/*drop:*/ 0);
5755 }
5756
5757
5758 /* ============ Routines to expand arguments to commands
5759  *
5760  * We have to deal with backquotes, shell variables, and file metacharacters.
5761  */
5762
5763 #if ENABLE_FEATURE_SH_MATH
5764 static arith_t
5765 ash_arith(const char *s)
5766 {
5767         arith_state_t math_state;
5768         arith_t result;
5769
5770         math_state.lookupvar = lookupvar;
5771         math_state.setvar    = setvar0;
5772         //math_state.endofname = endofname;
5773
5774         INT_OFF;
5775         result = arith(&math_state, s);
5776         if (math_state.errmsg)
5777                 ash_msg_and_raise_error(math_state.errmsg);
5778         INT_ON;
5779
5780         return result;
5781 }
5782 #endif
5783 #if BASH_SUBSTR
5784 # if ENABLE_FEATURE_SH_MATH
5785 static int substr_atoi(const char *s)
5786 {
5787         arith_t t = ash_arith(s);
5788         if (sizeof(t) > sizeof(int)) {
5789                 /* clamp very large or very large negative nums for ${v:N:M}:
5790                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5791                  */
5792                 if (t > INT_MAX)
5793                         t = INT_MAX;
5794                 if (t < INT_MIN)
5795                         t = INT_MIN;
5796         }
5797         return t;
5798 }
5799 # else
5800 #  define substr_atoi(s) number(s)
5801 # endif
5802 #endif
5803
5804 /*
5805  * expandarg flags
5806  */
5807 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5808 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5809 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5810 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5811 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5812  * POSIX says for this case:
5813  *  Pathname expansion shall not be performed on the word by a
5814  *  non-interactive shell; an interactive shell may perform it, but shall
5815  *  do so only when the expansion would result in one word.
5816  * Currently, our code complies to the above rule by never globbing
5817  * redirection filenames.
5818  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5819  * (this means that on a typical Linux distro, bash almost always
5820  * performs globbing, and thus diverges from what we do).
5821  */
5822 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5823 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5824 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5825 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5826 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5827 /*
5828  * rmescape() flags
5829  */
5830 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5831 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5832 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5833 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5834
5835 /* Add CTLESC when necessary. */
5836 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5837 /* Do not skip NUL characters. */
5838 #define QUOTES_KEEPNUL EXP_TILDE
5839
5840 /*
5841  * Structure specifying which parts of the string should be searched
5842  * for IFS characters.
5843  */
5844 struct ifsregion {
5845         struct ifsregion *next; /* next region in list */
5846         int begoff;             /* offset of start of region */
5847         int endoff;             /* offset of end of region */
5848         int nulonly;            /* search for nul bytes only */
5849 };
5850
5851 struct arglist {
5852         struct strlist *list;
5853         struct strlist **lastp;
5854 };
5855
5856 /* output of current string */
5857 static char *expdest;
5858 /* list of back quote expressions */
5859 static struct nodelist *argbackq;
5860 /* first struct in list of ifs regions */
5861 static struct ifsregion ifsfirst;
5862 /* last struct in list */
5863 static struct ifsregion *ifslastp;
5864 /* holds expanded arg list */
5865 static struct arglist exparg;
5866
5867 /*
5868  * Our own itoa().
5869  * cvtnum() is used even if math support is off (to prepare $? values and such).
5870  */
5871 static int
5872 cvtnum(arith_t num)
5873 {
5874         int len;
5875
5876         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5877         len = sizeof(arith_t) * 3;
5878         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5879         if (sizeof(arith_t) < 4) len += 2;
5880
5881         expdest = makestrspace(len, expdest);
5882         len = fmtstr(expdest, len, ARITH_FMT, num);
5883         STADJUST(len, expdest);
5884         return len;
5885 }
5886
5887 /*
5888  * Break the argument string into pieces based upon IFS and add the
5889  * strings to the argument list.  The regions of the string to be
5890  * searched for IFS characters have been stored by recordregion.
5891  */
5892 static void
5893 ifsbreakup(char *string, struct arglist *arglist)
5894 {
5895         struct ifsregion *ifsp;
5896         struct strlist *sp;
5897         char *start;
5898         char *p;
5899         char *q;
5900         const char *ifs, *realifs;
5901         int ifsspc;
5902         int nulonly;
5903
5904         start = string;
5905         if (ifslastp != NULL) {
5906                 ifsspc = 0;
5907                 nulonly = 0;
5908                 realifs = ifsset() ? ifsval() : defifs;
5909                 ifsp = &ifsfirst;
5910                 do {
5911                         p = string + ifsp->begoff;
5912                         nulonly = ifsp->nulonly;
5913                         ifs = nulonly ? nullstr : realifs;
5914                         ifsspc = 0;
5915                         while (p < string + ifsp->endoff) {
5916                                 q = p;
5917                                 if ((unsigned char)*p == CTLESC)
5918                                         p++;
5919                                 if (!strchr(ifs, *p)) {
5920                                         p++;
5921                                         continue;
5922                                 }
5923                                 if (!nulonly)
5924                                         ifsspc = (strchr(defifs, *p) != NULL);
5925                                 /* Ignore IFS whitespace at start */
5926                                 if (q == start && ifsspc) {
5927                                         p++;
5928                                         start = p;
5929                                         continue;
5930                                 }
5931                                 *q = '\0';
5932                                 sp = stzalloc(sizeof(*sp));
5933                                 sp->text = start;
5934                                 *arglist->lastp = sp;
5935                                 arglist->lastp = &sp->next;
5936                                 p++;
5937                                 if (!nulonly) {
5938                                         for (;;) {
5939                                                 if (p >= string + ifsp->endoff) {
5940                                                         break;
5941                                                 }
5942                                                 q = p;
5943                                                 if ((unsigned char)*p == CTLESC)
5944                                                         p++;
5945                                                 if (strchr(ifs, *p) == NULL) {
5946                                                         p = q;
5947                                                         break;
5948                                                 }
5949                                                 if (strchr(defifs, *p) == NULL) {
5950                                                         if (ifsspc) {
5951                                                                 p++;
5952                                                                 ifsspc = 0;
5953                                                         } else {
5954                                                                 p = q;
5955                                                                 break;
5956                                                         }
5957                                                 } else
5958                                                         p++;
5959                                         }
5960                                 }
5961                                 start = p;
5962                         } /* while */
5963                         ifsp = ifsp->next;
5964                 } while (ifsp != NULL);
5965                 if (nulonly)
5966                         goto add;
5967         }
5968
5969         if (!*start)
5970                 return;
5971
5972  add:
5973         sp = stzalloc(sizeof(*sp));
5974         sp->text = start;
5975         *arglist->lastp = sp;
5976         arglist->lastp = &sp->next;
5977 }
5978
5979 static void
5980 ifsfree(void)
5981 {
5982         struct ifsregion *p = ifsfirst.next;
5983
5984         if (!p)
5985                 goto out;
5986
5987         INT_OFF;
5988         do {
5989                 struct ifsregion *ifsp;
5990                 ifsp = p->next;
5991                 free(p);
5992                 p = ifsp;
5993         } while (p);
5994         ifsfirst.next = NULL;
5995         INT_ON;
5996  out:
5997         ifslastp = NULL;
5998 }
5999
6000 static size_t
6001 esclen(const char *start, const char *p)
6002 {
6003         size_t esc = 0;
6004
6005         while (p > start && (unsigned char)*--p == CTLESC) {
6006                 esc++;
6007         }
6008         return esc;
6009 }
6010
6011 /*
6012  * Remove any CTLESC characters from a string.
6013  */
6014 #if !BASH_PATTERN_SUBST
6015 #define rmescapes(str, flag, slash_position) \
6016         rmescapes(str, flag)
6017 #endif
6018 static char *
6019 rmescapes(char *str, int flag, int *slash_position)
6020 {
6021         static const char qchars[] ALIGN1 = {
6022                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6023
6024         char *p, *q, *r;
6025         unsigned inquotes;
6026         unsigned protect_against_glob;
6027         unsigned globbing;
6028
6029         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6030         if (!p)
6031                 return str;
6032
6033         q = p;
6034         r = str;
6035         if (flag & RMESCAPE_ALLOC) {
6036                 size_t len = p - str;
6037                 size_t fulllen = len + strlen(p) + 1;
6038
6039                 if (flag & RMESCAPE_GROW) {
6040                         int strloc = str - (char *)stackblock();
6041                         r = makestrspace(fulllen, expdest);
6042                         /* p and str may be invalidated by makestrspace */
6043                         str = (char *)stackblock() + strloc;
6044                         p = str + len;
6045                 } else if (flag & RMESCAPE_HEAP) {
6046                         r = ckmalloc(fulllen);
6047                 } else {
6048                         r = stalloc(fulllen);
6049                 }
6050                 q = r;
6051                 if (len > 0) {
6052                         q = (char *)mempcpy(q, str, len);
6053                 }
6054         }
6055
6056         inquotes = 0;
6057         globbing = flag & RMESCAPE_GLOB;
6058         protect_against_glob = globbing;
6059         while (*p) {
6060                 if ((unsigned char)*p == CTLQUOTEMARK) {
6061 // Note: both inquotes and protect_against_glob only affect whether
6062 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6063                         inquotes = ~inquotes;
6064                         p++;
6065                         protect_against_glob = globbing;
6066                         continue;
6067                 }
6068                 if ((unsigned char)*p == CTLESC) {
6069                         p++;
6070 #if DEBUG
6071                         if (*p == '\0')
6072                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6073 #endif
6074                         if (protect_against_glob) {
6075                                 /*
6076                                  * We used to trust glob() and fnmatch() to eat
6077                                  * superfluous escapes (\z where z has no
6078                                  * special meaning anyway). But this causes
6079                                  * bugs such as string of one greek letter rho
6080                                  * (unicode-encoded as two bytes "cf,81")
6081                                  * getting encoded as "cf,CTLESC,81"
6082                                  * and here, converted to "cf,\,81" -
6083                                  * which does not go well with some flavors
6084                                  * of fnmatch() in unicode locales
6085                                  * (for example, glibc <= 2.22).
6086                                  *
6087                                  * Lets add "\" only on the chars which need it.
6088                                  * Testcases for less obvious chars are shown.
6089                                  */
6090                                 if (*p == '*'
6091                                  || *p == '?'
6092                                  || *p == '['
6093                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6094                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6095                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6096                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6097                                 /* Some libc support [^negate], that's why "^" also needs love */
6098                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6099                                 ) {
6100                                         *q++ = '\\';
6101                                 }
6102                         }
6103                 } else if (*p == '\\' && !inquotes) {
6104                         /* naked back slash */
6105                         protect_against_glob = 0;
6106                         goto copy;
6107                 }
6108 #if BASH_PATTERN_SUBST
6109                 else if (slash_position && p == str + *slash_position) {
6110                         /* stop handling globbing */
6111                         globbing = 0;
6112                         *slash_position = q - r;
6113                         slash_position = NULL;
6114                 }
6115 #endif
6116                 protect_against_glob = globbing;
6117  copy:
6118                 *q++ = *p++;
6119         }
6120         *q = '\0';
6121         if (flag & RMESCAPE_GROW) {
6122                 expdest = r;
6123                 STADJUST(q - r + 1, expdest);
6124         }
6125         return r;
6126 }
6127 #define pmatch(a, b) !fnmatch((a), (b), 0)
6128
6129 /*
6130  * Prepare a pattern for a expmeta (internal glob(3)) call.
6131  *
6132  * Returns an stalloced string.
6133  */
6134 static char *
6135 preglob(const char *pattern, int flag)
6136 {
6137         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6138 }
6139
6140 /*
6141  * Put a string on the stack.
6142  */
6143 static void
6144 memtodest(const char *p, size_t len, int syntax, int quotes)
6145 {
6146         char *q;
6147
6148         if (!len)
6149                 return;
6150
6151         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6152
6153         do {
6154                 unsigned char c = *p++;
6155                 if (c) {
6156                         if (quotes & QUOTES_ESC) {
6157                                 int n = SIT(c, syntax);
6158                                 if (n == CCTL
6159                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6160                                      && n == CBACK
6161                                     )
6162                                 ) {
6163                                         USTPUTC(CTLESC, q);
6164                                 }
6165                         }
6166                 } else if (!(quotes & QUOTES_KEEPNUL))
6167                         continue;
6168                 USTPUTC(c, q);
6169         } while (--len);
6170
6171         expdest = q;
6172 }
6173
6174 static size_t
6175 strtodest(const char *p, int syntax, int quotes)
6176 {
6177         size_t len = strlen(p);
6178         memtodest(p, len, syntax, quotes);
6179         return len;
6180 }
6181
6182 /*
6183  * Record the fact that we have to scan this region of the
6184  * string for IFS characters.
6185  */
6186 static void
6187 recordregion(int start, int end, int nulonly)
6188 {
6189         struct ifsregion *ifsp;
6190
6191         if (ifslastp == NULL) {
6192                 ifsp = &ifsfirst;
6193         } else {
6194                 INT_OFF;
6195                 ifsp = ckzalloc(sizeof(*ifsp));
6196                 /*ifsp->next = NULL; - ckzalloc did it */
6197                 ifslastp->next = ifsp;
6198                 INT_ON;
6199         }
6200         ifslastp = ifsp;
6201         ifslastp->begoff = start;
6202         ifslastp->endoff = end;
6203         ifslastp->nulonly = nulonly;
6204 }
6205
6206 static void
6207 removerecordregions(int endoff)
6208 {
6209         if (ifslastp == NULL)
6210                 return;
6211
6212         if (ifsfirst.endoff > endoff) {
6213                 while (ifsfirst.next) {
6214                         struct ifsregion *ifsp;
6215                         INT_OFF;
6216                         ifsp = ifsfirst.next->next;
6217                         free(ifsfirst.next);
6218                         ifsfirst.next = ifsp;
6219                         INT_ON;
6220                 }
6221                 if (ifsfirst.begoff > endoff) {
6222                         ifslastp = NULL;
6223                 } else {
6224                         ifslastp = &ifsfirst;
6225                         ifsfirst.endoff = endoff;
6226                 }
6227                 return;
6228         }
6229
6230         ifslastp = &ifsfirst;
6231         while (ifslastp->next && ifslastp->next->begoff < endoff)
6232                 ifslastp = ifslastp->next;
6233         while (ifslastp->next) {
6234                 struct ifsregion *ifsp;
6235                 INT_OFF;
6236                 ifsp = ifslastp->next->next;
6237                 free(ifslastp->next);
6238                 ifslastp->next = ifsp;
6239                 INT_ON;
6240         }
6241         if (ifslastp->endoff > endoff)
6242                 ifslastp->endoff = endoff;
6243 }
6244
6245 static char *
6246 exptilde(char *startp, char *p, int flags)
6247 {
6248         unsigned char c;
6249         char *name;
6250         struct passwd *pw;
6251         const char *home;
6252         int quotes = flags & QUOTES_ESC;
6253
6254         name = p + 1;
6255
6256         while ((c = *++p) != '\0') {
6257                 switch (c) {
6258                 case CTLESC:
6259                         return startp;
6260                 case CTLQUOTEMARK:
6261                         return startp;
6262                 case ':':
6263                         if (flags & EXP_VARTILDE)
6264                                 goto done;
6265                         break;
6266                 case '/':
6267                 case CTLENDVAR:
6268                         goto done;
6269                 }
6270         }
6271  done:
6272         *p = '\0';
6273         if (*name == '\0') {
6274                 home = lookupvar("HOME");
6275         } else {
6276                 pw = getpwnam(name);
6277                 if (pw == NULL)
6278                         goto lose;
6279                 home = pw->pw_dir;
6280         }
6281         if (!home || !*home)
6282                 goto lose;
6283         *p = c;
6284         strtodest(home, SQSYNTAX, quotes);
6285         return p;
6286  lose:
6287         *p = c;
6288         return startp;
6289 }
6290
6291 /*
6292  * Execute a command inside back quotes.  If it's a builtin command, we
6293  * want to save its output in a block obtained from malloc.  Otherwise
6294  * we fork off a subprocess and get the output of the command via a pipe.
6295  * Should be called with interrupts off.
6296  */
6297 struct backcmd {                /* result of evalbackcmd */
6298         int fd;                 /* file descriptor to read from */
6299         int nleft;              /* number of chars in buffer */
6300         char *buf;              /* buffer */
6301         struct job *jp;         /* job structure for command */
6302 };
6303
6304 /* These forward decls are needed to use "eval" code for backticks handling: */
6305 /* flags in argument to evaltree */
6306 #define EV_EXIT    01           /* exit after evaluating tree */
6307 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6308 static int evaltree(union node *, int);
6309
6310 /* An evaltree() which is known to never return.
6311  * Used to use an alias:
6312  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6313  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6314  */
6315 static ALWAYS_INLINE NORETURN void
6316 evaltreenr(union node *n, int flags)
6317 {
6318         evaltree(n, flags);
6319         bb_unreachable(abort());
6320         /* NOTREACHED */
6321 }
6322
6323 static void FAST_FUNC
6324 evalbackcmd(union node *n, struct backcmd *result)
6325 {
6326         int pip[2];
6327         struct job *jp;
6328
6329         result->fd = -1;
6330         result->buf = NULL;
6331         result->nleft = 0;
6332         result->jp = NULL;
6333         if (n == NULL) {
6334                 goto out;
6335         }
6336
6337         if (pipe(pip) < 0)
6338                 ash_msg_and_raise_perror("can't create pipe");
6339         jp = makejob(/*n,*/ 1);
6340         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6341                 /* child */
6342                 FORCE_INT_ON;
6343                 close(pip[0]);
6344                 if (pip[1] != 1) {
6345                         /*close(1);*/
6346                         dup2_or_raise(pip[1], 1);
6347                         close(pip[1]);
6348                 }
6349 /* TODO: eflag clearing makes the following not abort:
6350  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6351  * which is what bash does (unless it is in POSIX mode).
6352  * dash deleted "eflag = 0" line in the commit
6353  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6354  *  [EVAL] Don't clear eflag in evalbackcmd
6355  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6356  */
6357                 eflag = 0;
6358                 ifsfree();
6359                 evaltreenr(n, EV_EXIT);
6360                 /* NOTREACHED */
6361         }
6362         /* parent */
6363         close(pip[1]);
6364         result->fd = pip[0];
6365         result->jp = jp;
6366
6367  out:
6368         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6369                 result->fd, result->buf, result->nleft, result->jp));
6370 }
6371
6372 /*
6373  * Expand stuff in backwards quotes.
6374  */
6375 static void
6376 expbackq(union node *cmd, int flag)
6377 {
6378         struct backcmd in;
6379         int i;
6380         char buf[128];
6381         char *p;
6382         char *dest;
6383         int startloc;
6384         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6385         struct stackmark smark;
6386
6387         INT_OFF;
6388         startloc = expdest - (char *)stackblock();
6389         pushstackmark(&smark, startloc);
6390         evalbackcmd(cmd, &in);
6391         popstackmark(&smark);
6392
6393         p = in.buf;
6394         i = in.nleft;
6395         if (i == 0)
6396                 goto read;
6397         for (;;) {
6398                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6399  read:
6400                 if (in.fd < 0)
6401                         break;
6402                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6403                 TRACE(("expbackq: read returns %d\n", i));
6404                 if (i <= 0)
6405                         break;
6406                 p = buf;
6407         }
6408
6409         free(in.buf);
6410         if (in.fd >= 0) {
6411                 close(in.fd);
6412                 back_exitstatus = waitforjob(in.jp);
6413         }
6414         INT_ON;
6415
6416         /* Eat all trailing newlines */
6417         dest = expdest;
6418         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6419                 STUNPUTC(dest);
6420         expdest = dest;
6421
6422         if (!(flag & EXP_QUOTED))
6423                 recordregion(startloc, dest - (char *)stackblock(), 0);
6424         TRACE(("evalbackq: size:%d:'%.*s'\n",
6425                 (int)((dest - (char *)stackblock()) - startloc),
6426                 (int)((dest - (char *)stackblock()) - startloc),
6427                 stackblock() + startloc));
6428 }
6429
6430 #if ENABLE_FEATURE_SH_MATH
6431 /*
6432  * Expand arithmetic expression.  Backup to start of expression,
6433  * evaluate, place result in (backed up) result, adjust string position.
6434  */
6435 static void
6436 expari(int flag)
6437 {
6438         char *p, *start;
6439         int begoff;
6440         int len;
6441
6442         /* ifsfree(); */
6443
6444         /*
6445          * This routine is slightly over-complicated for
6446          * efficiency.  Next we scan backwards looking for the
6447          * start of arithmetic.
6448          */
6449         start = stackblock();
6450         p = expdest - 1;
6451         *p = '\0';
6452         p--;
6453         while (1) {
6454                 int esc;
6455
6456                 while ((unsigned char)*p != CTLARI) {
6457                         p--;
6458 #if DEBUG
6459                         if (p < start) {
6460                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6461                         }
6462 #endif
6463                 }
6464
6465                 esc = esclen(start, p);
6466                 if (!(esc % 2)) {
6467                         break;
6468                 }
6469
6470                 p -= esc + 1;
6471         }
6472
6473         begoff = p - start;
6474
6475         removerecordregions(begoff);
6476
6477         expdest = p;
6478
6479         if (flag & QUOTES_ESC)
6480                 rmescapes(p + 1, 0, NULL);
6481
6482         len = cvtnum(ash_arith(p + 1));
6483
6484         if (!(flag & EXP_QUOTED))
6485                 recordregion(begoff, begoff + len, 0);
6486 }
6487 #endif
6488
6489 /* argstr needs it */
6490 static char *evalvar(char *p, int flags);
6491
6492 /*
6493  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6494  * characters to allow for further processing.  Otherwise treat
6495  * $@ like $* since no splitting will be performed.
6496  */
6497 static void
6498 argstr(char *p, int flags)
6499 {
6500         static const char spclchars[] ALIGN1 = {
6501                 '=',
6502                 ':',
6503                 CTLQUOTEMARK,
6504                 CTLENDVAR,
6505                 CTLESC,
6506                 CTLVAR,
6507                 CTLBACKQ,
6508 #if ENABLE_FEATURE_SH_MATH
6509                 CTLENDARI,
6510 #endif
6511                 '\0'
6512         };
6513         const char *reject = spclchars;
6514         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6515         int inquotes;
6516         size_t length;
6517         int startloc;
6518
6519         if (!(flags & EXP_VARTILDE)) {
6520                 reject += 2;
6521         } else if (flags & EXP_VARTILDE2) {
6522                 reject++;
6523         }
6524         inquotes = 0;
6525         length = 0;
6526         if (flags & EXP_TILDE) {
6527                 char *q;
6528
6529                 flags &= ~EXP_TILDE;
6530  tilde:
6531                 q = p;
6532                 if (*q == '~')
6533                         p = exptilde(p, q, flags);
6534         }
6535  start:
6536         startloc = expdest - (char *)stackblock();
6537         for (;;) {
6538                 unsigned char c;
6539
6540                 length += strcspn(p + length, reject);
6541                 c = p[length];
6542                 if (c) {
6543                         if (!(c & 0x80)
6544                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6545                         ) {
6546                                 /* c == '=' || c == ':' || c == CTLENDARI */
6547                                 length++;
6548                         }
6549                 }
6550                 if (length > 0) {
6551                         int newloc;
6552                         expdest = stack_nputstr(p, length, expdest);
6553                         newloc = expdest - (char *)stackblock();
6554                         if (breakall && !inquotes && newloc > startloc) {
6555                                 recordregion(startloc, newloc, 0);
6556                         }
6557                         startloc = newloc;
6558                 }
6559                 p += length + 1;
6560                 length = 0;
6561
6562                 switch (c) {
6563                 case '\0':
6564                         goto breakloop;
6565                 case '=':
6566                         if (flags & EXP_VARTILDE2) {
6567                                 p--;
6568                                 continue;
6569                         }
6570                         flags |= EXP_VARTILDE2;
6571                         reject++;
6572                         /* fall through */
6573                 case ':':
6574                         /*
6575                          * sort of a hack - expand tildes in variable
6576                          * assignments (after the first '=' and after ':'s).
6577                          */
6578                         if (*--p == '~') {
6579                                 goto tilde;
6580                         }
6581                         continue;
6582                 }
6583
6584                 switch (c) {
6585                 case CTLENDVAR: /* ??? */
6586                         goto breakloop;
6587                 case CTLQUOTEMARK:
6588                         inquotes ^= EXP_QUOTED;
6589                         /* "$@" syntax adherence hack */
6590                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6591                                 p = evalvar(p + 1, flags | inquotes) + 1;
6592                                 goto start;
6593                         }
6594  addquote:
6595                         if (flags & QUOTES_ESC) {
6596                                 p--;
6597                                 length++;
6598                                 startloc++;
6599                         }
6600                         break;
6601                 case CTLESC:
6602                         startloc++;
6603                         length++;
6604
6605                         /*
6606                          * Quoted parameter expansion pattern: remove quote
6607                          * unless inside inner quotes or we have a literal
6608                          * backslash.
6609                          */
6610                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6611                             EXP_QPAT && *p != '\\')
6612                                 break;
6613
6614                         goto addquote;
6615                 case CTLVAR:
6616                         TRACE(("argstr: evalvar('%s')\n", p));
6617                         p = evalvar(p, flags | inquotes);
6618                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6619                         goto start;
6620                 case CTLBACKQ:
6621                         expbackq(argbackq->n, flags | inquotes);
6622                         argbackq = argbackq->next;
6623                         goto start;
6624 #if ENABLE_FEATURE_SH_MATH
6625                 case CTLENDARI:
6626                         p--;
6627                         expari(flags | inquotes);
6628                         goto start;
6629 #endif
6630                 }
6631         }
6632  breakloop: ;
6633 }
6634
6635 static char *
6636 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6637                 char *pattern, int quotes, int zero)
6638 {
6639         char *loc, *loc2;
6640         char c;
6641
6642         loc = startp;
6643         loc2 = rmesc;
6644         do {
6645                 int match;
6646                 const char *s = loc2;
6647
6648                 c = *loc2;
6649                 if (zero) {
6650                         *loc2 = '\0';
6651                         s = rmesc;
6652                 }
6653                 match = pmatch(pattern, s);
6654
6655                 *loc2 = c;
6656                 if (match)
6657                         return loc;
6658                 if (quotes && (unsigned char)*loc == CTLESC)
6659                         loc++;
6660                 loc++;
6661                 loc2++;
6662         } while (c);
6663         return NULL;
6664 }
6665
6666 static char *
6667 scanright(char *startp, char *rmesc, char *rmescend,
6668                 char *pattern, int quotes, int match_at_start)
6669 {
6670 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6671         int try2optimize = match_at_start;
6672 #endif
6673         int esc = 0;
6674         char *loc;
6675         char *loc2;
6676
6677         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6678          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6679          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6680          * Logic:
6681          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6682          * and on each iteration they go back two/one char until they reach the beginning.
6683          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6684          */
6685         /* TODO: document in what other circumstances we are called. */
6686
6687         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6688                 int match;
6689                 char c = *loc2;
6690                 const char *s = loc2;
6691                 if (match_at_start) {
6692                         *loc2 = '\0';
6693                         s = rmesc;
6694                 }
6695                 match = pmatch(pattern, s);
6696                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6697                 *loc2 = c;
6698                 if (match)
6699                         return loc;
6700 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6701                 if (try2optimize) {
6702                         /* Maybe we can optimize this:
6703                          * if pattern ends with unescaped *, we can avoid checking
6704                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6705                          * it won't match truncated "raw_value_of_" strings too.
6706                          */
6707                         unsigned plen = strlen(pattern);
6708                         /* Does it end with "*"? */
6709                         if (plen != 0 && pattern[--plen] == '*') {
6710                                 /* "xxxx*" is not escaped */
6711                                 /* "xxx\*" is escaped */
6712                                 /* "xx\\*" is not escaped */
6713                                 /* "x\\\*" is escaped */
6714                                 int slashes = 0;
6715                                 while (plen != 0 && pattern[--plen] == '\\')
6716                                         slashes++;
6717                                 if (!(slashes & 1))
6718                                         break; /* ends with unescaped "*" */
6719                         }
6720                         try2optimize = 0;
6721                 }
6722 #endif
6723                 loc--;
6724                 if (quotes) {
6725                         if (--esc < 0) {
6726                                 esc = esclen(startp, loc);
6727                         }
6728                         if (esc % 2) {
6729                                 esc--;
6730                                 loc--;
6731                         }
6732                 }
6733         }
6734         return NULL;
6735 }
6736
6737 static void varunset(const char *, const char *, const char *, int) NORETURN;
6738 static void
6739 varunset(const char *end, const char *var, const char *umsg, int varflags)
6740 {
6741         const char *msg;
6742         const char *tail;
6743
6744         tail = nullstr;
6745         msg = "parameter not set";
6746         if (umsg) {
6747                 if ((unsigned char)*end == CTLENDVAR) {
6748                         if (varflags & VSNUL)
6749                                 tail = " or null";
6750                 } else {
6751                         msg = umsg;
6752                 }
6753         }
6754         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6755 }
6756
6757 static const char *
6758 subevalvar(char *p, char *varname, int strloc, int subtype,
6759                 int startloc, int varflags, int flag)
6760 {
6761         struct nodelist *saveargbackq = argbackq;
6762         int quotes = flag & QUOTES_ESC;
6763         char *startp;
6764         char *loc;
6765         char *rmesc, *rmescend;
6766         char *str;
6767         int amount, resetloc;
6768         int argstr_flags;
6769         IF_BASH_PATTERN_SUBST(int workloc;)
6770         IF_BASH_PATTERN_SUBST(int slash_pos;)
6771         IF_BASH_PATTERN_SUBST(char *repl;)
6772         int zero;
6773         char *(*scan)(char*, char*, char*, char*, int, int);
6774
6775         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6776         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6777
6778 #if BASH_PATTERN_SUBST
6779         /* For "${v/pattern/repl}", we must find the delimiter _before_
6780          * argstr() call expands possible variable references in pattern:
6781          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6782          */
6783         repl = NULL;
6784         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6785                 /* Find '/' and replace with NUL */
6786                 repl = p;
6787                 for (;;) {
6788                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6789                         if (*repl == '\0') {
6790                                 repl = NULL;
6791                                 break;
6792                         }
6793                         if (*repl == '/') {
6794                                 *repl = '\0';
6795                                 break;
6796                         }
6797                         if ((unsigned char)*repl == CTLESC && repl[1])
6798                                 repl++;
6799                         repl++;
6800                 }
6801         }
6802 #endif
6803         argstr_flags = EXP_TILDE;
6804         if (subtype != VSASSIGN && subtype != VSQUESTION)
6805                 argstr_flags |= (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE);
6806         argstr(p, argstr_flags);
6807 #if BASH_PATTERN_SUBST
6808         slash_pos = -1;
6809         if (repl) {
6810                 slash_pos = expdest - ((char *)stackblock() + strloc);
6811                 STPUTC('/', expdest);
6812                 argstr(repl + 1, argstr_flags);
6813                 *repl = '/';
6814         }
6815 #endif
6816         STPUTC('\0', expdest);
6817         argbackq = saveargbackq;
6818         startp = (char *)stackblock() + startloc;
6819         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6820
6821         switch (subtype) {
6822         case VSASSIGN:
6823                 setvar0(varname, startp);
6824                 amount = startp - expdest;
6825                 STADJUST(amount, expdest);
6826                 return startp;
6827
6828         case VSQUESTION:
6829                 varunset(p, varname, startp, varflags);
6830                 /* NOTREACHED */
6831
6832 #if BASH_SUBSTR
6833         case VSSUBSTR: {
6834                 int pos, len, orig_len;
6835                 char *colon;
6836
6837                 loc = str = stackblock() + strloc;
6838
6839                 /* Read POS in ${var:POS:LEN} */
6840                 colon = strchr(loc, ':');
6841                 if (colon) *colon = '\0';
6842                 pos = substr_atoi(loc);
6843                 if (colon) *colon = ':';
6844
6845                 /* Read LEN in ${var:POS:LEN} */
6846                 len = str - startp - 1;
6847                 /* *loc != '\0', guaranteed by parser */
6848                 if (quotes) {
6849                         char *ptr;
6850                         /* Adjust the length by the number of escapes */
6851                         for (ptr = startp; ptr < (str - 1); ptr++) {
6852                                 if ((unsigned char)*ptr == CTLESC) {
6853                                         len--;
6854                                         ptr++;
6855                                 }
6856                         }
6857                 }
6858                 orig_len = len;
6859                 if (*loc++ == ':') {
6860                         /* ${var::LEN} */
6861                         len = substr_atoi(loc);
6862                 } else {
6863                         /* Skip POS in ${var:POS:LEN} */
6864                         len = orig_len;
6865                         while (*loc && *loc != ':')
6866                                 loc++;
6867                         if (*loc++ == ':')
6868                                 len = substr_atoi(loc);
6869                 }
6870                 if (pos < 0) {
6871                         /* ${VAR:$((-n)):l} starts n chars from the end */
6872                         pos = orig_len + pos;
6873                 }
6874                 if ((unsigned)pos >= orig_len) {
6875                         /* apart from obvious ${VAR:999999:l},
6876                          * covers ${VAR:$((-9999999)):l} - result is ""
6877                          * (bash compat)
6878                          */
6879                         pos = 0;
6880                         len = 0;
6881                 }
6882                 if (len < 0) {
6883                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6884                         len = (orig_len - pos) + len;
6885                 }
6886                 if ((unsigned)len > (orig_len - pos))
6887                         len = orig_len - pos;
6888
6889                 for (str = startp; pos; str++, pos--) {
6890                         if (quotes && (unsigned char)*str == CTLESC)
6891                                 str++;
6892                 }
6893                 for (loc = startp; len; len--) {
6894                         if (quotes && (unsigned char)*str == CTLESC)
6895                                 *loc++ = *str++;
6896                         *loc++ = *str++;
6897                 }
6898                 *loc = '\0';
6899                 amount = loc - expdest;
6900                 STADJUST(amount, expdest);
6901                 return loc;
6902         }
6903 #endif /* BASH_SUBSTR */
6904         }
6905
6906         resetloc = expdest - (char *)stackblock();
6907
6908 #if BASH_PATTERN_SUBST
6909         repl = NULL;
6910
6911         /* We'll comeback here if we grow the stack while handling
6912          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6913          * stack will need rebasing, and we'll need to remove our work
6914          * areas each time
6915          */
6916  restart:
6917 #endif
6918
6919         amount = expdest - ((char *)stackblock() + resetloc);
6920         STADJUST(-amount, expdest);
6921         startp = (char *)stackblock() + startloc;
6922
6923         rmesc = startp;
6924         rmescend = (char *)stackblock() + strloc;
6925         //bb_error_msg("str7:'%s'", rmescend);
6926         if (quotes) {
6927 //TODO: how to handle slash_pos here if string changes (shortens?)
6928                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
6929                 if (rmesc != startp) {
6930                         rmescend = expdest;
6931                         startp = (char *)stackblock() + startloc;
6932                 }
6933         }
6934         rmescend--;
6935         str = (char *)stackblock() + strloc;
6936         /*
6937          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6938          * The result is a_\_z_c (not a\_\_z_c)!
6939          *
6940          * The search pattern and replace string treat backslashes differently!
6941          * "&slash_pos" causes rmescapes() to work differently on the pattern
6942          * and string.  It's only used on the first call.
6943          */
6944         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
6945         rmescapes(str, RMESCAPE_GLOB,
6946                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
6947         );
6948
6949 #if BASH_PATTERN_SUBST
6950         workloc = expdest - (char *)stackblock();
6951         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6952                 int len;
6953                 char *idx, *end;
6954
6955                 if (!repl) {
6956                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
6957                         repl = nullstr;
6958                         if (slash_pos >= 0) {
6959                                 repl = str + slash_pos;
6960                                 *repl++ = '\0';
6961                         }
6962                 }
6963                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6964
6965                 /* If there's no pattern to match, return the expansion unmolested */
6966                 if (str[0] == '\0')
6967                         return NULL;
6968
6969                 len = 0;
6970                 idx = startp;
6971                 end = str - 1;
6972                 while (idx < end) {
6973  try_to_match:
6974                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6975                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6976                         if (!loc) {
6977                                 /* No match, advance */
6978                                 char *restart_detect = stackblock();
6979  skip_matching:
6980                                 STPUTC(*idx, expdest);
6981                                 if (quotes && (unsigned char)*idx == CTLESC) {
6982                                         idx++;
6983                                         len++;
6984                                         STPUTC(*idx, expdest);
6985                                 }
6986                                 if (stackblock() != restart_detect)
6987                                         goto restart;
6988                                 idx++;
6989                                 len++;
6990                                 rmesc++;
6991                                 /* continue; - prone to quadratic behavior, smarter code: */
6992                                 if (idx >= end)
6993                                         break;
6994                                 if (str[0] == '*') {
6995                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6996                                          * it would never match "ong_string" etc, no point in trying.
6997                                          */
6998                                         goto skip_matching;
6999                                 }
7000                                 goto try_to_match;
7001                         }
7002
7003                         if (subtype == VSREPLACEALL) {
7004                                 while (idx < loc) {
7005                                         if (quotes && (unsigned char)*idx == CTLESC)
7006                                                 idx++;
7007                                         idx++;
7008                                         rmesc++;
7009                                 }
7010                         } else {
7011                                 idx = loc;
7012                         }
7013
7014                         //bb_error_msg("repl:'%s'", repl);
7015                         for (loc = (char*)repl; *loc; loc++) {
7016                                 char *restart_detect = stackblock();
7017                                 if (quotes && *loc == '\\') {
7018                                         STPUTC(CTLESC, expdest);
7019                                         len++;
7020                                 }
7021                                 STPUTC(*loc, expdest);
7022                                 if (stackblock() != restart_detect)
7023                                         goto restart;
7024                                 len++;
7025                         }
7026
7027                         if (subtype == VSREPLACE) {
7028                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7029                                 while (*idx) {
7030                                         char *restart_detect = stackblock();
7031                                         STPUTC(*idx, expdest);
7032                                         if (stackblock() != restart_detect)
7033                                                 goto restart;
7034                                         len++;
7035                                         idx++;
7036                                 }
7037                                 break;
7038                         }
7039                 }
7040
7041                 /* We've put the replaced text into a buffer at workloc, now
7042                  * move it to the right place and adjust the stack.
7043                  */
7044                 STPUTC('\0', expdest);
7045                 startp = (char *)stackblock() + startloc;
7046                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7047                 //bb_error_msg("startp:'%s'", startp);
7048                 amount = expdest - (startp + len);
7049                 STADJUST(-amount, expdest);
7050                 return startp;
7051         }
7052 #endif /* BASH_PATTERN_SUBST */
7053
7054         subtype -= VSTRIMRIGHT;
7055 #if DEBUG
7056         if (subtype < 0 || subtype > 7)
7057                 abort();
7058 #endif
7059         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7060         zero = subtype >> 1;
7061         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7062         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7063
7064         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7065         if (loc) {
7066                 if (zero) {
7067                         memmove(startp, loc, str - loc);
7068                         loc = startp + (str - loc) - 1;
7069                 }
7070                 *loc = '\0';
7071                 amount = loc - expdest;
7072                 STADJUST(amount, expdest);
7073         }
7074         return loc;
7075 }
7076
7077 /*
7078  * Add the value of a specialized variable to the stack string.
7079  * name parameter (examples):
7080  * ash -c 'echo $1'      name:'1='
7081  * ash -c 'echo $qwe'    name:'qwe='
7082  * ash -c 'echo $$'      name:'$='
7083  * ash -c 'echo ${$}'    name:'$='
7084  * ash -c 'echo ${$##q}' name:'$=q'
7085  * ash -c 'echo ${#$}'   name:'$='
7086  * note: examples with bad shell syntax:
7087  * ash -c 'echo ${#$1}'  name:'$=1'
7088  * ash -c 'echo ${#1#}'  name:'1=#'
7089  */
7090 static NOINLINE ssize_t
7091 varvalue(char *name, int varflags, int flags, int *quotedp)
7092 {
7093         const char *p;
7094         int num;
7095         int i;
7096         ssize_t len = 0;
7097         int sep;
7098         int quoted = *quotedp;
7099         int subtype = varflags & VSTYPE;
7100         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7101         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7102         int syntax;
7103
7104         sep = (flags & EXP_FULL) << CHAR_BIT;
7105         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7106
7107         switch (*name) {
7108         case '$':
7109                 num = rootpid;
7110                 goto numvar;
7111         case '?':
7112                 num = exitstatus;
7113                 goto numvar;
7114         case '#':
7115                 num = shellparam.nparam;
7116                 goto numvar;
7117         case '!':
7118                 num = backgndpid;
7119                 if (num == 0)
7120                         return -1;
7121  numvar:
7122                 len = cvtnum(num);
7123                 goto check_1char_name;
7124         case '-':
7125                 expdest = makestrspace(NOPTS, expdest);
7126                 for (i = NOPTS - 1; i >= 0; i--) {
7127                         if (optlist[i]) {
7128                                 USTPUTC(optletters(i), expdest);
7129                                 len++;
7130                         }
7131                 }
7132  check_1char_name:
7133 #if 0
7134                 /* handles cases similar to ${#$1} */
7135                 if (name[2] != '\0')
7136                         raise_error_syntax("bad substitution");
7137 #endif
7138                 break;
7139         case '@':
7140                 if (quoted && sep)
7141                         goto param;
7142                 /* fall through */
7143         case '*': {
7144                 char **ap;
7145                 char sepc;
7146
7147                 if (quoted)
7148                         sep = 0;
7149                 sep |= ifsset() ? ifsval()[0] : ' ';
7150  param:
7151                 sepc = sep;
7152                 *quotedp = !sepc;
7153                 ap = shellparam.p;
7154                 if (!ap)
7155                         return -1;
7156                 while ((p = *ap++) != NULL) {
7157                         len += strtodest(p, syntax, quotes);
7158
7159                         if (*ap && sep) {
7160                                 len++;
7161                                 memtodest(&sepc, 1, syntax, quotes);
7162                         }
7163                 }
7164                 break;
7165         } /* case '*' */
7166         case '0':
7167         case '1':
7168         case '2':
7169         case '3':
7170         case '4':
7171         case '5':
7172         case '6':
7173         case '7':
7174         case '8':
7175         case '9':
7176                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7177                 if (num < 0 || num > shellparam.nparam)
7178                         return -1;
7179                 p = num ? shellparam.p[num - 1] : arg0;
7180                 goto value;
7181         default:
7182                 /* NB: name has form "VAR=..." */
7183                 p = lookupvar(name);
7184  value:
7185                 if (!p)
7186                         return -1;
7187
7188                 len = strtodest(p, syntax, quotes);
7189 #if ENABLE_UNICODE_SUPPORT
7190                 if (subtype == VSLENGTH && len > 0) {
7191                         reinit_unicode_for_ash();
7192                         if (unicode_status == UNICODE_ON) {
7193                                 STADJUST(-len, expdest);
7194                                 discard = 0;
7195                                 len = unicode_strlen(p);
7196                         }
7197                 }
7198 #endif
7199                 break;
7200         }
7201
7202         if (discard)
7203                 STADJUST(-len, expdest);
7204         return len;
7205 }
7206
7207 /*
7208  * Expand a variable, and return a pointer to the next character in the
7209  * input string.
7210  */
7211 static char *
7212 evalvar(char *p, int flag)
7213 {
7214         char varflags;
7215         char subtype;
7216         int quoted;
7217         char easy;
7218         char *var;
7219         int patloc;
7220         int startloc;
7221         ssize_t varlen;
7222
7223         varflags = (unsigned char) *p++;
7224         subtype = varflags & VSTYPE;
7225
7226         if (!subtype)
7227                 raise_error_syntax("bad substitution");
7228
7229         quoted = flag & EXP_QUOTED;
7230         var = p;
7231         easy = (!quoted || (*var == '@' && shellparam.nparam));
7232         startloc = expdest - (char *)stackblock();
7233         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7234
7235  again:
7236         varlen = varvalue(var, varflags, flag, &quoted);
7237         if (varflags & VSNUL)
7238                 varlen--;
7239
7240         if (subtype == VSPLUS) {
7241                 varlen = -1 - varlen;
7242                 goto vsplus;
7243         }
7244
7245         if (subtype == VSMINUS) {
7246  vsplus:
7247                 if (varlen < 0) {
7248                         argstr(
7249                                 p,
7250                                 flag | EXP_TILDE | EXP_WORD
7251                         );
7252                         goto end;
7253                 }
7254                 goto record;
7255         }
7256
7257         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7258                 if (varlen >= 0)
7259                         goto record;
7260
7261                 subevalvar(p, var, 0, subtype, startloc, varflags,
7262                            flag & ~QUOTES_ESC);
7263                 varflags &= ~VSNUL;
7264                 /*
7265                  * Remove any recorded regions beyond
7266                  * start of variable
7267                  */
7268                 removerecordregions(startloc);
7269                 goto again;
7270         }
7271
7272         if (varlen < 0 && uflag)
7273                 varunset(p, var, 0, 0);
7274
7275         if (subtype == VSLENGTH) {
7276                 cvtnum(varlen > 0 ? varlen : 0);
7277                 goto record;
7278         }
7279
7280         if (subtype == VSNORMAL) {
7281  record:
7282                 if (!easy)
7283                         goto end;
7284                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7285                 goto end;
7286         }
7287
7288 #if DEBUG
7289         switch (subtype) {
7290         case VSTRIMLEFT:
7291         case VSTRIMLEFTMAX:
7292         case VSTRIMRIGHT:
7293         case VSTRIMRIGHTMAX:
7294 #if BASH_SUBSTR
7295         case VSSUBSTR:
7296 #endif
7297 #if BASH_PATTERN_SUBST
7298         case VSREPLACE:
7299         case VSREPLACEALL:
7300 #endif
7301                 break;
7302         default:
7303                 abort();
7304         }
7305 #endif
7306
7307         if (varlen >= 0) {
7308                 /*
7309                  * Terminate the string and start recording the pattern
7310                  * right after it
7311                  */
7312                 STPUTC('\0', expdest);
7313                 patloc = expdest - (char *)stackblock();
7314                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7315                                 startloc, varflags, flag)) {
7316                         int amount = expdest - (
7317                                 (char *)stackblock() + patloc - 1
7318                         );
7319                         STADJUST(-amount, expdest);
7320                 }
7321                 /* Remove any recorded regions beyond start of variable */
7322                 removerecordregions(startloc);
7323                 goto record;
7324         }
7325
7326  end:
7327         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7328                 int nesting = 1;
7329                 for (;;) {
7330                         unsigned char c = *p++;
7331                         if (c == CTLESC)
7332                                 p++;
7333                         else if (c == CTLBACKQ) {
7334                                 if (varlen >= 0)
7335                                         argbackq = argbackq->next;
7336                         } else if (c == CTLVAR) {
7337                                 if ((*p++ & VSTYPE) != VSNORMAL)
7338                                         nesting++;
7339                         } else if (c == CTLENDVAR) {
7340                                 if (--nesting == 0)
7341                                         break;
7342                         }
7343                 }
7344         }
7345         return p;
7346 }
7347
7348 /*
7349  * Add a file name to the list.
7350  */
7351 static void
7352 addfname(const char *name)
7353 {
7354         struct strlist *sp;
7355
7356         sp = stzalloc(sizeof(*sp));
7357         sp->text = sstrdup(name);
7358         *exparg.lastp = sp;
7359         exparg.lastp = &sp->next;
7360 }
7361
7362 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7363 static int
7364 hasmeta(const char *p)
7365 {
7366         static const char chars[] ALIGN1 = {
7367                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7368         };
7369
7370         for (;;) {
7371                 p = strpbrk(p, chars);
7372                 if (!p)
7373                         break;
7374                 switch ((unsigned char) *p) {
7375                 case CTLQUOTEMARK:
7376                         for (;;) {
7377                                 p++;
7378                                 if (*p == CTLQUOTEMARK)
7379                                         break;
7380                                 if (*p == CTLESC)
7381                                         p++;
7382                                 if (*p == '\0') /* huh? */
7383                                         return 0;
7384                         }
7385                         break;
7386                 case '\\':
7387                 case CTLESC:
7388                         p++;
7389                         if (*p == '\0')
7390                                 return 0;
7391                         break;
7392                 case '[':
7393                         if (!strchr(p + 1, ']')) {
7394                                 /* It's not a properly closed [] pattern,
7395                                  * but other metas may follow. Continue checking.
7396                                  * my[file* _is_ globbed by bash
7397                                  * and matches filenames like "my[file1".
7398                                  */
7399                                 break;
7400                         }
7401                         /* fallthrough */
7402                 default:
7403                 /* case '*': */
7404                 /* case '?': */
7405                         return 1;
7406                 }
7407                 p++;
7408         }
7409
7410         return 0;
7411 }
7412
7413 /* If we want to use glob() from libc... */
7414 #if !ENABLE_ASH_INTERNAL_GLOB
7415
7416 /* Add the result of glob() to the list */
7417 static void
7418 addglob(const glob_t *pglob)
7419 {
7420         char **p = pglob->gl_pathv;
7421
7422         do {
7423                 addfname(*p);
7424         } while (*++p);
7425 }
7426 static void
7427 expandmeta(struct strlist *str /*, int flag*/)
7428 {
7429         /* TODO - EXP_REDIR */
7430
7431         while (str) {
7432                 char *p;
7433                 glob_t pglob;
7434                 int i;
7435
7436                 if (fflag)
7437                         goto nometa;
7438
7439                 if (!hasmeta(str->text))
7440                         goto nometa;
7441
7442                 INT_OFF;
7443                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7444 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7445 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7446 //
7447 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7448 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7449 // Which means you need to unescape the string, right? Not so fast:
7450 // if there _is_ a file named "file\?" (with backslash), it is returned
7451 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7452 // You DON'T KNOW by looking at the result whether you need to unescape it.
7453 //
7454 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7455 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7456 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7457 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7458 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7459 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7460                 i = glob(p, 0, NULL, &pglob);
7461                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7462                 if (p != str->text)
7463                         free(p);
7464                 switch (i) {
7465                 case 0:
7466 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7467                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7468                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7469                                 goto nometa2;
7470 #endif
7471                         addglob(&pglob);
7472                         globfree(&pglob);
7473                         INT_ON;
7474                         break;
7475                 case GLOB_NOMATCH:
7476  //nometa2:
7477                         globfree(&pglob);
7478                         INT_ON;
7479  nometa:
7480                         *exparg.lastp = str;
7481                         rmescapes(str->text, 0, NULL);
7482                         exparg.lastp = &str->next;
7483                         break;
7484                 default:        /* GLOB_NOSPACE */
7485                         globfree(&pglob);
7486                         INT_ON;
7487                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7488                 }
7489                 str = str->next;
7490         }
7491 }
7492
7493 #else
7494 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7495
7496 /*
7497  * Do metacharacter (i.e. *, ?, [...]) expansion.
7498  */
7499 static void
7500 expmeta(char *expdir, char *enddir, char *name)
7501 {
7502         char *p;
7503         const char *cp;
7504         char *start;
7505         char *endname;
7506         int metaflag;
7507         struct stat statb;
7508         DIR *dirp;
7509         struct dirent *dp;
7510         int atend;
7511         int matchdot;
7512         int esc;
7513
7514         metaflag = 0;
7515         start = name;
7516         for (p = name; esc = 0, *p; p += esc + 1) {
7517                 if (*p == '*' || *p == '?')
7518                         metaflag = 1;
7519                 else if (*p == '[') {
7520                         char *q = p + 1;
7521                         if (*q == '!')
7522                                 q++;
7523                         for (;;) {
7524                                 if (*q == '\\')
7525                                         q++;
7526                                 if (*q == '/' || *q == '\0')
7527                                         break;
7528                                 if (*++q == ']') {
7529                                         metaflag = 1;
7530                                         break;
7531                                 }
7532                         }
7533                 } else {
7534                         if (*p == '\\')
7535                                 esc++;
7536                         if (p[esc] == '/') {
7537                                 if (metaflag)
7538                                         break;
7539                                 start = p + esc + 1;
7540                         }
7541                 }
7542         }
7543         if (metaflag == 0) {    /* we've reached the end of the file name */
7544                 if (enddir != expdir)
7545                         metaflag++;
7546                 p = name;
7547                 do {
7548                         if (*p == '\\')
7549                                 p++;
7550                         *enddir++ = *p;
7551                 } while (*p++);
7552                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7553                         addfname(expdir);
7554                 return;
7555         }
7556         endname = p;
7557         if (name < start) {
7558                 p = name;
7559                 do {
7560                         if (*p == '\\')
7561                                 p++;
7562                         *enddir++ = *p++;
7563                 } while (p < start);
7564         }
7565         if (enddir == expdir) {
7566                 cp = ".";
7567         } else if (enddir == expdir + 1 && *expdir == '/') {
7568                 cp = "/";
7569         } else {
7570                 cp = expdir;
7571                 enddir[-1] = '\0';
7572         }
7573         dirp = opendir(cp);
7574         if (dirp == NULL)
7575                 return;
7576         if (enddir != expdir)
7577                 enddir[-1] = '/';
7578         if (*endname == 0) {
7579                 atend = 1;
7580         } else {
7581                 atend = 0;
7582                 *endname = '\0';
7583                 endname += esc + 1;
7584         }
7585         matchdot = 0;
7586         p = start;
7587         if (*p == '\\')
7588                 p++;
7589         if (*p == '.')
7590                 matchdot++;
7591         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7592                 if (dp->d_name[0] == '.' && !matchdot)
7593                         continue;
7594                 if (pmatch(start, dp->d_name)) {
7595                         if (atend) {
7596                                 strcpy(enddir, dp->d_name);
7597                                 addfname(expdir);
7598                         } else {
7599                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7600                                         continue;
7601                                 p[-1] = '/';
7602                                 expmeta(expdir, p, endname);
7603                         }
7604                 }
7605         }
7606         closedir(dirp);
7607         if (!atend)
7608                 endname[-esc - 1] = esc ? '\\' : '/';
7609 }
7610
7611 static struct strlist *
7612 msort(struct strlist *list, int len)
7613 {
7614         struct strlist *p, *q = NULL;
7615         struct strlist **lpp;
7616         int half;
7617         int n;
7618
7619         if (len <= 1)
7620                 return list;
7621         half = len >> 1;
7622         p = list;
7623         for (n = half; --n >= 0;) {
7624                 q = p;
7625                 p = p->next;
7626         }
7627         q->next = NULL;                 /* terminate first half of list */
7628         q = msort(list, half);          /* sort first half of list */
7629         p = msort(p, len - half);               /* sort second half */
7630         lpp = &list;
7631         for (;;) {
7632 #if ENABLE_LOCALE_SUPPORT
7633                 if (strcoll(p->text, q->text) < 0)
7634 #else
7635                 if (strcmp(p->text, q->text) < 0)
7636 #endif
7637                                                 {
7638                         *lpp = p;
7639                         lpp = &p->next;
7640                         p = *lpp;
7641                         if (p == NULL) {
7642                                 *lpp = q;
7643                                 break;
7644                         }
7645                 } else {
7646                         *lpp = q;
7647                         lpp = &q->next;
7648                         q = *lpp;
7649                         if (q == NULL) {
7650                                 *lpp = p;
7651                                 break;
7652                         }
7653                 }
7654         }
7655         return list;
7656 }
7657
7658 /*
7659  * Sort the results of file name expansion.  It calculates the number of
7660  * strings to sort and then calls msort (short for merge sort) to do the
7661  * work.
7662  */
7663 static struct strlist *
7664 expsort(struct strlist *str)
7665 {
7666         int len;
7667         struct strlist *sp;
7668
7669         len = 0;
7670         for (sp = str; sp; sp = sp->next)
7671                 len++;
7672         return msort(str, len);
7673 }
7674
7675 static void
7676 expandmeta(struct strlist *str /*, int flag*/)
7677 {
7678         /* TODO - EXP_REDIR */
7679
7680         while (str) {
7681                 char *expdir;
7682                 struct strlist **savelastp;
7683                 struct strlist *sp;
7684                 char *p;
7685
7686                 if (fflag)
7687                         goto nometa;
7688                 if (!hasmeta(str->text))
7689                         goto nometa;
7690                 savelastp = exparg.lastp;
7691
7692                 INT_OFF;
7693                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7694                 {
7695                         int i = strlen(str->text);
7696 //BUGGY estimation of how long expanded name can be
7697                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7698                 }
7699                 expmeta(expdir, expdir, p);
7700                 free(expdir);
7701                 if (p != str->text)
7702                         free(p);
7703                 INT_ON;
7704                 if (exparg.lastp == savelastp) {
7705                         /*
7706                          * no matches
7707                          */
7708  nometa:
7709                         *exparg.lastp = str;
7710                         rmescapes(str->text, 0, NULL);
7711                         exparg.lastp = &str->next;
7712                 } else {
7713                         *exparg.lastp = NULL;
7714                         *savelastp = sp = expsort(*savelastp);
7715                         while (sp->next != NULL)
7716                                 sp = sp->next;
7717                         exparg.lastp = &sp->next;
7718                 }
7719                 str = str->next;
7720         }
7721 }
7722 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7723
7724 /*
7725  * Perform variable substitution and command substitution on an argument,
7726  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7727  * perform splitting and file name expansion.  When arglist is NULL, perform
7728  * here document expansion.
7729  */
7730 static void
7731 expandarg(union node *arg, struct arglist *arglist, int flag)
7732 {
7733         struct strlist *sp;
7734         char *p;
7735
7736         argbackq = arg->narg.backquote;
7737         STARTSTACKSTR(expdest);
7738         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7739         argstr(arg->narg.text, flag);
7740         p = _STPUTC('\0', expdest);
7741         expdest = p - 1;
7742         if (arglist == NULL) {
7743                 /* here document expanded */
7744                 goto out;
7745         }
7746         p = grabstackstr(p);
7747         TRACE(("expandarg: p:'%s'\n", p));
7748         exparg.lastp = &exparg.list;
7749         /*
7750          * TODO - EXP_REDIR
7751          */
7752         if (flag & EXP_FULL) {
7753                 ifsbreakup(p, &exparg);
7754                 *exparg.lastp = NULL;
7755                 exparg.lastp = &exparg.list;
7756                 expandmeta(exparg.list /*, flag*/);
7757         } else {
7758                 sp = stzalloc(sizeof(*sp));
7759                 sp->text = p;
7760                 *exparg.lastp = sp;
7761                 exparg.lastp = &sp->next;
7762         }
7763         *exparg.lastp = NULL;
7764         if (exparg.list) {
7765                 *arglist->lastp = exparg.list;
7766                 arglist->lastp = exparg.lastp;
7767         }
7768
7769  out:
7770         ifsfree();
7771 }
7772
7773 /*
7774  * Expand shell variables and backquotes inside a here document.
7775  */
7776 static void
7777 expandhere(union node *arg, int fd)
7778 {
7779         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7780         full_write(fd, stackblock(), expdest - (char *)stackblock());
7781 }
7782
7783 /*
7784  * Returns true if the pattern matches the string.
7785  */
7786 static int
7787 patmatch(char *pattern, const char *string)
7788 {
7789         char *p = preglob(pattern, 0);
7790         int r = pmatch(p, string);
7791         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7792         return r;
7793 }
7794
7795 /*
7796  * See if a pattern matches in a case statement.
7797  */
7798 static int
7799 casematch(union node *pattern, char *val)
7800 {
7801         struct stackmark smark;
7802         int result;
7803
7804         setstackmark(&smark);
7805         argbackq = pattern->narg.backquote;
7806         STARTSTACKSTR(expdest);
7807         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7808         STACKSTRNUL(expdest);
7809         ifsfree();
7810         result = patmatch(stackblock(), val);
7811         popstackmark(&smark);
7812         return result;
7813 }
7814
7815
7816 /* ============ find_command */
7817
7818 struct builtincmd {
7819         const char *name;
7820         int (*builtin)(int, char **) FAST_FUNC;
7821         /* unsigned flags; */
7822 };
7823 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7824 /* "regular" builtins always take precedence over commands,
7825  * regardless of PATH=....%builtin... position */
7826 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7827 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7828
7829 struct cmdentry {
7830         smallint cmdtype;       /* CMDxxx */
7831         union param {
7832                 int index;
7833                 /* index >= 0 for commands without path (slashes) */
7834                 /* (TODO: what exactly does the value mean? PATH position?) */
7835                 /* index == -1 for commands with slashes */
7836                 /* index == (-2 - applet_no) for NOFORK applets */
7837                 const struct builtincmd *cmd;
7838                 struct funcnode *func;
7839         } u;
7840 };
7841 /* values of cmdtype */
7842 #define CMDUNKNOWN      -1      /* no entry in table for command */
7843 #define CMDNORMAL       0       /* command is an executable program */
7844 #define CMDFUNCTION     1       /* command is a shell function */
7845 #define CMDBUILTIN      2       /* command is a shell builtin */
7846
7847 /* action to find_command() */
7848 #define DO_ERR          0x01    /* prints errors */
7849 #define DO_ABS          0x02    /* checks absolute paths */
7850 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7851 #define DO_ALTPATH      0x08    /* using alternate path */
7852 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7853
7854 static void find_command(char *, struct cmdentry *, int, const char *);
7855
7856
7857 /* ============ Hashing commands */
7858
7859 /*
7860  * When commands are first encountered, they are entered in a hash table.
7861  * This ensures that a full path search will not have to be done for them
7862  * on each invocation.
7863  *
7864  * We should investigate converting to a linear search, even though that
7865  * would make the command name "hash" a misnomer.
7866  */
7867
7868 struct tblentry {
7869         struct tblentry *next;  /* next entry in hash chain */
7870         union param param;      /* definition of builtin function */
7871         smallint cmdtype;       /* CMDxxx */
7872         char rehash;            /* if set, cd done since entry created */
7873         char cmdname[1];        /* name of command */
7874 };
7875
7876 static struct tblentry **cmdtable;
7877 #define INIT_G_cmdtable() do { \
7878         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7879 } while (0)
7880
7881 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7882
7883
7884 static void
7885 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7886 {
7887 #if ENABLE_FEATURE_SH_STANDALONE
7888         if (applet_no >= 0) {
7889                 if (APPLET_IS_NOEXEC(applet_no)) {
7890                         clearenv();
7891                         while (*envp)
7892                                 putenv(*envp++);
7893                         popredir(/*drop:*/ 1);
7894                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7895                 }
7896                 /* re-exec ourselves with the new arguments */
7897                 execve(bb_busybox_exec_path, argv, envp);
7898                 /* If they called chroot or otherwise made the binary no longer
7899                  * executable, fall through */
7900         }
7901 #endif
7902
7903  repeat:
7904 #ifdef SYSV
7905         do {
7906                 execve(cmd, argv, envp);
7907         } while (errno == EINTR);
7908 #else
7909         execve(cmd, argv, envp);
7910 #endif
7911         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7912                 /* Run "cmd" as a shell script:
7913                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7914                  * "If the execve() function fails with ENOEXEC, the shell
7915                  * shall execute a command equivalent to having a shell invoked
7916                  * with the command name as its first operand,
7917                  * with any remaining arguments passed to the new shell"
7918                  *
7919                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7920                  * just call ourselves.
7921                  *
7922                  * Note that bash reads ~80 chars of the file, and if it sees
7923                  * a zero byte before it sees newline, it doesn't try to
7924                  * interpret it, but fails with "cannot execute binary file"
7925                  * message and exit code 126. For one, this prevents attempts
7926                  * to interpret foreign ELF binaries as shell scripts.
7927                  */
7928                 argv[0] = (char*) cmd;
7929                 cmd = bb_busybox_exec_path;
7930                 /* NB: this is only possible because all callers of shellexec()
7931                  * ensure that the argv[-1] slot exists!
7932                  */
7933                 argv--;
7934                 argv[0] = (char*) "ash";
7935                 goto repeat;
7936         }
7937 }
7938
7939 /*
7940  * Exec a program.  Never returns.  If you change this routine, you may
7941  * have to change the find_command routine as well.
7942  * argv[-1] must exist and be writable! See tryexec() for why.
7943  */
7944 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7945 static void shellexec(char *prog, char **argv, const char *path, int idx)
7946 {
7947         char *cmdname;
7948         int e;
7949         char **envp;
7950         int exerrno;
7951         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7952
7953         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
7954         if (strchr(prog, '/') != NULL
7955 #if ENABLE_FEATURE_SH_STANDALONE
7956          || (applet_no = find_applet_by_name(prog)) >= 0
7957 #endif
7958         ) {
7959                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7960                 if (applet_no >= 0) {
7961                         /* We tried execing ourself, but it didn't work.
7962                          * Maybe /proc/self/exe doesn't exist?
7963                          * Try $PATH search.
7964                          */
7965                         goto try_PATH;
7966                 }
7967                 e = errno;
7968         } else {
7969  try_PATH:
7970                 e = ENOENT;
7971                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7972                         if (--idx < 0 && pathopt == NULL) {
7973                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7974                                 if (errno != ENOENT && errno != ENOTDIR)
7975                                         e = errno;
7976                         }
7977                         stunalloc(cmdname);
7978                 }
7979         }
7980
7981         /* Map to POSIX errors */
7982         switch (e) {
7983         case EACCES:
7984                 exerrno = 126;
7985                 break;
7986         case ENOENT:
7987                 exerrno = 127;
7988                 break;
7989         default:
7990                 exerrno = 2;
7991                 break;
7992         }
7993         exitstatus = exerrno;
7994         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7995                 prog, e, suppress_int));
7996         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7997         /* NOTREACHED */
7998 }
7999
8000 static void
8001 printentry(struct tblentry *cmdp)
8002 {
8003         int idx;
8004         const char *path;
8005         char *name;
8006
8007         idx = cmdp->param.index;
8008         path = pathval();
8009         do {
8010                 name = path_advance(&path, cmdp->cmdname);
8011                 stunalloc(name);
8012         } while (--idx >= 0);
8013         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8014 }
8015
8016 /*
8017  * Clear out command entries.  The argument specifies the first entry in
8018  * PATH which has changed.
8019  */
8020 static void
8021 clearcmdentry(int firstchange)
8022 {
8023         struct tblentry **tblp;
8024         struct tblentry **pp;
8025         struct tblentry *cmdp;
8026
8027         INT_OFF;
8028         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8029                 pp = tblp;
8030                 while ((cmdp = *pp) != NULL) {
8031                         if ((cmdp->cmdtype == CMDNORMAL &&
8032                              cmdp->param.index >= firstchange)
8033                          || (cmdp->cmdtype == CMDBUILTIN &&
8034                              builtinloc >= firstchange)
8035                         ) {
8036                                 *pp = cmdp->next;
8037                                 free(cmdp);
8038                         } else {
8039                                 pp = &cmdp->next;
8040                         }
8041                 }
8042         }
8043         INT_ON;
8044 }
8045
8046 /*
8047  * Locate a command in the command hash table.  If "add" is nonzero,
8048  * add the command to the table if it is not already present.  The
8049  * variable "lastcmdentry" is set to point to the address of the link
8050  * pointing to the entry, so that delete_cmd_entry can delete the
8051  * entry.
8052  *
8053  * Interrupts must be off if called with add != 0.
8054  */
8055 static struct tblentry **lastcmdentry;
8056
8057 static struct tblentry *
8058 cmdlookup(const char *name, int add)
8059 {
8060         unsigned int hashval;
8061         const char *p;
8062         struct tblentry *cmdp;
8063         struct tblentry **pp;
8064
8065         p = name;
8066         hashval = (unsigned char)*p << 4;
8067         while (*p)
8068                 hashval += (unsigned char)*p++;
8069         hashval &= 0x7FFF;
8070         pp = &cmdtable[hashval % CMDTABLESIZE];
8071         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8072                 if (strcmp(cmdp->cmdname, name) == 0)
8073                         break;
8074                 pp = &cmdp->next;
8075         }
8076         if (add && cmdp == NULL) {
8077                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8078                                 + strlen(name)
8079                                 /* + 1 - already done because
8080                                  * tblentry::cmdname is char[1] */);
8081                 /*cmdp->next = NULL; - ckzalloc did it */
8082                 cmdp->cmdtype = CMDUNKNOWN;
8083                 strcpy(cmdp->cmdname, name);
8084         }
8085         lastcmdentry = pp;
8086         return cmdp;
8087 }
8088
8089 /*
8090  * Delete the command entry returned on the last lookup.
8091  */
8092 static void
8093 delete_cmd_entry(void)
8094 {
8095         struct tblentry *cmdp;
8096
8097         INT_OFF;
8098         cmdp = *lastcmdentry;
8099         *lastcmdentry = cmdp->next;
8100         if (cmdp->cmdtype == CMDFUNCTION)
8101                 freefunc(cmdp->param.func);
8102         free(cmdp);
8103         INT_ON;
8104 }
8105
8106 /*
8107  * Add a new command entry, replacing any existing command entry for
8108  * the same name - except special builtins.
8109  */
8110 static void
8111 addcmdentry(char *name, struct cmdentry *entry)
8112 {
8113         struct tblentry *cmdp;
8114
8115         cmdp = cmdlookup(name, 1);
8116         if (cmdp->cmdtype == CMDFUNCTION) {
8117                 freefunc(cmdp->param.func);
8118         }
8119         cmdp->cmdtype = entry->cmdtype;
8120         cmdp->param = entry->u;
8121         cmdp->rehash = 0;
8122 }
8123
8124 static int FAST_FUNC
8125 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8126 {
8127         struct tblentry **pp;
8128         struct tblentry *cmdp;
8129         int c;
8130         struct cmdentry entry;
8131         char *name;
8132
8133         if (nextopt("r") != '\0') {
8134                 clearcmdentry(0);
8135                 return 0;
8136         }
8137
8138         if (*argptr == NULL) {
8139                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8140                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8141                                 if (cmdp->cmdtype == CMDNORMAL)
8142                                         printentry(cmdp);
8143                         }
8144                 }
8145                 return 0;
8146         }
8147
8148         c = 0;
8149         while ((name = *argptr) != NULL) {
8150                 cmdp = cmdlookup(name, 0);
8151                 if (cmdp != NULL
8152                  && (cmdp->cmdtype == CMDNORMAL
8153                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8154                 ) {
8155                         delete_cmd_entry();
8156                 }
8157                 find_command(name, &entry, DO_ERR, pathval());
8158                 if (entry.cmdtype == CMDUNKNOWN)
8159                         c = 1;
8160                 argptr++;
8161         }
8162         return c;
8163 }
8164
8165 /*
8166  * Called when a cd is done.  Marks all commands so the next time they
8167  * are executed they will be rehashed.
8168  */
8169 static void
8170 hashcd(void)
8171 {
8172         struct tblentry **pp;
8173         struct tblentry *cmdp;
8174
8175         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8176                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8177                         if (cmdp->cmdtype == CMDNORMAL
8178                          || (cmdp->cmdtype == CMDBUILTIN
8179                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8180                              && builtinloc > 0)
8181                         ) {
8182                                 cmdp->rehash = 1;
8183                         }
8184                 }
8185         }
8186 }
8187
8188 /*
8189  * Fix command hash table when PATH changed.
8190  * Called before PATH is changed.  The argument is the new value of PATH;
8191  * pathval() still returns the old value at this point.
8192  * Called with interrupts off.
8193  */
8194 static void FAST_FUNC
8195 changepath(const char *new)
8196 {
8197         const char *old;
8198         int firstchange;
8199         int idx;
8200         int idx_bltin;
8201
8202         old = pathval();
8203         firstchange = 9999;     /* assume no change */
8204         idx = 0;
8205         idx_bltin = -1;
8206         for (;;) {
8207                 if (*old != *new) {
8208                         firstchange = idx;
8209                         if ((*old == '\0' && *new == ':')
8210                          || (*old == ':' && *new == '\0')
8211                         ) {
8212                                 firstchange++;
8213                         }
8214                         old = new;      /* ignore subsequent differences */
8215                 }
8216                 if (*new == '\0')
8217                         break;
8218                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8219                         idx_bltin = idx;
8220                 if (*new == ':')
8221                         idx++;
8222                 new++;
8223                 old++;
8224         }
8225         if (builtinloc < 0 && idx_bltin >= 0)
8226                 builtinloc = idx_bltin;             /* zap builtins */
8227         if (builtinloc >= 0 && idx_bltin < 0)
8228                 firstchange = 0;
8229         clearcmdentry(firstchange);
8230         builtinloc = idx_bltin;
8231 }
8232 enum {
8233         TEOF,
8234         TNL,
8235         TREDIR,
8236         TWORD,
8237         TSEMI,
8238         TBACKGND,
8239         TAND,
8240         TOR,
8241         TPIPE,
8242         TLP,
8243         TRP,
8244         TENDCASE,
8245         TENDBQUOTE,
8246         TNOT,
8247         TCASE,
8248         TDO,
8249         TDONE,
8250         TELIF,
8251         TELSE,
8252         TESAC,
8253         TFI,
8254         TFOR,
8255 #if BASH_FUNCTION
8256         TFUNCTION,
8257 #endif
8258         TIF,
8259         TIN,
8260         TTHEN,
8261         TUNTIL,
8262         TWHILE,
8263         TBEGIN,
8264         TEND
8265 };
8266 typedef smallint token_id_t;
8267
8268 /* Nth bit indicates if token marks the end of a list */
8269 enum {
8270         tokendlist = 0
8271         /*  0 */ | (1u << TEOF)
8272         /*  1 */ | (0u << TNL)
8273         /*  2 */ | (0u << TREDIR)
8274         /*  3 */ | (0u << TWORD)
8275         /*  4 */ | (0u << TSEMI)
8276         /*  5 */ | (0u << TBACKGND)
8277         /*  6 */ | (0u << TAND)
8278         /*  7 */ | (0u << TOR)
8279         /*  8 */ | (0u << TPIPE)
8280         /*  9 */ | (0u << TLP)
8281         /* 10 */ | (1u << TRP)
8282         /* 11 */ | (1u << TENDCASE)
8283         /* 12 */ | (1u << TENDBQUOTE)
8284         /* 13 */ | (0u << TNOT)
8285         /* 14 */ | (0u << TCASE)
8286         /* 15 */ | (1u << TDO)
8287         /* 16 */ | (1u << TDONE)
8288         /* 17 */ | (1u << TELIF)
8289         /* 18 */ | (1u << TELSE)
8290         /* 19 */ | (1u << TESAC)
8291         /* 20 */ | (1u << TFI)
8292         /* 21 */ | (0u << TFOR)
8293 #if BASH_FUNCTION
8294         /* 22 */ | (0u << TFUNCTION)
8295 #endif
8296         /* 23 */ | (0u << TIF)
8297         /* 24 */ | (0u << TIN)
8298         /* 25 */ | (1u << TTHEN)
8299         /* 26 */ | (0u << TUNTIL)
8300         /* 27 */ | (0u << TWHILE)
8301         /* 28 */ | (0u << TBEGIN)
8302         /* 29 */ | (1u << TEND)
8303         , /* thus far 29 bits used */
8304 };
8305
8306 static const char *const tokname_array[] = {
8307         "end of file",
8308         "newline",
8309         "redirection",
8310         "word",
8311         ";",
8312         "&",
8313         "&&",
8314         "||",
8315         "|",
8316         "(",
8317         ")",
8318         ";;",
8319         "`",
8320 #define KWDOFFSET 13
8321         /* the following are keywords */
8322         "!",
8323         "case",
8324         "do",
8325         "done",
8326         "elif",
8327         "else",
8328         "esac",
8329         "fi",
8330         "for",
8331 #if BASH_FUNCTION
8332         "function",
8333 #endif
8334         "if",
8335         "in",
8336         "then",
8337         "until",
8338         "while",
8339         "{",
8340         "}",
8341 };
8342
8343 /* Wrapper around strcmp for qsort/bsearch/... */
8344 static int
8345 pstrcmp(const void *a, const void *b)
8346 {
8347         return strcmp((char*)a, *(char**)b);
8348 }
8349
8350 static const char *const *
8351 findkwd(const char *s)
8352 {
8353         return bsearch(s, tokname_array + KWDOFFSET,
8354                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8355                         sizeof(tokname_array[0]), pstrcmp);
8356 }
8357
8358 /*
8359  * Locate and print what a word is...
8360  */
8361 static int
8362 describe_command(char *command, const char *path, int describe_command_verbose)
8363 {
8364         struct cmdentry entry;
8365 #if ENABLE_ASH_ALIAS
8366         const struct alias *ap;
8367 #endif
8368
8369         path = path ? path : pathval();
8370
8371         if (describe_command_verbose) {
8372                 out1str(command);
8373         }
8374
8375         /* First look at the keywords */
8376         if (findkwd(command)) {
8377                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8378                 goto out;
8379         }
8380
8381 #if ENABLE_ASH_ALIAS
8382         /* Then look at the aliases */
8383         ap = lookupalias(command, 0);
8384         if (ap != NULL) {
8385                 if (!describe_command_verbose) {
8386                         out1str("alias ");
8387                         printalias(ap);
8388                         return 0;
8389                 }
8390                 out1fmt(" is an alias for %s", ap->val);
8391                 goto out;
8392         }
8393 #endif
8394         /* Brute force */
8395         find_command(command, &entry, DO_ABS, path);
8396
8397         switch (entry.cmdtype) {
8398         case CMDNORMAL: {
8399                 int j = entry.u.index;
8400                 char *p;
8401                 if (j < 0) {
8402                         p = command;
8403                 } else {
8404                         do {
8405                                 p = path_advance(&path, command);
8406                                 stunalloc(p);
8407                         } while (--j >= 0);
8408                 }
8409                 if (describe_command_verbose) {
8410                         out1fmt(" is %s", p);
8411                 } else {
8412                         out1str(p);
8413                 }
8414                 break;
8415         }
8416
8417         case CMDFUNCTION:
8418                 if (describe_command_verbose) {
8419                         out1str(" is a shell function");
8420                 } else {
8421                         out1str(command);
8422                 }
8423                 break;
8424
8425         case CMDBUILTIN:
8426                 if (describe_command_verbose) {
8427                         out1fmt(" is a %sshell builtin",
8428                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8429                                         "special " : nullstr
8430                         );
8431                 } else {
8432                         out1str(command);
8433                 }
8434                 break;
8435
8436         default:
8437                 if (describe_command_verbose) {
8438                         out1str(": not found\n");
8439                 }
8440                 return 127;
8441         }
8442  out:
8443         out1str("\n");
8444         return 0;
8445 }
8446
8447 static int FAST_FUNC
8448 typecmd(int argc UNUSED_PARAM, char **argv)
8449 {
8450         int i = 1;
8451         int err = 0;
8452         int verbose = 1;
8453
8454         /* type -p ... ? (we don't bother checking for 'p') */
8455         if (argv[1] && argv[1][0] == '-') {
8456                 i++;
8457                 verbose = 0;
8458         }
8459         while (argv[i]) {
8460                 err |= describe_command(argv[i++], NULL, verbose);
8461         }
8462         return err;
8463 }
8464
8465 #if ENABLE_ASH_CMDCMD
8466 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8467 static char **
8468 parse_command_args(char **argv, const char **path)
8469 {
8470         char *cp, c;
8471
8472         for (;;) {
8473                 cp = *++argv;
8474                 if (!cp)
8475                         return NULL;
8476                 if (*cp++ != '-')
8477                         break;
8478                 c = *cp++;
8479                 if (!c)
8480                         break;
8481                 if (c == '-' && !*cp) {
8482                         if (!*++argv)
8483                                 return NULL;
8484                         break;
8485                 }
8486                 do {
8487                         switch (c) {
8488                         case 'p':
8489                                 *path = bb_default_path;
8490                                 break;
8491                         default:
8492                                 /* run 'typecmd' for other options */
8493                                 return NULL;
8494                         }
8495                         c = *cp++;
8496                 } while (c);
8497         }
8498         return argv;
8499 }
8500
8501 static int FAST_FUNC
8502 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8503 {
8504         char *cmd;
8505         int c;
8506         enum {
8507                 VERIFY_BRIEF = 1,
8508                 VERIFY_VERBOSE = 2,
8509         } verify = 0;
8510         const char *path = NULL;
8511
8512         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8513          * never reaches this function.
8514          */
8515
8516         while ((c = nextopt("pvV")) != '\0')
8517                 if (c == 'V')
8518                         verify |= VERIFY_VERBOSE;
8519                 else if (c == 'v')
8520                         /*verify |= VERIFY_BRIEF*/;
8521 #if DEBUG
8522                 else if (c != 'p')
8523                         abort();
8524 #endif
8525                 else
8526                         path = bb_default_path;
8527
8528         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8529         cmd = *argptr;
8530         if (/*verify && */ cmd)
8531                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8532
8533         return 0;
8534 }
8535 #endif
8536
8537
8538 /*static int funcblocksize;     // size of structures in function */
8539 /*static int funcstringsize;    // size of strings in node */
8540 static void *funcblock;         /* block to allocate function from */
8541 static char *funcstring_end;    /* end of block to allocate strings from */
8542
8543 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8544         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8545         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8546         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8547         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8548         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8549         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8550         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8551         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8552         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8553         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8554         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8555         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8556         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8557         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8558         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8559         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8560         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8561 #if BASH_REDIR_OUTPUT
8562         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8563 #endif
8564         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8565         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8566         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8567         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8568         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8569         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8570         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8571         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8572         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8573 };
8574
8575 static int calcsize(int funcblocksize, union node *n);
8576
8577 static int
8578 sizenodelist(int funcblocksize, struct nodelist *lp)
8579 {
8580         while (lp) {
8581                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8582                 funcblocksize = calcsize(funcblocksize, lp->n);
8583                 lp = lp->next;
8584         }
8585         return funcblocksize;
8586 }
8587
8588 static int
8589 calcsize(int funcblocksize, union node *n)
8590 {
8591         if (n == NULL)
8592                 return funcblocksize;
8593         funcblocksize += nodesize[n->type];
8594         switch (n->type) {
8595         case NCMD:
8596                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8597                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8598                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8599                 break;
8600         case NPIPE:
8601                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8602                 break;
8603         case NREDIR:
8604         case NBACKGND:
8605         case NSUBSHELL:
8606                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8607                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8608                 break;
8609         case NAND:
8610         case NOR:
8611         case NSEMI:
8612         case NWHILE:
8613         case NUNTIL:
8614                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8615                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8616                 break;
8617         case NIF:
8618                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8619                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8620                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8621                 break;
8622         case NFOR:
8623                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8624                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8625                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8626                 break;
8627         case NCASE:
8628                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8629                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8630                 break;
8631         case NCLIST:
8632                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8633                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8634                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8635                 break;
8636         case NDEFUN:
8637         case NARG:
8638                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8639                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8640                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8641                 break;
8642         case NTO:
8643 #if BASH_REDIR_OUTPUT
8644         case NTO2:
8645 #endif
8646         case NCLOBBER:
8647         case NFROM:
8648         case NFROMTO:
8649         case NAPPEND:
8650                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8651                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8652                 break;
8653         case NTOFD:
8654         case NFROMFD:
8655                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8656                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8657         break;
8658         case NHERE:
8659         case NXHERE:
8660                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8661                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8662                 break;
8663         case NNOT:
8664                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8665                 break;
8666         };
8667         return funcblocksize;
8668 }
8669
8670 static char *
8671 nodeckstrdup(char *s)
8672 {
8673         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8674         return strcpy(funcstring_end, s);
8675 }
8676
8677 static union node *copynode(union node *);
8678
8679 static struct nodelist *
8680 copynodelist(struct nodelist *lp)
8681 {
8682         struct nodelist *start;
8683         struct nodelist **lpp;
8684
8685         lpp = &start;
8686         while (lp) {
8687                 *lpp = funcblock;
8688                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8689                 (*lpp)->n = copynode(lp->n);
8690                 lp = lp->next;
8691                 lpp = &(*lpp)->next;
8692         }
8693         *lpp = NULL;
8694         return start;
8695 }
8696
8697 static union node *
8698 copynode(union node *n)
8699 {
8700         union node *new;
8701
8702         if (n == NULL)
8703                 return NULL;
8704         new = funcblock;
8705         funcblock = (char *) funcblock + nodesize[n->type];
8706
8707         switch (n->type) {
8708         case NCMD:
8709                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8710                 new->ncmd.args = copynode(n->ncmd.args);
8711                 new->ncmd.assign = copynode(n->ncmd.assign);
8712                 break;
8713         case NPIPE:
8714                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8715                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8716                 break;
8717         case NREDIR:
8718         case NBACKGND:
8719         case NSUBSHELL:
8720                 new->nredir.redirect = copynode(n->nredir.redirect);
8721                 new->nredir.n = copynode(n->nredir.n);
8722                 break;
8723         case NAND:
8724         case NOR:
8725         case NSEMI:
8726         case NWHILE:
8727         case NUNTIL:
8728                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8729                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8730                 break;
8731         case NIF:
8732                 new->nif.elsepart = copynode(n->nif.elsepart);
8733                 new->nif.ifpart = copynode(n->nif.ifpart);
8734                 new->nif.test = copynode(n->nif.test);
8735                 break;
8736         case NFOR:
8737                 new->nfor.var = nodeckstrdup(n->nfor.var);
8738                 new->nfor.body = copynode(n->nfor.body);
8739                 new->nfor.args = copynode(n->nfor.args);
8740                 break;
8741         case NCASE:
8742                 new->ncase.cases = copynode(n->ncase.cases);
8743                 new->ncase.expr = copynode(n->ncase.expr);
8744                 break;
8745         case NCLIST:
8746                 new->nclist.body = copynode(n->nclist.body);
8747                 new->nclist.pattern = copynode(n->nclist.pattern);
8748                 new->nclist.next = copynode(n->nclist.next);
8749                 break;
8750         case NDEFUN:
8751         case NARG:
8752                 new->narg.backquote = copynodelist(n->narg.backquote);
8753                 new->narg.text = nodeckstrdup(n->narg.text);
8754                 new->narg.next = copynode(n->narg.next);
8755                 break;
8756         case NTO:
8757 #if BASH_REDIR_OUTPUT
8758         case NTO2:
8759 #endif
8760         case NCLOBBER:
8761         case NFROM:
8762         case NFROMTO:
8763         case NAPPEND:
8764                 new->nfile.fname = copynode(n->nfile.fname);
8765                 new->nfile.fd = n->nfile.fd;
8766                 new->nfile.next = copynode(n->nfile.next);
8767                 break;
8768         case NTOFD:
8769         case NFROMFD:
8770                 new->ndup.vname = copynode(n->ndup.vname);
8771                 new->ndup.dupfd = n->ndup.dupfd;
8772                 new->ndup.fd = n->ndup.fd;
8773                 new->ndup.next = copynode(n->ndup.next);
8774                 break;
8775         case NHERE:
8776         case NXHERE:
8777                 new->nhere.doc = copynode(n->nhere.doc);
8778                 new->nhere.fd = n->nhere.fd;
8779                 new->nhere.next = copynode(n->nhere.next);
8780                 break;
8781         case NNOT:
8782                 new->nnot.com = copynode(n->nnot.com);
8783                 break;
8784         };
8785         new->type = n->type;
8786         return new;
8787 }
8788
8789 /*
8790  * Make a copy of a parse tree.
8791  */
8792 static struct funcnode *
8793 copyfunc(union node *n)
8794 {
8795         struct funcnode *f;
8796         size_t blocksize;
8797
8798         /*funcstringsize = 0;*/
8799         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8800         f = ckzalloc(blocksize /* + funcstringsize */);
8801         funcblock = (char *) f + offsetof(struct funcnode, n);
8802         funcstring_end = (char *) f + blocksize;
8803         copynode(n);
8804         /* f->count = 0; - ckzalloc did it */
8805         return f;
8806 }
8807
8808 /*
8809  * Define a shell function.
8810  */
8811 static void
8812 defun(union node *func)
8813 {
8814         struct cmdentry entry;
8815
8816         INT_OFF;
8817         entry.cmdtype = CMDFUNCTION;
8818         entry.u.func = copyfunc(func);
8819         addcmdentry(func->narg.text, &entry);
8820         INT_ON;
8821 }
8822
8823 /* Reasons for skipping commands (see comment on breakcmd routine) */
8824 #define SKIPBREAK      (1 << 0)
8825 #define SKIPCONT       (1 << 1)
8826 #define SKIPFUNC       (1 << 2)
8827 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8828 static int skipcount;           /* number of levels to skip */
8829 static int funcnest;            /* depth of function calls */
8830 static int loopnest;            /* current loop nesting level */
8831
8832 /* Forward decl way out to parsing code - dotrap needs it */
8833 static int evalstring(char *s, int flags);
8834
8835 /* Called to execute a trap.
8836  * Single callsite - at the end of evaltree().
8837  * If we return non-zero, evaltree raises EXEXIT exception.
8838  *
8839  * Perhaps we should avoid entering new trap handlers
8840  * while we are executing a trap handler. [is it a TODO?]
8841  */
8842 static void
8843 dotrap(void)
8844 {
8845         uint8_t *g;
8846         int sig;
8847         uint8_t last_status;
8848
8849         if (!pending_sig)
8850                 return;
8851
8852         last_status = exitstatus;
8853         pending_sig = 0;
8854         barrier();
8855
8856         TRACE(("dotrap entered\n"));
8857         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8858                 char *p;
8859
8860                 if (!*g)
8861                         continue;
8862
8863                 if (evalskip) {
8864                         pending_sig = sig;
8865                         break;
8866                 }
8867
8868                 p = trap[sig];
8869                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8870                  * don't upset it by resetting gotsig[SIGINT-1] */
8871                 if (sig == SIGINT && !p)
8872                         continue;
8873
8874                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8875                 *g = 0;
8876                 if (!p)
8877                         continue;
8878                 evalstring(p, 0);
8879         }
8880         exitstatus = last_status;
8881         TRACE(("dotrap returns\n"));
8882 }
8883
8884 /* forward declarations - evaluation is fairly recursive business... */
8885 static int evalloop(union node *, int);
8886 static int evalfor(union node *, int);
8887 static int evalcase(union node *, int);
8888 static int evalsubshell(union node *, int);
8889 static void expredir(union node *);
8890 static int evalpipe(union node *, int);
8891 static int evalcommand(union node *, int);
8892 static int evalbltin(const struct builtincmd *, int, char **, int);
8893 static void prehash(union node *);
8894
8895 /*
8896  * Evaluate a parse tree.  The value is left in the global variable
8897  * exitstatus.
8898  */
8899 static int
8900 evaltree(union node *n, int flags)
8901 {
8902         int checkexit = 0;
8903         int (*evalfn)(union node *, int);
8904         int status = 0;
8905
8906         if (n == NULL) {
8907                 TRACE(("evaltree(NULL) called\n"));
8908                 goto out;
8909         }
8910         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8911
8912         dotrap();
8913
8914         switch (n->type) {
8915         default:
8916 #if DEBUG
8917                 out1fmt("Node type = %d\n", n->type);
8918                 fflush_all();
8919                 break;
8920 #endif
8921         case NNOT:
8922                 status = !evaltree(n->nnot.com, EV_TESTED);
8923                 goto setstatus;
8924         case NREDIR:
8925                 expredir(n->nredir.redirect);
8926                 pushredir(n->nredir.redirect);
8927                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8928                 if (!status) {
8929                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8930                 }
8931                 if (n->nredir.redirect)
8932                         popredir(/*drop:*/ 0);
8933                 goto setstatus;
8934         case NCMD:
8935                 evalfn = evalcommand;
8936  checkexit:
8937                 if (eflag && !(flags & EV_TESTED))
8938                         checkexit = ~0;
8939                 goto calleval;
8940         case NFOR:
8941                 evalfn = evalfor;
8942                 goto calleval;
8943         case NWHILE:
8944         case NUNTIL:
8945                 evalfn = evalloop;
8946                 goto calleval;
8947         case NSUBSHELL:
8948         case NBACKGND:
8949                 evalfn = evalsubshell;
8950                 goto checkexit;
8951         case NPIPE:
8952                 evalfn = evalpipe;
8953                 goto checkexit;
8954         case NCASE:
8955                 evalfn = evalcase;
8956                 goto calleval;
8957         case NAND:
8958         case NOR:
8959         case NSEMI: {
8960
8961 #if NAND + 1 != NOR
8962 #error NAND + 1 != NOR
8963 #endif
8964 #if NOR + 1 != NSEMI
8965 #error NOR + 1 != NSEMI
8966 #endif
8967                 unsigned is_or = n->type - NAND;
8968                 status = evaltree(
8969                         n->nbinary.ch1,
8970                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8971                 );
8972                 if ((!status) == is_or || evalskip)
8973                         break;
8974                 n = n->nbinary.ch2;
8975  evaln:
8976                 evalfn = evaltree;
8977  calleval:
8978                 status = evalfn(n, flags);
8979                 goto setstatus;
8980         }
8981         case NIF:
8982                 status = evaltree(n->nif.test, EV_TESTED);
8983                 if (evalskip)
8984                         break;
8985                 if (!status) {
8986                         n = n->nif.ifpart;
8987                         goto evaln;
8988                 }
8989                 if (n->nif.elsepart) {
8990                         n = n->nif.elsepart;
8991                         goto evaln;
8992                 }
8993                 status = 0;
8994                 goto setstatus;
8995         case NDEFUN:
8996                 defun(n);
8997                 /* Not necessary. To test it:
8998                  * "false; f() { qwerty; }; echo $?" should print 0.
8999                  */
9000                 /* status = 0; */
9001  setstatus:
9002                 exitstatus = status;
9003                 break;
9004         }
9005  out:
9006         /* Order of checks below is important:
9007          * signal handlers trigger before exit caused by "set -e".
9008          */
9009         dotrap();
9010
9011         if (checkexit & status)
9012                 raise_exception(EXEXIT);
9013         if (flags & EV_EXIT)
9014                 raise_exception(EXEXIT);
9015
9016         TRACE(("leaving evaltree (no interrupts)\n"));
9017         return exitstatus;
9018 }
9019
9020 static int
9021 skiploop(void)
9022 {
9023         int skip = evalskip;
9024
9025         switch (skip) {
9026         case 0:
9027                 break;
9028         case SKIPBREAK:
9029         case SKIPCONT:
9030                 if (--skipcount <= 0) {
9031                         evalskip = 0;
9032                         break;
9033                 }
9034                 skip = SKIPBREAK;
9035                 break;
9036         }
9037         return skip;
9038 }
9039
9040 static int
9041 evalloop(union node *n, int flags)
9042 {
9043         int skip;
9044         int status;
9045
9046         loopnest++;
9047         status = 0;
9048         flags &= EV_TESTED;
9049         do {
9050                 int i;
9051
9052                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9053                 skip = skiploop();
9054                 if (skip == SKIPFUNC)
9055                         status = i;
9056                 if (skip)
9057                         continue;
9058                 if (n->type != NWHILE)
9059                         i = !i;
9060                 if (i != 0)
9061                         break;
9062                 status = evaltree(n->nbinary.ch2, flags);
9063                 skip = skiploop();
9064         } while (!(skip & ~SKIPCONT));
9065         loopnest--;
9066
9067         return status;
9068 }
9069
9070 static int
9071 evalfor(union node *n, int flags)
9072 {
9073         struct arglist arglist;
9074         union node *argp;
9075         struct strlist *sp;
9076         struct stackmark smark;
9077         int status = 0;
9078
9079         setstackmark(&smark);
9080         arglist.list = NULL;
9081         arglist.lastp = &arglist.list;
9082         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9083                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9084         }
9085         *arglist.lastp = NULL;
9086
9087         loopnest++;
9088         flags &= EV_TESTED;
9089         for (sp = arglist.list; sp; sp = sp->next) {
9090                 setvar0(n->nfor.var, sp->text);
9091                 status = evaltree(n->nfor.body, flags);
9092                 if (skiploop() & ~SKIPCONT)
9093                         break;
9094         }
9095         loopnest--;
9096         popstackmark(&smark);
9097
9098         return status;
9099 }
9100
9101 static int
9102 evalcase(union node *n, int flags)
9103 {
9104         union node *cp;
9105         union node *patp;
9106         struct arglist arglist;
9107         struct stackmark smark;
9108         int status = 0;
9109
9110         setstackmark(&smark);
9111         arglist.list = NULL;
9112         arglist.lastp = &arglist.list;
9113         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9114         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9115                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9116                         if (casematch(patp, arglist.list->text)) {
9117                                 /* Ensure body is non-empty as otherwise
9118                                  * EV_EXIT may prevent us from setting the
9119                                  * exit status.
9120                                  */
9121                                 if (evalskip == 0 && cp->nclist.body) {
9122                                         status = evaltree(cp->nclist.body, flags);
9123                                 }
9124                                 goto out;
9125                         }
9126                 }
9127         }
9128  out:
9129         popstackmark(&smark);
9130
9131         return status;
9132 }
9133
9134 /*
9135  * Kick off a subshell to evaluate a tree.
9136  */
9137 static int
9138 evalsubshell(union node *n, int flags)
9139 {
9140         struct job *jp;
9141         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9142         int status;
9143
9144         expredir(n->nredir.redirect);
9145         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9146                 goto nofork;
9147         INT_OFF;
9148         if (backgnd == FORK_FG)
9149                 get_tty_state();
9150         jp = makejob(/*n,*/ 1);
9151         if (forkshell(jp, n, backgnd) == 0) {
9152                 /* child */
9153                 INT_ON;
9154                 flags |= EV_EXIT;
9155                 if (backgnd)
9156                         flags &= ~EV_TESTED;
9157  nofork:
9158                 redirect(n->nredir.redirect, 0);
9159                 evaltreenr(n->nredir.n, flags);
9160                 /* never returns */
9161         }
9162         /* parent */
9163         status = 0;
9164         if (backgnd == FORK_FG)
9165                 status = waitforjob(jp);
9166         INT_ON;
9167         return status;
9168 }
9169
9170 /*
9171  * Compute the names of the files in a redirection list.
9172  */
9173 static void fixredir(union node *, const char *, int);
9174 static void
9175 expredir(union node *n)
9176 {
9177         union node *redir;
9178
9179         for (redir = n; redir; redir = redir->nfile.next) {
9180                 struct arglist fn;
9181
9182                 fn.list = NULL;
9183                 fn.lastp = &fn.list;
9184                 switch (redir->type) {
9185                 case NFROMTO:
9186                 case NFROM:
9187                 case NTO:
9188 #if BASH_REDIR_OUTPUT
9189                 case NTO2:
9190 #endif
9191                 case NCLOBBER:
9192                 case NAPPEND:
9193                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9194                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9195 #if BASH_REDIR_OUTPUT
9196  store_expfname:
9197 #endif
9198 #if 0
9199 // By the design of stack allocator, the loop of this kind:
9200 //      while true; do while true; do break; done </dev/null; done
9201 // will look like a memory leak: ash plans to free expfname's
9202 // of "/dev/null" as soon as it finishes running the loop
9203 // (in this case, never).
9204 // This "fix" is wrong:
9205                         if (redir->nfile.expfname)
9206                                 stunalloc(redir->nfile.expfname);
9207 // It results in corrupted state of stacked allocations.
9208 #endif
9209                         redir->nfile.expfname = fn.list->text;
9210                         break;
9211                 case NFROMFD:
9212                 case NTOFD: /* >& */
9213                         if (redir->ndup.vname) {
9214                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9215                                 if (fn.list == NULL)
9216                                         ash_msg_and_raise_error("redir error");
9217 #if BASH_REDIR_OUTPUT
9218 //FIXME: we used expandarg with different args!
9219                                 if (!isdigit_str9(fn.list->text)) {
9220                                         /* >&file, not >&fd */
9221                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9222                                                 ash_msg_and_raise_error("redir error");
9223                                         redir->type = NTO2;
9224                                         goto store_expfname;
9225                                 }
9226 #endif
9227                                 fixredir(redir, fn.list->text, 1);
9228                         }
9229                         break;
9230                 }
9231         }
9232 }
9233
9234 /*
9235  * Evaluate a pipeline.  All the processes in the pipeline are children
9236  * of the process creating the pipeline.  (This differs from some versions
9237  * of the shell, which make the last process in a pipeline the parent
9238  * of all the rest.)
9239  */
9240 static int
9241 evalpipe(union node *n, int flags)
9242 {
9243         struct job *jp;
9244         struct nodelist *lp;
9245         int pipelen;
9246         int prevfd;
9247         int pip[2];
9248         int status = 0;
9249
9250         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9251         pipelen = 0;
9252         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9253                 pipelen++;
9254         flags |= EV_EXIT;
9255         INT_OFF;
9256         if (n->npipe.pipe_backgnd == 0)
9257                 get_tty_state();
9258         jp = makejob(/*n,*/ pipelen);
9259         prevfd = -1;
9260         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9261                 prehash(lp->n);
9262                 pip[1] = -1;
9263                 if (lp->next) {
9264                         if (pipe(pip) < 0) {
9265                                 close(prevfd);
9266                                 ash_msg_and_raise_perror("can't create pipe");
9267                         }
9268                 }
9269                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9270                         /* child */
9271                         INT_ON;
9272                         if (pip[1] >= 0) {
9273                                 close(pip[0]);
9274                         }
9275                         if (prevfd > 0) {
9276                                 dup2(prevfd, 0);
9277                                 close(prevfd);
9278                         }
9279                         if (pip[1] > 1) {
9280                                 dup2(pip[1], 1);
9281                                 close(pip[1]);
9282                         }
9283                         evaltreenr(lp->n, flags);
9284                         /* never returns */
9285                 }
9286                 /* parent */
9287                 if (prevfd >= 0)
9288                         close(prevfd);
9289                 prevfd = pip[0];
9290                 /* Don't want to trigger debugging */
9291                 if (pip[1] != -1)
9292                         close(pip[1]);
9293         }
9294         if (n->npipe.pipe_backgnd == 0) {
9295                 status = waitforjob(jp);
9296                 TRACE(("evalpipe:  job done exit status %d\n", status));
9297         }
9298         INT_ON;
9299
9300         return status;
9301 }
9302
9303 /*
9304  * Controls whether the shell is interactive or not.
9305  */
9306 static void
9307 setinteractive(int on)
9308 {
9309         static smallint is_interactive;
9310
9311         if (++on == is_interactive)
9312                 return;
9313         is_interactive = on;
9314         setsignal(SIGINT);
9315         setsignal(SIGQUIT);
9316         setsignal(SIGTERM);
9317 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9318         if (is_interactive > 1) {
9319                 /* Looks like they want an interactive shell */
9320                 static smallint did_banner;
9321
9322                 if (!did_banner) {
9323                         /* note: ash and hush share this string */
9324                         out1fmt("\n\n%s %s\n"
9325                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9326                                 "\n",
9327                                 bb_banner,
9328                                 "built-in shell (ash)"
9329                         );
9330                         did_banner = 1;
9331                 }
9332         }
9333 #endif
9334 }
9335
9336 static void
9337 optschanged(void)
9338 {
9339 #if DEBUG
9340         opentrace();
9341 #endif
9342         setinteractive(iflag);
9343         setjobctl(mflag);
9344 #if ENABLE_FEATURE_EDITING_VI
9345         if (viflag)
9346                 line_input_state->flags |= VI_MODE;
9347         else
9348                 line_input_state->flags &= ~VI_MODE;
9349 #else
9350         viflag = 0; /* forcibly keep the option off */
9351 #endif
9352 }
9353
9354 struct localvar_list {
9355         struct localvar_list *next;
9356         struct localvar *lv;
9357 };
9358
9359 static struct localvar_list *localvar_stack;
9360
9361 /*
9362  * Called after a function returns.
9363  * Interrupts must be off.
9364  */
9365 static void
9366 poplocalvars(int keep)
9367 {
9368         struct localvar_list *ll;
9369         struct localvar *lvp, *next;
9370         struct var *vp;
9371
9372         INT_OFF;
9373         ll = localvar_stack;
9374         localvar_stack = ll->next;
9375
9376         next = ll->lv;
9377         free(ll);
9378
9379         while ((lvp = next) != NULL) {
9380                 next = lvp->next;
9381                 vp = lvp->vp;
9382                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9383                 if (keep) {
9384                         int bits = VSTRFIXED;
9385
9386                         if (lvp->flags != VUNSET) {
9387                                 if (vp->var_text == lvp->text)
9388                                         bits |= VTEXTFIXED;
9389                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9390                                         free((char*)lvp->text);
9391                         }
9392
9393                         vp->flags &= ~bits;
9394                         vp->flags |= (lvp->flags & bits);
9395
9396                         if ((vp->flags &
9397                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9398                                 unsetvar(vp->var_text);
9399                 } else if (vp == NULL) {        /* $- saved */
9400                         memcpy(optlist, lvp->text, sizeof(optlist));
9401                         free((char*)lvp->text);
9402                         optschanged();
9403                 } else if (lvp->flags == VUNSET) {
9404                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9405                         unsetvar(vp->var_text);
9406                 } else {
9407                         if (vp->var_func)
9408                                 vp->var_func(var_end(lvp->text));
9409                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9410                                 free((char*)vp->var_text);
9411                         vp->flags = lvp->flags;
9412                         vp->var_text = lvp->text;
9413                 }
9414                 free(lvp);
9415         }
9416         INT_ON;
9417 }
9418
9419 /*
9420  * Create a new localvar environment.
9421  */
9422 static struct localvar_list *
9423 pushlocalvars(void)
9424 {
9425         struct localvar_list *ll;
9426
9427         INT_OFF;
9428         ll = ckzalloc(sizeof(*ll));
9429         /*ll->lv = NULL; - zalloc did it */
9430         ll->next = localvar_stack;
9431         localvar_stack = ll;
9432         INT_ON;
9433
9434         return ll->next;
9435 }
9436
9437 static void
9438 unwindlocalvars(struct localvar_list *stop)
9439 {
9440         while (localvar_stack != stop)
9441                 poplocalvars(0);
9442 }
9443
9444 static int
9445 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9446 {
9447         volatile struct shparam saveparam;
9448         struct jmploc *volatile savehandler;
9449         struct jmploc jmploc;
9450         int e;
9451
9452         saveparam = shellparam;
9453         savehandler = exception_handler;
9454         e = setjmp(jmploc.loc);
9455         if (e) {
9456                 goto funcdone;
9457         }
9458         INT_OFF;
9459         exception_handler = &jmploc;
9460         shellparam.malloced = 0;
9461         func->count++;
9462         funcnest++;
9463         INT_ON;
9464         shellparam.nparam = argc - 1;
9465         shellparam.p = argv + 1;
9466 #if ENABLE_ASH_GETOPTS
9467         shellparam.optind = 1;
9468         shellparam.optoff = -1;
9469 #endif
9470         pushlocalvars();
9471         evaltree(func->n.narg.next, flags & EV_TESTED);
9472         poplocalvars(0);
9473  funcdone:
9474         INT_OFF;
9475         funcnest--;
9476         freefunc(func);
9477         freeparam(&shellparam);
9478         shellparam = saveparam;
9479         exception_handler = savehandler;
9480         INT_ON;
9481         evalskip &= ~SKIPFUNC;
9482         return e;
9483 }
9484
9485 /*
9486  * Make a variable a local variable.  When a variable is made local, it's
9487  * value and flags are saved in a localvar structure.  The saved values
9488  * will be restored when the shell function returns.  We handle the name
9489  * "-" as a special case: it makes changes to "set +-options" local
9490  * (options will be restored on return from the function).
9491  */
9492 static void
9493 mklocal(char *name)
9494 {
9495         struct localvar *lvp;
9496         struct var **vpp;
9497         struct var *vp;
9498         char *eq = strchr(name, '=');
9499
9500         INT_OFF;
9501         /* Cater for duplicate "local". Examples:
9502          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9503          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9504          */
9505         lvp = localvar_stack->lv;
9506         while (lvp) {
9507                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9508                         if (eq)
9509                                 setvareq(name, 0);
9510                         /* else:
9511                          * it's a duplicate "local VAR" declaration, do nothing
9512                          */
9513                         goto ret;
9514                 }
9515                 lvp = lvp->next;
9516         }
9517
9518         lvp = ckzalloc(sizeof(*lvp));
9519         if (LONE_DASH(name)) {
9520                 char *p;
9521                 p = ckmalloc(sizeof(optlist));
9522                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9523                 vp = NULL;
9524         } else {
9525                 vpp = hashvar(name);
9526                 vp = *findvar(vpp, name);
9527                 if (vp == NULL) {
9528                         /* variable did not exist yet */
9529                         if (eq)
9530                                 vp = setvareq(name, VSTRFIXED);
9531                         else
9532                                 vp = setvar(name, NULL, VSTRFIXED);
9533                         lvp->flags = VUNSET;
9534                 } else {
9535                         lvp->text = vp->var_text;
9536                         lvp->flags = vp->flags;
9537                         /* make sure neither "struct var" nor string gets freed
9538                          * during (un)setting:
9539                          */
9540                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9541                         if (eq)
9542                                 setvareq(name, 0);
9543                         else
9544                                 /* "local VAR" unsets VAR: */
9545                                 setvar0(name, NULL);
9546                 }
9547         }
9548         lvp->vp = vp;
9549         lvp->next = localvar_stack->lv;
9550         localvar_stack->lv = lvp;
9551  ret:
9552         INT_ON;
9553 }
9554
9555 /*
9556  * The "local" command.
9557  */
9558 static int FAST_FUNC
9559 localcmd(int argc UNUSED_PARAM, char **argv)
9560 {
9561         char *name;
9562
9563         if (!localvar_stack)
9564                 ash_msg_and_raise_error("not in a function");
9565
9566         argv = argptr;
9567         while ((name = *argv++) != NULL) {
9568                 mklocal(name);
9569         }
9570         return 0;
9571 }
9572
9573 static int FAST_FUNC
9574 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9575 {
9576         return 1;
9577 }
9578
9579 static int FAST_FUNC
9580 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9581 {
9582         return 0;
9583 }
9584
9585 static int FAST_FUNC
9586 execcmd(int argc UNUSED_PARAM, char **argv)
9587 {
9588         optionarg = NULL;
9589         while (nextopt("a:") != '\0')
9590                 /* nextopt() sets optionarg to "-a ARGV0" */;
9591
9592         argv = argptr;
9593         if (argv[0]) {
9594                 char *prog;
9595
9596                 iflag = 0;              /* exit on error */
9597                 mflag = 0;
9598                 optschanged();
9599                 /* We should set up signals for "exec CMD"
9600                  * the same way as for "CMD" without "exec".
9601                  * But optschanged->setinteractive->setsignal
9602                  * still thought we are a root shell. Therefore, for example,
9603                  * SIGQUIT is still set to IGN. Fix it:
9604                  */
9605                 shlvl++;
9606                 setsignal(SIGQUIT);
9607                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9608                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9609                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9610
9611                 prog = argv[0];
9612                 if (optionarg)
9613                         argv[0] = optionarg;
9614                 shellexec(prog, argv, pathval(), 0);
9615                 /* NOTREACHED */
9616         }
9617         return 0;
9618 }
9619
9620 /*
9621  * The return command.
9622  */
9623 static int FAST_FUNC
9624 returncmd(int argc UNUSED_PARAM, char **argv)
9625 {
9626         /*
9627          * If called outside a function, do what ksh does;
9628          * skip the rest of the file.
9629          */
9630         evalskip = SKIPFUNC;
9631         return argv[1] ? number(argv[1]) : exitstatus;
9632 }
9633
9634 /* Forward declarations for builtintab[] */
9635 static int breakcmd(int, char **) FAST_FUNC;
9636 static int dotcmd(int, char **) FAST_FUNC;
9637 static int evalcmd(int, char **, int) FAST_FUNC;
9638 static int exitcmd(int, char **) FAST_FUNC;
9639 static int exportcmd(int, char **) FAST_FUNC;
9640 #if ENABLE_ASH_GETOPTS
9641 static int getoptscmd(int, char **) FAST_FUNC;
9642 #endif
9643 #if ENABLE_ASH_HELP
9644 static int helpcmd(int, char **) FAST_FUNC;
9645 #endif
9646 #if MAX_HISTORY
9647 static int historycmd(int, char **) FAST_FUNC;
9648 #endif
9649 #if ENABLE_FEATURE_SH_MATH
9650 static int letcmd(int, char **) FAST_FUNC;
9651 #endif
9652 static int readcmd(int, char **) FAST_FUNC;
9653 static int setcmd(int, char **) FAST_FUNC;
9654 static int shiftcmd(int, char **) FAST_FUNC;
9655 static int timescmd(int, char **) FAST_FUNC;
9656 static int trapcmd(int, char **) FAST_FUNC;
9657 static int umaskcmd(int, char **) FAST_FUNC;
9658 static int unsetcmd(int, char **) FAST_FUNC;
9659 static int ulimitcmd(int, char **) FAST_FUNC;
9660
9661 #define BUILTIN_NOSPEC          "0"
9662 #define BUILTIN_SPECIAL         "1"
9663 #define BUILTIN_REGULAR         "2"
9664 #define BUILTIN_SPEC_REG        "3"
9665 #define BUILTIN_ASSIGN          "4"
9666 #define BUILTIN_SPEC_ASSG       "5"
9667 #define BUILTIN_REG_ASSG        "6"
9668 #define BUILTIN_SPEC_REG_ASSG   "7"
9669
9670 /* Stubs for calling non-FAST_FUNC's */
9671 #if ENABLE_ASH_ECHO
9672 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9673 #endif
9674 #if ENABLE_ASH_PRINTF
9675 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9676 #endif
9677 #if ENABLE_ASH_TEST || BASH_TEST2
9678 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9679 #endif
9680
9681 /* Keep these in proper order since it is searched via bsearch() */
9682 static const struct builtincmd builtintab[] = {
9683         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9684         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9685 #if ENABLE_ASH_TEST
9686         { BUILTIN_REGULAR       "["       , testcmd    },
9687 #endif
9688 #if BASH_TEST2
9689         { BUILTIN_REGULAR       "[["      , testcmd    },
9690 #endif
9691 #if ENABLE_ASH_ALIAS
9692         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9693 #endif
9694 #if JOBS
9695         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9696 #endif
9697         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9698         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9699         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9700 #if ENABLE_ASH_CMDCMD
9701         { BUILTIN_REGULAR       "command" , commandcmd },
9702 #endif
9703         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9704 #if ENABLE_ASH_ECHO
9705         { BUILTIN_REGULAR       "echo"    , echocmd    },
9706 #endif
9707         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9708         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9709         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9710         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9711         { BUILTIN_REGULAR       "false"   , falsecmd   },
9712 #if JOBS
9713         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9714 #endif
9715 #if ENABLE_ASH_GETOPTS
9716         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9717 #endif
9718         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9719 #if ENABLE_ASH_HELP
9720         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9721 #endif
9722 #if MAX_HISTORY
9723         { BUILTIN_NOSPEC        "history" , historycmd },
9724 #endif
9725 #if JOBS
9726         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9727         { BUILTIN_REGULAR       "kill"    , killcmd    },
9728 #endif
9729 #if ENABLE_FEATURE_SH_MATH
9730         { BUILTIN_NOSPEC        "let"     , letcmd     },
9731 #endif
9732         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9733 #if ENABLE_ASH_PRINTF
9734         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9735 #endif
9736         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9737         { BUILTIN_REGULAR       "read"    , readcmd    },
9738         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9739         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9740         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9741         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9742 #if BASH_SOURCE
9743         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9744 #endif
9745 #if ENABLE_ASH_TEST
9746         { BUILTIN_REGULAR       "test"    , testcmd    },
9747 #endif
9748         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9749         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9750         { BUILTIN_REGULAR       "true"    , truecmd    },
9751         { BUILTIN_NOSPEC        "type"    , typecmd    },
9752         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9753         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9754 #if ENABLE_ASH_ALIAS
9755         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9756 #endif
9757         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9758         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9759 };
9760
9761 /* Should match the above table! */
9762 #define COMMANDCMD (builtintab + \
9763         /* . : */       2 + \
9764         /* [ */         1 * ENABLE_ASH_TEST + \
9765         /* [[ */        1 * BASH_TEST2 + \
9766         /* alias */     1 * ENABLE_ASH_ALIAS + \
9767         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9768         /* break cd cddir  */   3)
9769 #define EVALCMD (COMMANDCMD + \
9770         /* command */   1 * ENABLE_ASH_CMDCMD + \
9771         /* continue */  1 + \
9772         /* echo */      1 * ENABLE_ASH_ECHO + \
9773         0)
9774 #define EXECCMD (EVALCMD + \
9775         /* eval */      1)
9776
9777 /*
9778  * Search the table of builtin commands.
9779  */
9780 static int
9781 pstrcmp1(const void *a, const void *b)
9782 {
9783         return strcmp((char*)a, *(char**)b + 1);
9784 }
9785 static struct builtincmd *
9786 find_builtin(const char *name)
9787 {
9788         struct builtincmd *bp;
9789
9790         bp = bsearch(
9791                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9792                 pstrcmp1
9793         );
9794         return bp;
9795 }
9796
9797 /*
9798  * Execute a simple command.
9799  */
9800 static int
9801 isassignment(const char *p)
9802 {
9803         const char *q = endofname(p);
9804         if (p == q)
9805                 return 0;
9806         return *q == '=';
9807 }
9808 static int FAST_FUNC
9809 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9810 {
9811         /* Preserve exitstatus of a previous possible redirection
9812          * as POSIX mandates */
9813         return back_exitstatus;
9814 }
9815 static int
9816 evalcommand(union node *cmd, int flags)
9817 {
9818         static const struct builtincmd null_bltin = {
9819                 "\0\0", bltincmd /* why three NULs? */
9820         };
9821         struct localvar_list *localvar_stop;
9822         struct redirtab *redir_stop;
9823         struct stackmark smark;
9824         union node *argp;
9825         struct arglist arglist;
9826         struct arglist varlist;
9827         char **argv;
9828         int argc;
9829         const struct strlist *sp;
9830         struct cmdentry cmdentry;
9831         struct job *jp;
9832         char *lastarg;
9833         const char *path;
9834         int spclbltin;
9835         int status;
9836         char **nargv;
9837         smallint cmd_is_exec;
9838
9839         /* First expand the arguments. */
9840         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9841         setstackmark(&smark);
9842         localvar_stop = pushlocalvars();
9843         back_exitstatus = 0;
9844
9845         cmdentry.cmdtype = CMDBUILTIN;
9846         cmdentry.u.cmd = &null_bltin;
9847         varlist.lastp = &varlist.list;
9848         *varlist.lastp = NULL;
9849         arglist.lastp = &arglist.list;
9850         *arglist.lastp = NULL;
9851
9852         argc = 0;
9853         if (cmd->ncmd.args) {
9854                 struct builtincmd *bcmd;
9855                 smallint pseudovarflag;
9856
9857                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9858                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9859
9860                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9861                         struct strlist **spp;
9862
9863                         spp = arglist.lastp;
9864                         if (pseudovarflag && isassignment(argp->narg.text))
9865                                 expandarg(argp, &arglist, EXP_VARTILDE);
9866                         else
9867                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9868
9869                         for (sp = *spp; sp; sp = sp->next)
9870                                 argc++;
9871                 }
9872         }
9873
9874         /* Reserve one extra spot at the front for shellexec. */
9875         nargv = stalloc(sizeof(char *) * (argc + 2));
9876         argv = ++nargv;
9877         for (sp = arglist.list; sp; sp = sp->next) {
9878                 TRACE(("evalcommand arg: %s\n", sp->text));
9879                 *nargv++ = sp->text;
9880         }
9881         *nargv = NULL;
9882
9883         lastarg = NULL;
9884         if (iflag && funcnest == 0 && argc > 0)
9885                 lastarg = nargv[-1];
9886
9887         expredir(cmd->ncmd.redirect);
9888         redir_stop = pushredir(cmd->ncmd.redirect);
9889         preverrout_fd = 2;
9890         if (BASH_XTRACEFD && xflag) {
9891                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9892                  * we do not emulate this. We only use its value.
9893                  */
9894                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9895                 if (xtracefd && is_number(xtracefd))
9896                         preverrout_fd = atoi(xtracefd);
9897
9898         }
9899         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9900
9901         path = vpath.var_text;
9902         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9903                 struct strlist **spp;
9904                 char *p;
9905
9906                 spp = varlist.lastp;
9907                 expandarg(argp, &varlist, EXP_VARTILDE);
9908
9909                 mklocal((*spp)->text);
9910
9911                 /*
9912                  * Modify the command lookup path, if a PATH= assignment
9913                  * is present
9914                  */
9915                 p = (*spp)->text;
9916                 if (varcmp(p, path) == 0)
9917                         path = p;
9918         }
9919
9920         /* Print the command if xflag is set. */
9921         if (xflag) {
9922                 const char *pfx = "";
9923
9924                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9925
9926                 sp = varlist.list;
9927                 while (sp) {
9928                         char *varval = sp->text;
9929                         char *eq = strchrnul(varval, '=');
9930                         if (*eq)
9931                                 eq++;
9932                         fdprintf(preverrout_fd, "%s%.*s%s",
9933                                 pfx,
9934                                 (int)(eq - varval), varval,
9935                                 maybe_single_quote(eq)
9936                         );
9937                         sp = sp->next;
9938                         pfx = " ";
9939                 }
9940
9941                 sp = arglist.list;
9942                 while (sp) {
9943                         fdprintf(preverrout_fd, "%s%s",
9944                                 pfx,
9945                                 /* always quote if matches reserved word: */
9946                                 findkwd(sp->text)
9947                                 ? single_quote(sp->text)
9948                                 : maybe_single_quote(sp->text)
9949                         );
9950                         sp = sp->next;
9951                         pfx = " ";
9952                 }
9953                 safe_write(preverrout_fd, "\n", 1);
9954         }
9955
9956         cmd_is_exec = 0;
9957         spclbltin = -1;
9958
9959         /* Now locate the command. */
9960         if (argc) {
9961                 int cmd_flag = DO_ERR;
9962 #if ENABLE_ASH_CMDCMD
9963                 const char *oldpath = path + 5;
9964 #endif
9965                 path += 5;
9966                 for (;;) {
9967                         find_command(argv[0], &cmdentry, cmd_flag, path);
9968                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9969                                 flush_stdout_stderr();
9970                                 status = 127;
9971                                 goto bail;
9972                         }
9973
9974                         /* implement bltin and command here */
9975                         if (cmdentry.cmdtype != CMDBUILTIN)
9976                                 break;
9977                         if (spclbltin < 0)
9978                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9979                         if (cmdentry.u.cmd == EXECCMD)
9980                                 cmd_is_exec = 1;
9981 #if ENABLE_ASH_CMDCMD
9982                         if (cmdentry.u.cmd == COMMANDCMD) {
9983                                 path = oldpath;
9984                                 nargv = parse_command_args(argv, &path);
9985                                 if (!nargv)
9986                                         break;
9987                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9988                                  * nargv => "PROG". path is updated if -p.
9989                                  */
9990                                 argc -= nargv - argv;
9991                                 argv = nargv;
9992                                 cmd_flag |= DO_NOFUNC;
9993                         } else
9994 #endif
9995                                 break;
9996                 }
9997         }
9998
9999         if (status) {
10000  bail:
10001                 exitstatus = status;
10002
10003                 /* We have a redirection error. */
10004                 if (spclbltin > 0)
10005                         raise_exception(EXERROR);
10006
10007                 goto out;
10008         }
10009
10010         /* Execute the command. */
10011         switch (cmdentry.cmdtype) {
10012         default: {
10013
10014 #if ENABLE_FEATURE_SH_NOFORK && NUM_APPLETS > 1
10015 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10016  *     around run_nofork_applet() call.
10017  * (2) Should this check also be done in forkshell()?
10018  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10019  */
10020                 /* find_command() encodes applet_no as (-2 - applet_no) */
10021                 int applet_no = (- cmdentry.u.index - 2);
10022                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10023                         char **sv_environ;
10024
10025                         INT_OFF;
10026                         sv_environ = environ;
10027                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10028                         /*
10029                          * Run <applet>_main().
10030                          * Signals (^C) can't interrupt here.
10031                          * Otherwise we can mangle stdio or malloc internal state.
10032                          * This makes applets which can run for a long time
10033                          * and/or wait for user input ineligible for NOFORK:
10034                          * for example, "yes" or "rm" (rm -i waits for input).
10035                          */
10036                         status = run_nofork_applet(applet_no, argv);
10037                         environ = sv_environ;
10038                         /*
10039                          * Try enabling NOFORK for "yes" applet.
10040                          * ^C _will_ stop it (write returns EINTR),
10041                          * but this causes stdout FILE to be stuck
10042                          * and needing clearerr(). What if other applets
10043                          * also can get EINTRs? Do we need to switch
10044                          * our signals to SA_RESTART?
10045                          */
10046                         /*clearerr(stdout);*/
10047                         INT_ON;
10048                         break;
10049                 }
10050 #endif
10051                 /* Can we avoid forking? For example, very last command
10052                  * in a script or a subshell does not need forking,
10053                  * we can just exec it.
10054                  */
10055                 if (!(flags & EV_EXIT) || may_have_traps) {
10056                         /* No, forking off a child is necessary */
10057                         INT_OFF;
10058                         get_tty_state();
10059                         jp = makejob(/*cmd,*/ 1);
10060                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10061                                 /* parent */
10062                                 status = waitforjob(jp);
10063                                 INT_ON;
10064                                 TRACE(("forked child exited with %d\n", status));
10065                                 break;
10066                         }
10067                         /* child */
10068                         FORCE_INT_ON;
10069                         /* fall through to exec'ing external program */
10070                 }
10071                 listsetvar(varlist.list, VEXPORT|VSTACK);
10072                 shellexec(argv[0], argv, path, cmdentry.u.index);
10073                 /* NOTREACHED */
10074         } /* default */
10075         case CMDBUILTIN:
10076                 if (spclbltin > 0 || argc == 0) {
10077                         poplocalvars(1);
10078                         if (cmd_is_exec && argc > 1)
10079                                 listsetvar(varlist.list, VEXPORT);
10080                 }
10081
10082                 /* Tight loop with builtins only:
10083                  * "while kill -0 $child; do true; done"
10084                  * will never exit even if $child died, unless we do this
10085                  * to reap the zombie and make kill detect that it's gone: */
10086                 dowait(DOWAIT_NONBLOCK, NULL);
10087
10088                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10089                         if (exception_type == EXERROR && spclbltin <= 0) {
10090                                 FORCE_INT_ON;
10091                                 goto readstatus;
10092                         }
10093  raise:
10094                         longjmp(exception_handler->loc, 1);
10095                 }
10096                 goto readstatus;
10097
10098         case CMDFUNCTION:
10099                 poplocalvars(1);
10100                 /* See above for the rationale */
10101                 dowait(DOWAIT_NONBLOCK, NULL);
10102                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10103                         goto raise;
10104  readstatus:
10105                 status = exitstatus;
10106                 break;
10107         } /* switch */
10108
10109  out:
10110         if (cmd->ncmd.redirect)
10111                 popredir(/*drop:*/ cmd_is_exec);
10112         unwindredir(redir_stop);
10113         unwindlocalvars(localvar_stop);
10114         if (lastarg) {
10115                 /* dsl: I think this is intended to be used to support
10116                  * '_' in 'vi' command mode during line editing...
10117                  * However I implemented that within libedit itself.
10118                  */
10119                 setvar0("_", lastarg);
10120         }
10121         popstackmark(&smark);
10122
10123         return status;
10124 }
10125
10126 static int
10127 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10128 {
10129         char *volatile savecmdname;
10130         struct jmploc *volatile savehandler;
10131         struct jmploc jmploc;
10132         int status;
10133         int i;
10134
10135         savecmdname = commandname;
10136         savehandler = exception_handler;
10137         i = setjmp(jmploc.loc);
10138         if (i)
10139                 goto cmddone;
10140         exception_handler = &jmploc;
10141         commandname = argv[0];
10142         argptr = argv + 1;
10143         optptr = NULL;                  /* initialize nextopt */
10144         if (cmd == EVALCMD)
10145                 status = evalcmd(argc, argv, flags);
10146         else
10147                 status = (*cmd->builtin)(argc, argv);
10148         flush_stdout_stderr();
10149         status |= ferror(stdout);
10150         exitstatus = status;
10151  cmddone:
10152         clearerr(stdout);
10153         commandname = savecmdname;
10154         exception_handler = savehandler;
10155
10156         return i;
10157 }
10158
10159 static int
10160 goodname(const char *p)
10161 {
10162         return endofname(p)[0] == '\0';
10163 }
10164
10165
10166 /*
10167  * Search for a command.  This is called before we fork so that the
10168  * location of the command will be available in the parent as well as
10169  * the child.  The check for "goodname" is an overly conservative
10170  * check that the name will not be subject to expansion.
10171  */
10172 static void
10173 prehash(union node *n)
10174 {
10175         struct cmdentry entry;
10176
10177         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10178                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10179 }
10180
10181
10182 /* ============ Builtin commands
10183  *
10184  * Builtin commands whose functions are closely tied to evaluation
10185  * are implemented here.
10186  */
10187
10188 /*
10189  * Handle break and continue commands.  Break, continue, and return are
10190  * all handled by setting the evalskip flag.  The evaluation routines
10191  * above all check this flag, and if it is set they start skipping
10192  * commands rather than executing them.  The variable skipcount is
10193  * the number of loops to break/continue, or the number of function
10194  * levels to return.  (The latter is always 1.)  It should probably
10195  * be an error to break out of more loops than exist, but it isn't
10196  * in the standard shell so we don't make it one here.
10197  */
10198 static int FAST_FUNC
10199 breakcmd(int argc UNUSED_PARAM, char **argv)
10200 {
10201         int n = argv[1] ? number(argv[1]) : 1;
10202
10203         if (n <= 0)
10204                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10205         if (n > loopnest)
10206                 n = loopnest;
10207         if (n > 0) {
10208                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10209                 skipcount = n;
10210         }
10211         return 0;
10212 }
10213
10214
10215 /*
10216  * This implements the input routines used by the parser.
10217  */
10218
10219 enum {
10220         INPUT_PUSH_FILE = 1,
10221         INPUT_NOFILE_OK = 2,
10222 };
10223
10224 static smallint checkkwd;
10225 /* values of checkkwd variable */
10226 #define CHKALIAS        0x1
10227 #define CHKKWD          0x2
10228 #define CHKNL           0x4
10229 #define CHKEOFMARK      0x8
10230
10231 /*
10232  * Push a string back onto the input at this current parsefile level.
10233  * We handle aliases this way.
10234  */
10235 #if !ENABLE_ASH_ALIAS
10236 #define pushstring(s, ap) pushstring(s)
10237 #endif
10238 static void
10239 pushstring(char *s, struct alias *ap)
10240 {
10241         struct strpush *sp;
10242         int len;
10243
10244         len = strlen(s);
10245         INT_OFF;
10246         if (g_parsefile->strpush) {
10247                 sp = ckzalloc(sizeof(*sp));
10248                 sp->prev = g_parsefile->strpush;
10249         } else {
10250                 sp = &(g_parsefile->basestrpush);
10251         }
10252         g_parsefile->strpush = sp;
10253         sp->prev_string = g_parsefile->next_to_pgetc;
10254         sp->prev_left_in_line = g_parsefile->left_in_line;
10255         sp->unget = g_parsefile->unget;
10256         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10257 #if ENABLE_ASH_ALIAS
10258         sp->ap = ap;
10259         if (ap) {
10260                 ap->flag |= ALIASINUSE;
10261                 sp->string = s;
10262         }
10263 #endif
10264         g_parsefile->next_to_pgetc = s;
10265         g_parsefile->left_in_line = len;
10266         g_parsefile->unget = 0;
10267         INT_ON;
10268 }
10269
10270 static void
10271 popstring(void)
10272 {
10273         struct strpush *sp = g_parsefile->strpush;
10274
10275         INT_OFF;
10276 #if ENABLE_ASH_ALIAS
10277         if (sp->ap) {
10278                 if (g_parsefile->next_to_pgetc[-1] == ' '
10279                  || g_parsefile->next_to_pgetc[-1] == '\t'
10280                 ) {
10281                         checkkwd |= CHKALIAS;
10282                 }
10283                 if (sp->string != sp->ap->val) {
10284                         free(sp->string);
10285                 }
10286                 sp->ap->flag &= ~ALIASINUSE;
10287                 if (sp->ap->flag & ALIASDEAD) {
10288                         unalias(sp->ap->name);
10289                 }
10290         }
10291 #endif
10292         g_parsefile->next_to_pgetc = sp->prev_string;
10293         g_parsefile->left_in_line = sp->prev_left_in_line;
10294         g_parsefile->unget = sp->unget;
10295         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10296         g_parsefile->strpush = sp->prev;
10297         if (sp != &(g_parsefile->basestrpush))
10298                 free(sp);
10299         INT_ON;
10300 }
10301
10302 static int
10303 preadfd(void)
10304 {
10305         int nr;
10306         char *buf = g_parsefile->buf;
10307
10308         g_parsefile->next_to_pgetc = buf;
10309 #if ENABLE_FEATURE_EDITING
10310  retry:
10311         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10312                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10313         else {
10314 # if ENABLE_ASH_IDLE_TIMEOUT
10315                 int timeout = -1;
10316                 if (iflag) {
10317                         const char *tmout_var = lookupvar("TMOUT");
10318                         if (tmout_var) {
10319                                 timeout = atoi(tmout_var) * 1000;
10320                                 if (timeout <= 0)
10321                                         timeout = -1;
10322                         }
10323                 }
10324                 line_input_state->timeout = timeout;
10325 # endif
10326 # if ENABLE_FEATURE_TAB_COMPLETION
10327                 line_input_state->path_lookup = pathval();
10328 # endif
10329                 reinit_unicode_for_ash();
10330                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10331                 if (nr == 0) {
10332                         /* ^C pressed, "convert" to SIGINT */
10333                         write(STDOUT_FILENO, "^C", 2);
10334                         if (trap[SIGINT]) {
10335                                 buf[0] = '\n';
10336                                 buf[1] = '\0';
10337                                 raise(SIGINT);
10338                                 return 1;
10339                         }
10340                         exitstatus = 128 + SIGINT;
10341                         bb_putchar('\n');
10342                         goto retry;
10343                 }
10344                 if (nr < 0) {
10345                         if (errno == 0) {
10346                                 /* Ctrl+D pressed */
10347                                 nr = 0;
10348                         }
10349 # if ENABLE_ASH_IDLE_TIMEOUT
10350                         else if (errno == EAGAIN && timeout > 0) {
10351                                 puts("\007timed out waiting for input: auto-logout");
10352                                 exitshell();
10353                         }
10354 # endif
10355                 }
10356         }
10357 #else
10358         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10359 #endif
10360
10361 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10362         if (nr < 0) {
10363                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10364                         int flags = fcntl(0, F_GETFL);
10365                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10366                                 flags &= ~O_NONBLOCK;
10367                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10368                                         out2str("sh: turning off NDELAY mode\n");
10369                                         goto retry;
10370                                 }
10371                         }
10372                 }
10373         }
10374 #endif
10375         return nr;
10376 }
10377
10378 /*
10379  * Refill the input buffer and return the next input character:
10380  *
10381  * 1) If a string was pushed back on the input, pop it;
10382  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10383  *    or we are reading from a string so we can't refill the buffer,
10384  *    return EOF.
10385  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10386  * 4) Process input up to the next newline, deleting nul characters.
10387  */
10388 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10389 #define pgetc_debug(...) ((void)0)
10390 static int pgetc(void);
10391 static int
10392 preadbuffer(void)
10393 {
10394         char *q;
10395         int more;
10396
10397         if (g_parsefile->strpush) {
10398 #if ENABLE_ASH_ALIAS
10399                 if (g_parsefile->left_in_line == -1
10400                  && g_parsefile->strpush->ap
10401                  && g_parsefile->next_to_pgetc[-1] != ' '
10402                  && g_parsefile->next_to_pgetc[-1] != '\t'
10403                 ) {
10404                         pgetc_debug("preadbuffer PEOA");
10405                         return PEOA;
10406                 }
10407 #endif
10408                 popstring();
10409                 return pgetc();
10410         }
10411         /* on both branches above g_parsefile->left_in_line < 0.
10412          * "pgetc" needs refilling.
10413          */
10414
10415         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10416          * pungetc() may increment it a few times.
10417          * Assuming it won't increment it to less than -90.
10418          */
10419         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10420                 pgetc_debug("preadbuffer PEOF1");
10421                 /* even in failure keep left_in_line and next_to_pgetc
10422                  * in lock step, for correct multi-layer pungetc.
10423                  * left_in_line was decremented before preadbuffer(),
10424                  * must inc next_to_pgetc: */
10425                 g_parsefile->next_to_pgetc++;
10426                 return PEOF;
10427         }
10428
10429         more = g_parsefile->left_in_buffer;
10430         if (more <= 0) {
10431                 flush_stdout_stderr();
10432  again:
10433                 more = preadfd();
10434                 if (more <= 0) {
10435                         /* don't try reading again */
10436                         g_parsefile->left_in_line = -99;
10437                         pgetc_debug("preadbuffer PEOF2");
10438                         g_parsefile->next_to_pgetc++;
10439                         return PEOF;
10440                 }
10441         }
10442
10443         /* Find out where's the end of line.
10444          * Set g_parsefile->left_in_line
10445          * and g_parsefile->left_in_buffer acordingly.
10446          * NUL chars are deleted.
10447          */
10448         q = g_parsefile->next_to_pgetc;
10449         for (;;) {
10450                 char c;
10451
10452                 more--;
10453
10454                 c = *q;
10455                 if (c == '\0') {
10456                         memmove(q, q + 1, more);
10457                 } else {
10458                         q++;
10459                         if (c == '\n') {
10460                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10461                                 break;
10462                         }
10463                 }
10464
10465                 if (more <= 0) {
10466                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10467                         if (g_parsefile->left_in_line < 0)
10468                                 goto again;
10469                         break;
10470                 }
10471         }
10472         g_parsefile->left_in_buffer = more;
10473
10474         if (vflag) {
10475                 char save = *q;
10476                 *q = '\0';
10477                 out2str(g_parsefile->next_to_pgetc);
10478                 *q = save;
10479         }
10480
10481         pgetc_debug("preadbuffer at %d:%p'%s'",
10482                         g_parsefile->left_in_line,
10483                         g_parsefile->next_to_pgetc,
10484                         g_parsefile->next_to_pgetc);
10485         return (unsigned char)*g_parsefile->next_to_pgetc++;
10486 }
10487
10488 static void
10489 nlprompt(void)
10490 {
10491         g_parsefile->linno++;
10492         setprompt_if(doprompt, 2);
10493 }
10494 static void
10495 nlnoprompt(void)
10496 {
10497         g_parsefile->linno++;
10498         needprompt = doprompt;
10499 }
10500
10501 static int
10502 pgetc(void)
10503 {
10504         int c;
10505
10506         pgetc_debug("pgetc at %d:%p'%s'",
10507                         g_parsefile->left_in_line,
10508                         g_parsefile->next_to_pgetc,
10509                         g_parsefile->next_to_pgetc);
10510         if (g_parsefile->unget)
10511                 return g_parsefile->lastc[--g_parsefile->unget];
10512
10513         if (--g_parsefile->left_in_line >= 0)
10514                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10515         else
10516                 c = preadbuffer();
10517
10518         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10519         g_parsefile->lastc[0] = c;
10520
10521         return c;
10522 }
10523
10524 #if ENABLE_ASH_ALIAS
10525 static int
10526 pgetc_without_PEOA(void)
10527 {
10528         int c;
10529         do {
10530                 pgetc_debug("pgetc at %d:%p'%s'",
10531                                 g_parsefile->left_in_line,
10532                                 g_parsefile->next_to_pgetc,
10533                                 g_parsefile->next_to_pgetc);
10534                 c = pgetc();
10535         } while (c == PEOA);
10536         return c;
10537 }
10538 #else
10539 # define pgetc_without_PEOA() pgetc()
10540 #endif
10541
10542 /*
10543  * Undo a call to pgetc.  Only two characters may be pushed back.
10544  * PEOF may be pushed back.
10545  */
10546 static void
10547 pungetc(void)
10548 {
10549         g_parsefile->unget++;
10550 }
10551
10552 /* This one eats backslash+newline */
10553 static int
10554 pgetc_eatbnl(void)
10555 {
10556         int c;
10557
10558         while ((c = pgetc()) == '\\') {
10559                 if (pgetc() != '\n') {
10560                         pungetc();
10561                         break;
10562                 }
10563
10564                 nlprompt();
10565         }
10566
10567         return c;
10568 }
10569
10570 /*
10571  * To handle the "." command, a stack of input files is used.  Pushfile
10572  * adds a new entry to the stack and popfile restores the previous level.
10573  */
10574 static void
10575 pushfile(void)
10576 {
10577         struct parsefile *pf;
10578
10579         pf = ckzalloc(sizeof(*pf));
10580         pf->prev = g_parsefile;
10581         pf->pf_fd = -1;
10582         /*pf->strpush = NULL; - ckzalloc did it */
10583         /*pf->basestrpush.prev = NULL;*/
10584         /*pf->unget = 0;*/
10585         g_parsefile = pf;
10586 }
10587
10588 static void
10589 popfile(void)
10590 {
10591         struct parsefile *pf = g_parsefile;
10592
10593         if (pf == &basepf)
10594                 return;
10595
10596         INT_OFF;
10597         if (pf->pf_fd >= 0)
10598                 close(pf->pf_fd);
10599         free(pf->buf);
10600         while (pf->strpush)
10601                 popstring();
10602         g_parsefile = pf->prev;
10603         free(pf);
10604         INT_ON;
10605 }
10606
10607 /*
10608  * Return to top level.
10609  */
10610 static void
10611 popallfiles(void)
10612 {
10613         while (g_parsefile != &basepf)
10614                 popfile();
10615 }
10616
10617 /*
10618  * Close the file(s) that the shell is reading commands from.  Called
10619  * after a fork is done.
10620  */
10621 static void
10622 closescript(void)
10623 {
10624         popallfiles();
10625         if (g_parsefile->pf_fd > 0) {
10626                 close(g_parsefile->pf_fd);
10627                 g_parsefile->pf_fd = 0;
10628         }
10629 }
10630
10631 /*
10632  * Like setinputfile, but takes an open file descriptor.  Call this with
10633  * interrupts off.
10634  */
10635 static void
10636 setinputfd(int fd, int push)
10637 {
10638         if (push) {
10639                 pushfile();
10640                 g_parsefile->buf = NULL;
10641         }
10642         g_parsefile->pf_fd = fd;
10643         if (g_parsefile->buf == NULL)
10644                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10645         g_parsefile->left_in_buffer = 0;
10646         g_parsefile->left_in_line = 0;
10647         g_parsefile->linno = 1;
10648 }
10649
10650 /*
10651  * Set the input to take input from a file.  If push is set, push the
10652  * old input onto the stack first.
10653  */
10654 static int
10655 setinputfile(const char *fname, int flags)
10656 {
10657         int fd;
10658
10659         INT_OFF;
10660         fd = open(fname, O_RDONLY);
10661         if (fd < 0) {
10662                 if (flags & INPUT_NOFILE_OK)
10663                         goto out;
10664                 exitstatus = 127;
10665                 ash_msg_and_raise_perror("can't open '%s'", fname);
10666         }
10667         if (fd < 10)
10668                 fd = savefd(fd);
10669         else
10670                 close_on_exec_on(fd);
10671         setinputfd(fd, flags & INPUT_PUSH_FILE);
10672  out:
10673         INT_ON;
10674         return fd;
10675 }
10676
10677 /*
10678  * Like setinputfile, but takes input from a string.
10679  */
10680 static void
10681 setinputstring(char *string)
10682 {
10683         INT_OFF;
10684         pushfile();
10685         g_parsefile->next_to_pgetc = string;
10686         g_parsefile->left_in_line = strlen(string);
10687         g_parsefile->buf = NULL;
10688         g_parsefile->linno = 1;
10689         INT_ON;
10690 }
10691
10692
10693 /*
10694  * Routines to check for mail.
10695  */
10696
10697 #if ENABLE_ASH_MAIL
10698
10699 /* Hash of mtimes of mailboxes */
10700 static unsigned mailtime_hash;
10701 /* Set if MAIL or MAILPATH is changed. */
10702 static smallint mail_var_path_changed;
10703
10704 /*
10705  * Print appropriate message(s) if mail has arrived.
10706  * If mail_var_path_changed is set,
10707  * then the value of MAIL has mail_var_path_changed,
10708  * so we just update the values.
10709  */
10710 static void
10711 chkmail(void)
10712 {
10713         const char *mpath;
10714         char *p;
10715         char *q;
10716         unsigned new_hash;
10717         struct stackmark smark;
10718         struct stat statb;
10719
10720         setstackmark(&smark);
10721         mpath = mpathset() ? mpathval() : mailval();
10722         new_hash = 0;
10723         for (;;) {
10724                 p = path_advance(&mpath, nullstr);
10725                 if (p == NULL)
10726                         break;
10727                 if (*p == '\0')
10728                         continue;
10729                 for (q = p; *q; q++)
10730                         continue;
10731 #if DEBUG
10732                 if (q[-1] != '/')
10733                         abort();
10734 #endif
10735                 q[-1] = '\0';                   /* delete trailing '/' */
10736                 if (stat(p, &statb) < 0) {
10737                         continue;
10738                 }
10739                 /* Very simplistic "hash": just a sum of all mtimes */
10740                 new_hash += (unsigned)statb.st_mtime;
10741         }
10742         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10743                 if (mailtime_hash != 0)
10744                         out2str("you have mail\n");
10745                 mailtime_hash = new_hash;
10746         }
10747         mail_var_path_changed = 0;
10748         popstackmark(&smark);
10749 }
10750
10751 static void FAST_FUNC
10752 changemail(const char *val UNUSED_PARAM)
10753 {
10754         mail_var_path_changed = 1;
10755 }
10756
10757 #endif /* ASH_MAIL */
10758
10759
10760 /* ============ ??? */
10761
10762 /*
10763  * Set the shell parameters.
10764  */
10765 static void
10766 setparam(char **argv)
10767 {
10768         char **newparam;
10769         char **ap;
10770         int nparam;
10771
10772         for (nparam = 0; argv[nparam]; nparam++)
10773                 continue;
10774         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10775         while (*argv) {
10776                 *ap++ = ckstrdup(*argv++);
10777         }
10778         *ap = NULL;
10779         freeparam(&shellparam);
10780         shellparam.malloced = 1;
10781         shellparam.nparam = nparam;
10782         shellparam.p = newparam;
10783 #if ENABLE_ASH_GETOPTS
10784         shellparam.optind = 1;
10785         shellparam.optoff = -1;
10786 #endif
10787 }
10788
10789 /*
10790  * Process shell options.  The global variable argptr contains a pointer
10791  * to the argument list; we advance it past the options.
10792  *
10793  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10794  * For a non-interactive shell, an error condition encountered
10795  * by a special built-in ... shall cause the shell to write a diagnostic message
10796  * to standard error and exit as shown in the following table:
10797  * Error                                           Special Built-In
10798  * ...
10799  * Utility syntax error (option or operand error)  Shall exit
10800  * ...
10801  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10802  * we see that bash does not do that (set "finishes" with error code 1 instead,
10803  * and shell continues), and people rely on this behavior!
10804  * Testcase:
10805  * set -o barfoo 2>/dev/null
10806  * echo $?
10807  *
10808  * Oh well. Let's mimic that.
10809  */
10810 static int
10811 plus_minus_o(char *name, int val)
10812 {
10813         int i;
10814
10815         if (name) {
10816                 for (i = 0; i < NOPTS; i++) {
10817                         if (strcmp(name, optnames(i)) == 0) {
10818                                 optlist[i] = val;
10819                                 return 0;
10820                         }
10821                 }
10822                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10823                 return 1;
10824         }
10825         for (i = 0; i < NOPTS; i++) {
10826                 if (val) {
10827                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10828                 } else {
10829                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10830                 }
10831         }
10832         return 0;
10833 }
10834 static void
10835 setoption(int flag, int val)
10836 {
10837         int i;
10838
10839         for (i = 0; i < NOPTS; i++) {
10840                 if (optletters(i) == flag) {
10841                         optlist[i] = val;
10842                         return;
10843                 }
10844         }
10845         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10846         /* NOTREACHED */
10847 }
10848 static int
10849 options(int cmdline, int *login_sh)
10850 {
10851         char *p;
10852         int val;
10853         int c;
10854
10855         if (cmdline)
10856                 minusc = NULL;
10857         while ((p = *argptr) != NULL) {
10858                 c = *p++;
10859                 if (c != '-' && c != '+')
10860                         break;
10861                 argptr++;
10862                 val = 0; /* val = 0 if c == '+' */
10863                 if (c == '-') {
10864                         val = 1;
10865                         if (p[0] == '\0' || LONE_DASH(p)) {
10866                                 if (!cmdline) {
10867                                         /* "-" means turn off -x and -v */
10868                                         if (p[0] == '\0')
10869                                                 xflag = vflag = 0;
10870                                         /* "--" means reset params */
10871                                         else if (*argptr == NULL)
10872                                                 setparam(argptr);
10873                                 }
10874                                 break;    /* "-" or "--" terminates options */
10875                         }
10876                 }
10877                 /* first char was + or - */
10878                 while ((c = *p++) != '\0') {
10879                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10880                         if (c == 'c' && cmdline) {
10881                                 minusc = p;     /* command is after shell args */
10882                         } else if (c == 'o') {
10883                                 if (plus_minus_o(*argptr, val)) {
10884                                         /* it already printed err message */
10885                                         return 1; /* error */
10886                                 }
10887                                 if (*argptr)
10888                                         argptr++;
10889                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10890                                 if (login_sh)
10891                                         *login_sh = 1;
10892                         /* bash does not accept +-login, we also won't */
10893                         } else if (cmdline && val && (c == '-')) { /* long options */
10894                                 if (strcmp(p, "login") == 0) {
10895                                         if (login_sh)
10896                                                 *login_sh = 1;
10897                                 }
10898                                 break;
10899                         } else {
10900                                 setoption(c, val);
10901                         }
10902                 }
10903         }
10904         return 0;
10905 }
10906
10907 /*
10908  * The shift builtin command.
10909  */
10910 static int FAST_FUNC
10911 shiftcmd(int argc UNUSED_PARAM, char **argv)
10912 {
10913         int n;
10914         char **ap1, **ap2;
10915
10916         n = 1;
10917         if (argv[1])
10918                 n = number(argv[1]);
10919         if (n > shellparam.nparam)
10920                 return 1;
10921         INT_OFF;
10922         shellparam.nparam -= n;
10923         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10924                 if (shellparam.malloced)
10925                         free(*ap1);
10926         }
10927         ap2 = shellparam.p;
10928         while ((*ap2++ = *ap1++) != NULL)
10929                 continue;
10930 #if ENABLE_ASH_GETOPTS
10931         shellparam.optind = 1;
10932         shellparam.optoff = -1;
10933 #endif
10934         INT_ON;
10935         return 0;
10936 }
10937
10938 /*
10939  * POSIX requires that 'set' (but not export or readonly) output the
10940  * variables in lexicographic order - by the locale's collating order (sigh).
10941  * Maybe we could keep them in an ordered balanced binary tree
10942  * instead of hashed lists.
10943  * For now just roll 'em through qsort for printing...
10944  */
10945 static int
10946 showvars(const char *sep_prefix, int on, int off)
10947 {
10948         const char *sep;
10949         char **ep, **epend;
10950
10951         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
10952         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10953
10954         sep = *sep_prefix ? " " : sep_prefix;
10955
10956         for (; ep < epend; ep++) {
10957                 const char *p;
10958                 const char *q;
10959
10960                 p = endofname(*ep);
10961 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
10962  * makes "export -p" to have output not suitable for "eval":
10963  * import os
10964  * os.environ["test-test"]="test"
10965  * if os.fork() == 0:
10966  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
10967  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
10968  */
10969                 q = nullstr;
10970                 if (*p == '=')
10971                         q = single_quote(++p);
10972                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10973         }
10974         return 0;
10975 }
10976
10977 /*
10978  * The set command builtin.
10979  */
10980 static int FAST_FUNC
10981 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10982 {
10983         int retval;
10984
10985         if (!argv[1])
10986                 return showvars(nullstr, 0, VUNSET);
10987
10988         INT_OFF;
10989         retval = options(/*cmdline:*/ 0, NULL);
10990         if (retval == 0) { /* if no parse error... */
10991                 optschanged();
10992                 if (*argptr != NULL) {
10993                         setparam(argptr);
10994                 }
10995         }
10996         INT_ON;
10997         return retval;
10998 }
10999
11000 #if ENABLE_ASH_RANDOM_SUPPORT
11001 static void FAST_FUNC
11002 change_random(const char *value)
11003 {
11004         uint32_t t;
11005
11006         if (value == NULL) {
11007                 /* "get", generate */
11008                 t = next_random(&random_gen);
11009                 /* set without recursion */
11010                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11011                 vrandom.flags &= ~VNOFUNC;
11012         } else {
11013                 /* set/reset */
11014                 t = strtoul(value, NULL, 10);
11015                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11016         }
11017 }
11018 #endif
11019
11020 #if ENABLE_ASH_GETOPTS
11021 static int
11022 getopts(char *optstr, char *optvar, char **optfirst)
11023 {
11024         char *p, *q;
11025         char c = '?';
11026         int done = 0;
11027         char sbuf[2];
11028         char **optnext;
11029         int ind = shellparam.optind;
11030         int off = shellparam.optoff;
11031
11032         sbuf[1] = '\0';
11033
11034         shellparam.optind = -1;
11035         optnext = optfirst + ind - 1;
11036
11037         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11038                 p = NULL;
11039         else
11040                 p = optnext[-1] + off;
11041         if (p == NULL || *p == '\0') {
11042                 /* Current word is done, advance */
11043                 p = *optnext;
11044                 if (p == NULL || *p != '-' || *++p == '\0') {
11045  atend:
11046                         unsetvar("OPTARG");
11047                         p = NULL;
11048                         done = 1;
11049                         goto out;
11050                 }
11051                 optnext++;
11052                 if (LONE_DASH(p))        /* check for "--" */
11053                         goto atend;
11054         }
11055
11056         c = *p++;
11057         for (q = optstr; *q != c;) {
11058                 if (*q == '\0') {
11059                         /* OPTERR is a bashism */
11060                         const char *cp = lookupvar("OPTERR");
11061                         if ((cp && LONE_CHAR(cp, '0'))
11062                          || (optstr[0] == ':')
11063                         ) {
11064                                 sbuf[0] = c;
11065                                 /*sbuf[1] = '\0'; - already is */
11066                                 setvar0("OPTARG", sbuf);
11067                         } else {
11068                                 fprintf(stderr, "Illegal option -%c\n", c);
11069                                 unsetvar("OPTARG");
11070                         }
11071                         c = '?';
11072                         goto out;
11073                 }
11074                 if (*++q == ':')
11075                         q++;
11076         }
11077
11078         if (*++q == ':') {
11079                 if (*p == '\0' && (p = *optnext) == NULL) {
11080                         /* OPTERR is a bashism */
11081                         const char *cp = lookupvar("OPTERR");
11082                         if ((cp && LONE_CHAR(cp, '0'))
11083                          || (optstr[0] == ':')
11084                         ) {
11085                                 sbuf[0] = c;
11086                                 /*sbuf[1] = '\0'; - already is */
11087                                 setvar0("OPTARG", sbuf);
11088                                 c = ':';
11089                         } else {
11090                                 fprintf(stderr, "No arg for -%c option\n", c);
11091                                 unsetvar("OPTARG");
11092                                 c = '?';
11093                         }
11094                         goto out;
11095                 }
11096
11097                 if (p == *optnext)
11098                         optnext++;
11099                 setvar0("OPTARG", p);
11100                 p = NULL;
11101         } else
11102                 setvar0("OPTARG", nullstr);
11103  out:
11104         ind = optnext - optfirst + 1;
11105         setvar("OPTIND", itoa(ind), VNOFUNC);
11106         sbuf[0] = c;
11107         /*sbuf[1] = '\0'; - already is */
11108         setvar0(optvar, sbuf);
11109
11110         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11111         shellparam.optind = ind;
11112
11113         return done;
11114 }
11115
11116 /*
11117  * The getopts builtin.  Shellparam.optnext points to the next argument
11118  * to be processed.  Shellparam.optptr points to the next character to
11119  * be processed in the current argument.  If shellparam.optnext is NULL,
11120  * then it's the first time getopts has been called.
11121  */
11122 static int FAST_FUNC
11123 getoptscmd(int argc, char **argv)
11124 {
11125         char **optbase;
11126
11127         if (argc < 3)
11128                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11129         if (argc == 3) {
11130                 optbase = shellparam.p;
11131                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11132                         shellparam.optind = 1;
11133                         shellparam.optoff = -1;
11134                 }
11135         } else {
11136                 optbase = &argv[3];
11137                 if ((unsigned)shellparam.optind > argc - 2) {
11138                         shellparam.optind = 1;
11139                         shellparam.optoff = -1;
11140                 }
11141         }
11142
11143         return getopts(argv[1], argv[2], optbase);
11144 }
11145 #endif /* ASH_GETOPTS */
11146
11147
11148 /* ============ Shell parser */
11149
11150 struct heredoc {
11151         struct heredoc *next;   /* next here document in list */
11152         union node *here;       /* redirection node */
11153         char *eofmark;          /* string indicating end of input */
11154         smallint striptabs;     /* if set, strip leading tabs */
11155 };
11156
11157 static smallint tokpushback;           /* last token pushed back */
11158 static smallint quoteflag;             /* set if (part of) last token was quoted */
11159 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11160 static struct heredoc *heredoclist;    /* list of here documents to read */
11161 static char *wordtext;                 /* text of last word returned by readtoken */
11162 static struct nodelist *backquotelist;
11163 static union node *redirnode;
11164 static struct heredoc *heredoc;
11165
11166 static const char *
11167 tokname(char *buf, int tok)
11168 {
11169         if (tok < TSEMI)
11170                 return tokname_array[tok];
11171         sprintf(buf, "\"%s\"", tokname_array[tok]);
11172         return buf;
11173 }
11174
11175 /* raise_error_unexpected_syntax:
11176  * Called when an unexpected token is read during the parse.  The argument
11177  * is the token that is expected, or -1 if more than one type of token can
11178  * occur at this point.
11179  */
11180 static void raise_error_unexpected_syntax(int) NORETURN;
11181 static void
11182 raise_error_unexpected_syntax(int token)
11183 {
11184         char msg[64];
11185         char buf[16];
11186         int l;
11187
11188         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11189         if (token >= 0)
11190                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11191         raise_error_syntax(msg);
11192         /* NOTREACHED */
11193 }
11194
11195 /* parsing is heavily cross-recursive, need these forward decls */
11196 static union node *andor(void);
11197 static union node *pipeline(void);
11198 static union node *parse_command(void);
11199 static void parseheredoc(void);
11200 static int peektoken(void);
11201 static int readtoken(void);
11202
11203 static union node *
11204 list(int nlflag)
11205 {
11206         union node *n1, *n2, *n3;
11207         int tok;
11208
11209         n1 = NULL;
11210         for (;;) {
11211                 switch (peektoken()) {
11212                 case TNL:
11213                         if (!(nlflag & 1))
11214                                 break;
11215                         parseheredoc();
11216                         return n1;
11217
11218                 case TEOF:
11219                         if (!n1 && (nlflag & 1))
11220                                 n1 = NODE_EOF;
11221                         parseheredoc();
11222                         return n1;
11223                 }
11224
11225                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11226                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11227                         return n1;
11228                 nlflag |= 2;
11229
11230                 n2 = andor();
11231                 tok = readtoken();
11232                 if (tok == TBACKGND) {
11233                         if (n2->type == NPIPE) {
11234                                 n2->npipe.pipe_backgnd = 1;
11235                         } else {
11236                                 if (n2->type != NREDIR) {
11237                                         n3 = stzalloc(sizeof(struct nredir));
11238                                         n3->nredir.n = n2;
11239                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11240                                         n2 = n3;
11241                                 }
11242                                 n2->type = NBACKGND;
11243                         }
11244                 }
11245                 if (n1 == NULL) {
11246                         n1 = n2;
11247                 } else {
11248                         n3 = stzalloc(sizeof(struct nbinary));
11249                         n3->type = NSEMI;
11250                         n3->nbinary.ch1 = n1;
11251                         n3->nbinary.ch2 = n2;
11252                         n1 = n3;
11253                 }
11254                 switch (tok) {
11255                 case TNL:
11256                 case TEOF:
11257                         tokpushback = 1;
11258                         /* fall through */
11259                 case TBACKGND:
11260                 case TSEMI:
11261                         break;
11262                 default:
11263                         if ((nlflag & 1))
11264                                 raise_error_unexpected_syntax(-1);
11265                         tokpushback = 1;
11266                         return n1;
11267                 }
11268         }
11269 }
11270
11271 static union node *
11272 andor(void)
11273 {
11274         union node *n1, *n2, *n3;
11275         int t;
11276
11277         n1 = pipeline();
11278         for (;;) {
11279                 t = readtoken();
11280                 if (t == TAND) {
11281                         t = NAND;
11282                 } else if (t == TOR) {
11283                         t = NOR;
11284                 } else {
11285                         tokpushback = 1;
11286                         return n1;
11287                 }
11288                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11289                 n2 = pipeline();
11290                 n3 = stzalloc(sizeof(struct nbinary));
11291                 n3->type = t;
11292                 n3->nbinary.ch1 = n1;
11293                 n3->nbinary.ch2 = n2;
11294                 n1 = n3;
11295         }
11296 }
11297
11298 static union node *
11299 pipeline(void)
11300 {
11301         union node *n1, *n2, *pipenode;
11302         struct nodelist *lp, *prev;
11303         int negate;
11304
11305         negate = 0;
11306         TRACE(("pipeline: entered\n"));
11307         if (readtoken() == TNOT) {
11308                 negate = !negate;
11309                 checkkwd = CHKKWD | CHKALIAS;
11310         } else
11311                 tokpushback = 1;
11312         n1 = parse_command();
11313         if (readtoken() == TPIPE) {
11314                 pipenode = stzalloc(sizeof(struct npipe));
11315                 pipenode->type = NPIPE;
11316                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11317                 lp = stzalloc(sizeof(struct nodelist));
11318                 pipenode->npipe.cmdlist = lp;
11319                 lp->n = n1;
11320                 do {
11321                         prev = lp;
11322                         lp = stzalloc(sizeof(struct nodelist));
11323                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11324                         lp->n = parse_command();
11325                         prev->next = lp;
11326                 } while (readtoken() == TPIPE);
11327                 lp->next = NULL;
11328                 n1 = pipenode;
11329         }
11330         tokpushback = 1;
11331         if (negate) {
11332                 n2 = stzalloc(sizeof(struct nnot));
11333                 n2->type = NNOT;
11334                 n2->nnot.com = n1;
11335                 return n2;
11336         }
11337         return n1;
11338 }
11339
11340 static union node *
11341 makename(void)
11342 {
11343         union node *n;
11344
11345         n = stzalloc(sizeof(struct narg));
11346         n->type = NARG;
11347         /*n->narg.next = NULL; - stzalloc did it */
11348         n->narg.text = wordtext;
11349         n->narg.backquote = backquotelist;
11350         return n;
11351 }
11352
11353 static void
11354 fixredir(union node *n, const char *text, int err)
11355 {
11356         int fd;
11357
11358         TRACE(("Fix redir %s %d\n", text, err));
11359         if (!err)
11360                 n->ndup.vname = NULL;
11361
11362         fd = bb_strtou(text, NULL, 10);
11363         if (!errno && fd >= 0)
11364                 n->ndup.dupfd = fd;
11365         else if (LONE_DASH(text))
11366                 n->ndup.dupfd = -1;
11367         else {
11368                 if (err)
11369                         raise_error_syntax("bad fd number");
11370                 n->ndup.vname = makename();
11371         }
11372 }
11373
11374 static void
11375 parsefname(void)
11376 {
11377         union node *n = redirnode;
11378
11379         if (n->type == NHERE)
11380                 checkkwd = CHKEOFMARK;
11381         if (readtoken() != TWORD)
11382                 raise_error_unexpected_syntax(-1);
11383         if (n->type == NHERE) {
11384                 struct heredoc *here = heredoc;
11385                 struct heredoc *p;
11386
11387                 if (quoteflag == 0)
11388                         n->type = NXHERE;
11389                 TRACE(("Here document %d\n", n->type));
11390                 rmescapes(wordtext, 0, NULL);
11391                 here->eofmark = wordtext;
11392                 here->next = NULL;
11393                 if (heredoclist == NULL)
11394                         heredoclist = here;
11395                 else {
11396                         for (p = heredoclist; p->next; p = p->next)
11397                                 continue;
11398                         p->next = here;
11399                 }
11400         } else if (n->type == NTOFD || n->type == NFROMFD) {
11401                 fixredir(n, wordtext, 0);
11402         } else {
11403                 n->nfile.fname = makename();
11404         }
11405 }
11406
11407 static union node *
11408 simplecmd(void)
11409 {
11410         union node *args, **app;
11411         union node *n = NULL;
11412         union node *vars, **vpp;
11413         union node **rpp, *redir;
11414         int savecheckkwd;
11415 #if BASH_TEST2
11416         smallint double_brackets_flag = 0;
11417 #endif
11418         IF_BASH_FUNCTION(smallint function_flag = 0;)
11419
11420         args = NULL;
11421         app = &args;
11422         vars = NULL;
11423         vpp = &vars;
11424         redir = NULL;
11425         rpp = &redir;
11426
11427         savecheckkwd = CHKALIAS;
11428         for (;;) {
11429                 int t;
11430                 checkkwd = savecheckkwd;
11431                 t = readtoken();
11432                 switch (t) {
11433 #if BASH_FUNCTION
11434                 case TFUNCTION:
11435                         if (peektoken() != TWORD)
11436                                 raise_error_unexpected_syntax(TWORD);
11437                         function_flag = 1;
11438                         break;
11439 #endif
11440 #if BASH_TEST2
11441                 case TAND: /* "&&" */
11442                 case TOR: /* "||" */
11443                         if (!double_brackets_flag) {
11444                                 tokpushback = 1;
11445                                 goto out;
11446                         }
11447                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11448 #endif
11449                 case TWORD:
11450                         n = stzalloc(sizeof(struct narg));
11451                         n->type = NARG;
11452                         /*n->narg.next = NULL; - stzalloc did it */
11453                         n->narg.text = wordtext;
11454 #if BASH_TEST2
11455                         if (strcmp("[[", wordtext) == 0)
11456                                 double_brackets_flag = 1;
11457                         else if (strcmp("]]", wordtext) == 0)
11458                                 double_brackets_flag = 0;
11459 #endif
11460                         n->narg.backquote = backquotelist;
11461                         if (savecheckkwd && isassignment(wordtext)) {
11462                                 *vpp = n;
11463                                 vpp = &n->narg.next;
11464                         } else {
11465                                 *app = n;
11466                                 app = &n->narg.next;
11467                                 savecheckkwd = 0;
11468                         }
11469 #if BASH_FUNCTION
11470                         if (function_flag) {
11471                                 checkkwd = CHKNL | CHKKWD;
11472                                 switch (peektoken()) {
11473                                 case TBEGIN:
11474                                 case TIF:
11475                                 case TCASE:
11476                                 case TUNTIL:
11477                                 case TWHILE:
11478                                 case TFOR:
11479                                         goto do_func;
11480                                 case TLP:
11481                                         function_flag = 0;
11482                                         break;
11483                                 case TWORD:
11484                                         if (strcmp("[[", wordtext) == 0)
11485                                                 goto do_func;
11486                                         /* fall through */
11487                                 default:
11488                                         raise_error_unexpected_syntax(-1);
11489                                 }
11490                         }
11491 #endif
11492                         break;
11493                 case TREDIR:
11494                         *rpp = n = redirnode;
11495                         rpp = &n->nfile.next;
11496                         parsefname();   /* read name of redirection file */
11497                         break;
11498                 case TLP:
11499  IF_BASH_FUNCTION(do_func:)
11500                         if (args && app == &args->narg.next
11501                          && !vars && !redir
11502                         ) {
11503                                 struct builtincmd *bcmd;
11504                                 const char *name;
11505
11506                                 /* We have a function */
11507                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11508                                         raise_error_unexpected_syntax(TRP);
11509                                 name = n->narg.text;
11510                                 if (!goodname(name)
11511                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11512                                 ) {
11513                                         raise_error_syntax("bad function name");
11514                                 }
11515                                 n->type = NDEFUN;
11516                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11517                                 n->narg.next = parse_command();
11518                                 return n;
11519                         }
11520                         IF_BASH_FUNCTION(function_flag = 0;)
11521                         /* fall through */
11522                 default:
11523                         tokpushback = 1;
11524                         goto out;
11525                 }
11526         }
11527  out:
11528         *app = NULL;
11529         *vpp = NULL;
11530         *rpp = NULL;
11531         n = stzalloc(sizeof(struct ncmd));
11532         n->type = NCMD;
11533         n->ncmd.args = args;
11534         n->ncmd.assign = vars;
11535         n->ncmd.redirect = redir;
11536         return n;
11537 }
11538
11539 static union node *
11540 parse_command(void)
11541 {
11542         union node *n1, *n2;
11543         union node *ap, **app;
11544         union node *cp, **cpp;
11545         union node *redir, **rpp;
11546         union node **rpp2;
11547         int t;
11548
11549         redir = NULL;
11550         rpp2 = &redir;
11551
11552         switch (readtoken()) {
11553         default:
11554                 raise_error_unexpected_syntax(-1);
11555                 /* NOTREACHED */
11556         case TIF:
11557                 n1 = stzalloc(sizeof(struct nif));
11558                 n1->type = NIF;
11559                 n1->nif.test = list(0);
11560                 if (readtoken() != TTHEN)
11561                         raise_error_unexpected_syntax(TTHEN);
11562                 n1->nif.ifpart = list(0);
11563                 n2 = n1;
11564                 while (readtoken() == TELIF) {
11565                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11566                         n2 = n2->nif.elsepart;
11567                         n2->type = NIF;
11568                         n2->nif.test = list(0);
11569                         if (readtoken() != TTHEN)
11570                                 raise_error_unexpected_syntax(TTHEN);
11571                         n2->nif.ifpart = list(0);
11572                 }
11573                 if (lasttoken == TELSE)
11574                         n2->nif.elsepart = list(0);
11575                 else {
11576                         n2->nif.elsepart = NULL;
11577                         tokpushback = 1;
11578                 }
11579                 t = TFI;
11580                 break;
11581         case TWHILE:
11582         case TUNTIL: {
11583                 int got;
11584                 n1 = stzalloc(sizeof(struct nbinary));
11585                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11586                 n1->nbinary.ch1 = list(0);
11587                 got = readtoken();
11588                 if (got != TDO) {
11589                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11590                                         got == TWORD ? wordtext : ""));
11591                         raise_error_unexpected_syntax(TDO);
11592                 }
11593                 n1->nbinary.ch2 = list(0);
11594                 t = TDONE;
11595                 break;
11596         }
11597         case TFOR:
11598                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11599                         raise_error_syntax("bad for loop variable");
11600                 n1 = stzalloc(sizeof(struct nfor));
11601                 n1->type = NFOR;
11602                 n1->nfor.var = wordtext;
11603                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11604                 if (readtoken() == TIN) {
11605                         app = &ap;
11606                         while (readtoken() == TWORD) {
11607                                 n2 = stzalloc(sizeof(struct narg));
11608                                 n2->type = NARG;
11609                                 /*n2->narg.next = NULL; - stzalloc did it */
11610                                 n2->narg.text = wordtext;
11611                                 n2->narg.backquote = backquotelist;
11612                                 *app = n2;
11613                                 app = &n2->narg.next;
11614                         }
11615                         *app = NULL;
11616                         n1->nfor.args = ap;
11617                         if (lasttoken != TNL && lasttoken != TSEMI)
11618                                 raise_error_unexpected_syntax(-1);
11619                 } else {
11620                         n2 = stzalloc(sizeof(struct narg));
11621                         n2->type = NARG;
11622                         /*n2->narg.next = NULL; - stzalloc did it */
11623                         n2->narg.text = (char *)dolatstr;
11624                         /*n2->narg.backquote = NULL;*/
11625                         n1->nfor.args = n2;
11626                         /*
11627                          * Newline or semicolon here is optional (but note
11628                          * that the original Bourne shell only allowed NL).
11629                          */
11630                         if (lasttoken != TSEMI)
11631                                 tokpushback = 1;
11632                 }
11633                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11634                 if (readtoken() != TDO)
11635                         raise_error_unexpected_syntax(TDO);
11636                 n1->nfor.body = list(0);
11637                 t = TDONE;
11638                 break;
11639         case TCASE:
11640                 n1 = stzalloc(sizeof(struct ncase));
11641                 n1->type = NCASE;
11642                 if (readtoken() != TWORD)
11643                         raise_error_unexpected_syntax(TWORD);
11644                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11645                 n2->type = NARG;
11646                 /*n2->narg.next = NULL; - stzalloc did it */
11647                 n2->narg.text = wordtext;
11648                 n2->narg.backquote = backquotelist;
11649                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11650                 if (readtoken() != TIN)
11651                         raise_error_unexpected_syntax(TIN);
11652                 cpp = &n1->ncase.cases;
11653  next_case:
11654                 checkkwd = CHKNL | CHKKWD;
11655                 t = readtoken();
11656                 while (t != TESAC) {
11657                         if (lasttoken == TLP)
11658                                 readtoken();
11659                         *cpp = cp = stzalloc(sizeof(struct nclist));
11660                         cp->type = NCLIST;
11661                         app = &cp->nclist.pattern;
11662                         for (;;) {
11663                                 *app = ap = stzalloc(sizeof(struct narg));
11664                                 ap->type = NARG;
11665                                 /*ap->narg.next = NULL; - stzalloc did it */
11666                                 ap->narg.text = wordtext;
11667                                 ap->narg.backquote = backquotelist;
11668                                 if (readtoken() != TPIPE)
11669                                         break;
11670                                 app = &ap->narg.next;
11671                                 readtoken();
11672                         }
11673                         //ap->narg.next = NULL;
11674                         if (lasttoken != TRP)
11675                                 raise_error_unexpected_syntax(TRP);
11676                         cp->nclist.body = list(2);
11677
11678                         cpp = &cp->nclist.next;
11679
11680                         checkkwd = CHKNL | CHKKWD;
11681                         t = readtoken();
11682                         if (t != TESAC) {
11683                                 if (t != TENDCASE)
11684                                         raise_error_unexpected_syntax(TENDCASE);
11685                                 goto next_case;
11686                         }
11687                 }
11688                 *cpp = NULL;
11689                 goto redir;
11690         case TLP:
11691                 n1 = stzalloc(sizeof(struct nredir));
11692                 n1->type = NSUBSHELL;
11693                 n1->nredir.n = list(0);
11694                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11695                 t = TRP;
11696                 break;
11697         case TBEGIN:
11698                 n1 = list(0);
11699                 t = TEND;
11700                 break;
11701         IF_BASH_FUNCTION(case TFUNCTION:)
11702         case TWORD:
11703         case TREDIR:
11704                 tokpushback = 1;
11705                 return simplecmd();
11706         }
11707
11708         if (readtoken() != t)
11709                 raise_error_unexpected_syntax(t);
11710
11711  redir:
11712         /* Now check for redirection which may follow command */
11713         checkkwd = CHKKWD | CHKALIAS;
11714         rpp = rpp2;
11715         while (readtoken() == TREDIR) {
11716                 *rpp = n2 = redirnode;
11717                 rpp = &n2->nfile.next;
11718                 parsefname();
11719         }
11720         tokpushback = 1;
11721         *rpp = NULL;
11722         if (redir) {
11723                 if (n1->type != NSUBSHELL) {
11724                         n2 = stzalloc(sizeof(struct nredir));
11725                         n2->type = NREDIR;
11726                         n2->nredir.n = n1;
11727                         n1 = n2;
11728                 }
11729                 n1->nredir.redirect = redir;
11730         }
11731         return n1;
11732 }
11733
11734 #if BASH_DOLLAR_SQUOTE
11735 static int
11736 decode_dollar_squote(void)
11737 {
11738         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11739         int c, cnt;
11740         char *p;
11741         char buf[4];
11742
11743         c = pgetc();
11744         p = strchr(C_escapes, c);
11745         if (p) {
11746                 buf[0] = c;
11747                 p = buf;
11748                 cnt = 3;
11749                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11750                         do {
11751                                 c = pgetc();
11752                                 *++p = c;
11753                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11754                         pungetc();
11755                 } else if (c == 'x') { /* \xHH */
11756                         do {
11757                                 c = pgetc();
11758                                 *++p = c;
11759                         } while (isxdigit(c) && --cnt);
11760                         pungetc();
11761                         if (cnt == 3) { /* \x but next char is "bad" */
11762                                 c = 'x';
11763                                 goto unrecognized;
11764                         }
11765                 } else { /* simple seq like \\ or \t */
11766                         p++;
11767                 }
11768                 *p = '\0';
11769                 p = buf;
11770                 c = bb_process_escape_sequence((void*)&p);
11771         } else { /* unrecognized "\z": print both chars unless ' or " */
11772                 if (c != '\'' && c != '"') {
11773  unrecognized:
11774                         c |= 0x100; /* "please encode \, then me" */
11775                 }
11776         }
11777         return c;
11778 }
11779 #endif
11780
11781 /* Used by expandstr to get here-doc like behaviour. */
11782 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11783
11784 static ALWAYS_INLINE int
11785 realeofmark(const char *eofmark)
11786 {
11787         return eofmark && eofmark != FAKEEOFMARK;
11788 }
11789
11790 /*
11791  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11792  * is not NULL, read a here document.  In the latter case, eofmark is the
11793  * word which marks the end of the document and striptabs is true if
11794  * leading tabs should be stripped from the document.  The argument c
11795  * is the first character of the input token or document.
11796  *
11797  * Because C does not have internal subroutines, I have simulated them
11798  * using goto's to implement the subroutine linkage.  The following macros
11799  * will run code that appears at the end of readtoken1.
11800  */
11801 #define CHECKEND()      {goto checkend; checkend_return:;}
11802 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11803 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11804 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11805 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11806 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11807 static int
11808 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11809 {
11810         /* NB: syntax parameter fits into smallint */
11811         /* c parameter is an unsigned char or PEOF or PEOA */
11812         char *out;
11813         size_t len;
11814         struct nodelist *bqlist;
11815         smallint quotef;
11816         smallint dblquote;
11817         smallint oldstyle;
11818         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11819         smallint pssyntax;   /* we are expanding a prompt string */
11820         int varnest;         /* levels of variables expansion */
11821         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11822         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11823         int dqvarnest;       /* levels of variables expansion within double quotes */
11824
11825         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11826
11827         startlinno = g_parsefile->linno;
11828         bqlist = NULL;
11829         quotef = 0;
11830         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11831 #if ENABLE_ASH_EXPAND_PRMT
11832         pssyntax = (syntax == PSSYNTAX);
11833         if (pssyntax)
11834                 syntax = DQSYNTAX;
11835 #else
11836         pssyntax = 0; /* constant */
11837 #endif
11838         dblquote = (syntax == DQSYNTAX);
11839         varnest = 0;
11840         IF_FEATURE_SH_MATH(arinest = 0;)
11841         IF_FEATURE_SH_MATH(parenlevel = 0;)
11842         dqvarnest = 0;
11843
11844         STARTSTACKSTR(out);
11845  loop:
11846         /* For each line, until end of word */
11847         CHECKEND();     /* set c to PEOF if at end of here document */
11848         for (;;) {      /* until end of line or end of word */
11849                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11850                 switch (SIT(c, syntax)) {
11851                 case CNL:       /* '\n' */
11852                         if (syntax == BASESYNTAX)
11853                                 goto endword;   /* exit outer loop */
11854                         USTPUTC(c, out);
11855                         nlprompt();
11856                         c = pgetc();
11857                         goto loop;              /* continue outer loop */
11858                 case CWORD:
11859                         USTPUTC(c, out);
11860                         break;
11861                 case CCTL:
11862 #if BASH_DOLLAR_SQUOTE
11863                         if (c == '\\' && bash_dollar_squote) {
11864                                 c = decode_dollar_squote();
11865                                 if (c == '\0') {
11866                                         /* skip $'\000', $'\x00' (like bash) */
11867                                         break;
11868                                 }
11869                                 if (c & 0x100) {
11870                                         /* Unknown escape. Encode as '\z' */
11871                                         c = (unsigned char)c;
11872                                         if (eofmark == NULL || dblquote)
11873                                                 USTPUTC(CTLESC, out);
11874                                         USTPUTC('\\', out);
11875                                 }
11876                         }
11877 #endif
11878                         if (eofmark == NULL || dblquote)
11879                                 USTPUTC(CTLESC, out);
11880                         USTPUTC(c, out);
11881                         break;
11882                 case CBACK:     /* backslash */
11883                         c = pgetc_without_PEOA();
11884                         if (c == PEOF) {
11885                                 USTPUTC(CTLESC, out);
11886                                 USTPUTC('\\', out);
11887                                 pungetc();
11888                         } else if (c == '\n') {
11889                                 nlprompt();
11890                         } else {
11891                                 if (pssyntax && c == '$') {
11892                                         USTPUTC(CTLESC, out);
11893                                         USTPUTC('\\', out);
11894                                 }
11895                                 /* Backslash is retained if we are in "str" and next char isn't special */
11896                                 if (dblquote
11897                                  && c != '\\'
11898                                  && c != '`'
11899                                  && c != '$'
11900                                  && (c != '"' || eofmark != NULL)
11901                                 ) {
11902                                         USTPUTC('\\', out);
11903                                 }
11904                                 USTPUTC(CTLESC, out);
11905                                 USTPUTC(c, out);
11906                                 quotef = 1;
11907                         }
11908                         break;
11909                 case CSQUOTE:
11910                         syntax = SQSYNTAX;
11911  quotemark:
11912                         if (eofmark == NULL) {
11913                                 USTPUTC(CTLQUOTEMARK, out);
11914                         }
11915                         break;
11916                 case CDQUOTE:
11917                         syntax = DQSYNTAX;
11918                         dblquote = 1;
11919                         goto quotemark;
11920                 case CENDQUOTE:
11921                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11922                         if (eofmark != NULL && varnest == 0) {
11923                                 USTPUTC(c, out);
11924                         } else {
11925                                 if (dqvarnest == 0) {
11926                                         syntax = BASESYNTAX;
11927                                         dblquote = 0;
11928                                 }
11929                                 quotef = 1;
11930                                 goto quotemark;
11931                         }
11932                         break;
11933                 case CVAR:      /* '$' */
11934                         PARSESUB();             /* parse substitution */
11935                         break;
11936                 case CENDVAR:   /* '}' */
11937                         if (varnest > 0) {
11938                                 varnest--;
11939                                 if (dqvarnest > 0) {
11940                                         dqvarnest--;
11941                                 }
11942                                 c = CTLENDVAR;
11943                         }
11944                         USTPUTC(c, out);
11945                         break;
11946 #if ENABLE_FEATURE_SH_MATH
11947                 case CLP:       /* '(' in arithmetic */
11948                         parenlevel++;
11949                         USTPUTC(c, out);
11950                         break;
11951                 case CRP:       /* ')' in arithmetic */
11952                         if (parenlevel > 0) {
11953                                 parenlevel--;
11954                         } else {
11955                                 if (pgetc_eatbnl() == ')') {
11956                                         c = CTLENDARI;
11957                                         if (--arinest == 0) {
11958                                                 syntax = prevsyntax;
11959                                         }
11960                                 } else {
11961                                         /*
11962                                          * unbalanced parens
11963                                          * (don't 2nd guess - no error)
11964                                          */
11965                                         pungetc();
11966                                 }
11967                         }
11968                         USTPUTC(c, out);
11969                         break;
11970 #endif
11971                 case CBQUOTE:   /* '`' */
11972                         PARSEBACKQOLD();
11973                         break;
11974                 case CENDFILE:
11975                         goto endword;           /* exit outer loop */
11976                 case CIGN:
11977                         break;
11978                 default:
11979                         if (varnest == 0) {
11980 #if BASH_REDIR_OUTPUT
11981                                 if (c == '&') {
11982 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11983                                         if (pgetc() == '>')
11984                                                 c = 0x100 + '>'; /* flag &> */
11985                                         pungetc();
11986                                 }
11987 #endif
11988                                 goto endword;   /* exit outer loop */
11989                         }
11990                         IF_ASH_ALIAS(if (c != PEOA))
11991                                 USTPUTC(c, out);
11992                 }
11993                 c = pgetc();
11994         } /* for (;;) */
11995  endword:
11996
11997 #if ENABLE_FEATURE_SH_MATH
11998         if (syntax == ARISYNTAX)
11999                 raise_error_syntax("missing '))'");
12000 #endif
12001         if (syntax != BASESYNTAX && eofmark == NULL)
12002                 raise_error_syntax("unterminated quoted string");
12003         if (varnest != 0) {
12004                 startlinno = g_parsefile->linno;
12005                 /* { */
12006                 raise_error_syntax("missing '}'");
12007         }
12008         USTPUTC('\0', out);
12009         len = out - (char *)stackblock();
12010         out = stackblock();
12011         if (eofmark == NULL) {
12012                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12013                  && quotef == 0
12014                 ) {
12015                         if (isdigit_str9(out)) {
12016                                 PARSEREDIR(); /* passed as params: out, c */
12017                                 lasttoken = TREDIR;
12018                                 return lasttoken;
12019                         }
12020                         /* else: non-number X seen, interpret it
12021                          * as "NNNX>file" = "NNNX >file" */
12022                 }
12023                 pungetc();
12024         }
12025         quoteflag = quotef;
12026         backquotelist = bqlist;
12027         grabstackblock(len);
12028         wordtext = out;
12029         lasttoken = TWORD;
12030         return lasttoken;
12031 /* end of readtoken routine */
12032
12033 /*
12034  * Check to see whether we are at the end of the here document.  When this
12035  * is called, c is set to the first character of the next input line.  If
12036  * we are at the end of the here document, this routine sets the c to PEOF.
12037  */
12038 checkend: {
12039         if (realeofmark(eofmark)) {
12040                 int markloc;
12041                 char *p;
12042
12043 #if ENABLE_ASH_ALIAS
12044                 if (c == PEOA)
12045                         c = pgetc_without_PEOA();
12046 #endif
12047                 if (striptabs) {
12048                         while (c == '\t') {
12049                                 c = pgetc_without_PEOA();
12050                         }
12051                 }
12052
12053                 markloc = out - (char *)stackblock();
12054                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12055                         if (c != *p)
12056                                 goto more_heredoc;
12057
12058                         c = pgetc_without_PEOA();
12059                 }
12060
12061                 if (c == '\n' || c == PEOF) {
12062                         c = PEOF;
12063                         g_parsefile->linno++;
12064                         needprompt = doprompt;
12065                 } else {
12066                         int len_here;
12067
12068  more_heredoc:
12069                         p = (char *)stackblock() + markloc + 1;
12070                         len_here = out - p;
12071
12072                         if (len_here) {
12073                                 len_here -= (c >= PEOF);
12074                                 c = p[-1];
12075
12076                                 if (len_here) {
12077                                         char *str;
12078
12079                                         str = alloca(len_here + 1);
12080                                         *(char *)mempcpy(str, p, len_here) = '\0';
12081
12082                                         pushstring(str, NULL);
12083                                 }
12084                         }
12085                 }
12086
12087                 STADJUST((char *)stackblock() + markloc - out, out);
12088         }
12089         goto checkend_return;
12090 }
12091
12092 /*
12093  * Parse a redirection operator.  The variable "out" points to a string
12094  * specifying the fd to be redirected.  The variable "c" contains the
12095  * first character of the redirection operator.
12096  */
12097 parseredir: {
12098         /* out is already checked to be a valid number or "" */
12099         int fd = (*out == '\0' ? -1 : atoi(out));
12100         union node *np;
12101
12102         np = stzalloc(sizeof(struct nfile));
12103         if (c == '>') {
12104                 np->nfile.fd = 1;
12105                 c = pgetc();
12106                 if (c == '>')
12107                         np->type = NAPPEND;
12108                 else if (c == '|')
12109                         np->type = NCLOBBER;
12110                 else if (c == '&')
12111                         np->type = NTOFD;
12112                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12113                 else {
12114                         np->type = NTO;
12115                         pungetc();
12116                 }
12117         }
12118 #if BASH_REDIR_OUTPUT
12119         else if (c == 0x100 + '>') { /* this flags &> redirection */
12120                 np->nfile.fd = 1;
12121                 pgetc(); /* this is '>', no need to check */
12122                 np->type = NTO2;
12123         }
12124 #endif
12125         else { /* c == '<' */
12126                 /*np->nfile.fd = 0; - stzalloc did it */
12127                 c = pgetc();
12128                 switch (c) {
12129                 case '<':
12130                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12131                                 np = stzalloc(sizeof(struct nhere));
12132                                 /*np->nfile.fd = 0; - stzalloc did it */
12133                         }
12134                         np->type = NHERE;
12135                         heredoc = stzalloc(sizeof(struct heredoc));
12136                         heredoc->here = np;
12137                         c = pgetc();
12138                         if (c == '-') {
12139                                 heredoc->striptabs = 1;
12140                         } else {
12141                                 /*heredoc->striptabs = 0; - stzalloc did it */
12142                                 pungetc();
12143                         }
12144                         break;
12145
12146                 case '&':
12147                         np->type = NFROMFD;
12148                         break;
12149
12150                 case '>':
12151                         np->type = NFROMTO;
12152                         break;
12153
12154                 default:
12155                         np->type = NFROM;
12156                         pungetc();
12157                         break;
12158                 }
12159         }
12160         if (fd >= 0)
12161                 np->nfile.fd = fd;
12162         redirnode = np;
12163         goto parseredir_return;
12164 }
12165
12166 /*
12167  * Parse a substitution.  At this point, we have read the dollar sign
12168  * and nothing else.
12169  */
12170
12171 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12172  * (assuming ascii char codes, as the original implementation did) */
12173 #define is_special(c) \
12174         (((unsigned)(c) - 33 < 32) \
12175                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12176 parsesub: {
12177         unsigned char subtype;
12178         int typeloc;
12179
12180         c = pgetc_eatbnl();
12181         if ((checkkwd & CHKEOFMARK)
12182          || c > 255 /* PEOA or PEOF */
12183          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12184         ) {
12185 #if BASH_DOLLAR_SQUOTE
12186                 if (syntax != DQSYNTAX && c == '\'')
12187                         bash_dollar_squote = 1;
12188                 else
12189 #endif
12190                         USTPUTC('$', out);
12191                 pungetc();
12192         } else if (c == '(') {
12193                 /* $(command) or $((arith)) */
12194                 if (pgetc_eatbnl() == '(') {
12195 #if ENABLE_FEATURE_SH_MATH
12196                         PARSEARITH();
12197 #else
12198                         raise_error_syntax("support for $((arith)) is disabled");
12199 #endif
12200                 } else {
12201                         pungetc();
12202                         PARSEBACKQNEW();
12203                 }
12204         } else {
12205                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12206                 USTPUTC(CTLVAR, out);
12207                 typeloc = out - (char *)stackblock();
12208                 STADJUST(1, out);
12209                 subtype = VSNORMAL;
12210                 if (c == '{') {
12211                         c = pgetc_eatbnl();
12212                         subtype = 0;
12213                 }
12214  varname:
12215                 if (is_name(c)) {
12216                         /* $[{[#]]NAME[}] */
12217                         do {
12218                                 STPUTC(c, out);
12219                                 c = pgetc_eatbnl();
12220                         } while (is_in_name(c));
12221                 } else if (isdigit(c)) {
12222                         /* $[{[#]]NUM[}] */
12223                         do {
12224                                 STPUTC(c, out);
12225                                 c = pgetc_eatbnl();
12226                         } while (isdigit(c));
12227                 } else {
12228                         /* $[{[#]]<specialchar>[}] */
12229                         int cc = c;
12230
12231                         c = pgetc_eatbnl();
12232                         if (!subtype && cc == '#') {
12233                                 subtype = VSLENGTH;
12234                                 if (c == '_' || isalnum(c))
12235                                         goto varname;
12236                                 cc = c;
12237                                 c = pgetc_eatbnl();
12238                                 if (cc == '}' || c != '}') {
12239                                         pungetc();
12240                                         subtype = 0;
12241                                         c = cc;
12242                                         cc = '#';
12243                                 }
12244                         }
12245
12246                         if (!is_special(cc)) {
12247                                 if (subtype == VSLENGTH)
12248                                         subtype = 0;
12249                                 goto badsub;
12250                         }
12251
12252                         USTPUTC(cc, out);
12253                 }
12254
12255                 if (c != '}' && subtype == VSLENGTH) {
12256                         /* ${#VAR didn't end with } */
12257                         goto badsub;
12258                 }
12259
12260                 if (subtype == 0) {
12261                         static const char types[] ALIGN1 = "}-+?=";
12262                         /* ${VAR...} but not $VAR or ${#VAR} */
12263                         /* c == first char after VAR */
12264                         switch (c) {
12265                         case ':':
12266                                 c = pgetc_eatbnl();
12267 #if BASH_SUBSTR
12268                                 /* This check is only needed to not misinterpret
12269                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12270                                  * constructs.
12271                                  */
12272                                 if (!strchr(types, c)) {
12273                                         subtype = VSSUBSTR;
12274                                         pungetc();
12275                                         break; /* "goto badsub" is bigger (!) */
12276                                 }
12277 #endif
12278                                 subtype = VSNUL;
12279                                 /*FALLTHROUGH*/
12280                         default: {
12281                                 const char *p = strchr(types, c);
12282                                 if (p == NULL)
12283                                         break;
12284                                 subtype |= p - types + VSNORMAL;
12285                                 break;
12286                         }
12287                         case '%':
12288                         case '#': {
12289                                 int cc = c;
12290                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12291                                 c = pgetc_eatbnl();
12292                                 if (c != cc)
12293                                         goto badsub;
12294                                 subtype++;
12295                                 break;
12296                         }
12297 #if BASH_PATTERN_SUBST
12298                         case '/':
12299                                 /* ${v/[/]pattern/repl} */
12300 //TODO: encode pattern and repl separately.
12301 // Currently ${v/$var_with_slash/repl} is horribly broken
12302                                 subtype = VSREPLACE;
12303                                 c = pgetc_eatbnl();
12304                                 if (c != '/')
12305                                         goto badsub;
12306                                 subtype++; /* VSREPLACEALL */
12307                                 break;
12308 #endif
12309                         }
12310                 } else {
12311  badsub:
12312                         pungetc();
12313                 }
12314                 ((unsigned char *)stackblock())[typeloc] = subtype;
12315                 if (subtype != VSNORMAL) {
12316                         varnest++;
12317                         if (dblquote)
12318                                 dqvarnest++;
12319                 }
12320                 STPUTC('=', out);
12321         }
12322         goto parsesub_return;
12323 }
12324
12325 /*
12326  * Called to parse command substitutions.  Newstyle is set if the command
12327  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12328  * list of commands (passed by reference), and savelen is the number of
12329  * characters on the top of the stack which must be preserved.
12330  */
12331 parsebackq: {
12332         struct nodelist **nlpp;
12333         union node *n;
12334         char *str;
12335         size_t savelen;
12336         smallint saveprompt = 0;
12337
12338         str = NULL;
12339         savelen = out - (char *)stackblock();
12340         if (savelen > 0) {
12341                 /*
12342                  * FIXME: this can allocate very large block on stack and SEGV.
12343                  * Example:
12344                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12345                  * allocates 100kb for every command subst. With about
12346                  * a hundred command substitutions stack overflows.
12347                  * With larger prepended string, SEGV happens sooner.
12348                  */
12349                 str = alloca(savelen);
12350                 memcpy(str, stackblock(), savelen);
12351         }
12352
12353         if (oldstyle) {
12354                 /* We must read until the closing backquote, giving special
12355                  * treatment to some slashes, and then push the string and
12356                  * reread it as input, interpreting it normally.
12357                  */
12358                 char *pout;
12359                 size_t psavelen;
12360                 char *pstr;
12361
12362                 STARTSTACKSTR(pout);
12363                 for (;;) {
12364                         int pc;
12365
12366                         setprompt_if(needprompt, 2);
12367                         pc = pgetc();
12368                         switch (pc) {
12369                         case '`':
12370                                 goto done;
12371
12372                         case '\\':
12373                                 pc = pgetc();
12374                                 if (pc == '\n') {
12375                                         nlprompt();
12376                                         /*
12377                                          * If eating a newline, avoid putting
12378                                          * the newline into the new character
12379                                          * stream (via the STPUTC after the
12380                                          * switch).
12381                                          */
12382                                         continue;
12383                                 }
12384                                 if (pc != '\\' && pc != '`' && pc != '$'
12385                                  && (!dblquote || pc != '"')
12386                                 ) {
12387                                         STPUTC('\\', pout);
12388                                 }
12389                                 if (pc <= 255 /* not PEOA or PEOF */) {
12390                                         break;
12391                                 }
12392                                 /* fall through */
12393
12394                         case PEOF:
12395                         IF_ASH_ALIAS(case PEOA:)
12396                                 startlinno = g_parsefile->linno;
12397                                 raise_error_syntax("EOF in backquote substitution");
12398
12399                         case '\n':
12400                                 nlnoprompt();
12401                                 break;
12402
12403                         default:
12404                                 break;
12405                         }
12406                         STPUTC(pc, pout);
12407                 }
12408  done:
12409                 STPUTC('\0', pout);
12410                 psavelen = pout - (char *)stackblock();
12411                 if (psavelen > 0) {
12412                         pstr = grabstackstr(pout);
12413                         setinputstring(pstr);
12414                 }
12415         }
12416         nlpp = &bqlist;
12417         while (*nlpp)
12418                 nlpp = &(*nlpp)->next;
12419         *nlpp = stzalloc(sizeof(**nlpp));
12420         /* (*nlpp)->next = NULL; - stzalloc did it */
12421
12422         if (oldstyle) {
12423                 saveprompt = doprompt;
12424                 doprompt = 0;
12425         }
12426
12427         n = list(2);
12428
12429         if (oldstyle)
12430                 doprompt = saveprompt;
12431         else if (readtoken() != TRP)
12432                 raise_error_unexpected_syntax(TRP);
12433
12434         (*nlpp)->n = n;
12435         if (oldstyle) {
12436                 /*
12437                  * Start reading from old file again, ignoring any pushed back
12438                  * tokens left from the backquote parsing
12439                  */
12440                 popfile();
12441                 tokpushback = 0;
12442         }
12443         while (stackblocksize() <= savelen)
12444                 growstackblock();
12445         STARTSTACKSTR(out);
12446         if (str) {
12447                 memcpy(out, str, savelen);
12448                 STADJUST(savelen, out);
12449         }
12450         USTPUTC(CTLBACKQ, out);
12451         if (oldstyle)
12452                 goto parsebackq_oldreturn;
12453         goto parsebackq_newreturn;
12454 }
12455
12456 #if ENABLE_FEATURE_SH_MATH
12457 /*
12458  * Parse an arithmetic expansion (indicate start of one and set state)
12459  */
12460 parsearith: {
12461         if (++arinest == 1) {
12462                 prevsyntax = syntax;
12463                 syntax = ARISYNTAX;
12464         }
12465         USTPUTC(CTLARI, out);
12466         goto parsearith_return;
12467 }
12468 #endif
12469 } /* end of readtoken */
12470
12471 /*
12472  * Read the next input token.
12473  * If the token is a word, we set backquotelist to the list of cmds in
12474  *      backquotes.  We set quoteflag to true if any part of the word was
12475  *      quoted.
12476  * If the token is TREDIR, then we set redirnode to a structure containing
12477  *      the redirection.
12478  * In all cases, the variable startlinno is set to the number of the line
12479  *      on which the token starts.
12480  *
12481  * [Change comment:  here documents and internal procedures]
12482  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12483  *  word parsing code into a separate routine.  In this case, readtoken
12484  *  doesn't need to have any internal procedures, but parseword does.
12485  *  We could also make parseoperator in essence the main routine, and
12486  *  have parseword (readtoken1?) handle both words and redirection.]
12487  */
12488 #define NEW_xxreadtoken
12489 #ifdef NEW_xxreadtoken
12490 /* singles must be first! */
12491 static const char xxreadtoken_chars[7] ALIGN1 = {
12492         '\n', '(', ')', /* singles */
12493         '&', '|', ';',  /* doubles */
12494         0
12495 };
12496
12497 #define xxreadtoken_singles 3
12498 #define xxreadtoken_doubles 3
12499
12500 static const char xxreadtoken_tokens[] ALIGN1 = {
12501         TNL, TLP, TRP,          /* only single occurrence allowed */
12502         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12503         TEOF,                   /* corresponds to trailing nul */
12504         TAND, TOR, TENDCASE     /* if double occurrence */
12505 };
12506
12507 static int
12508 xxreadtoken(void)
12509 {
12510         int c;
12511
12512         if (tokpushback) {
12513                 tokpushback = 0;
12514                 return lasttoken;
12515         }
12516         setprompt_if(needprompt, 2);
12517         startlinno = g_parsefile->linno;
12518         for (;;) {                      /* until token or start of word found */
12519                 c = pgetc();
12520                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12521                         continue;
12522
12523                 if (c == '#') {
12524                         while ((c = pgetc()) != '\n' && c != PEOF)
12525                                 continue;
12526                         pungetc();
12527                 } else if (c == '\\') {
12528                         if (pgetc() != '\n') {
12529                                 pungetc();
12530                                 break; /* return readtoken1(...) */
12531                         }
12532                         nlprompt();
12533                 } else {
12534                         const char *p;
12535
12536                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12537                         if (c != PEOF) {
12538                                 if (c == '\n') {
12539                                         nlnoprompt();
12540                                 }
12541
12542                                 p = strchr(xxreadtoken_chars, c);
12543                                 if (p == NULL)
12544                                         break; /* return readtoken1(...) */
12545
12546                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12547                                         int cc = pgetc();
12548                                         if (cc == c) {    /* double occurrence? */
12549                                                 p += xxreadtoken_doubles + 1;
12550                                         } else {
12551                                                 pungetc();
12552 #if BASH_REDIR_OUTPUT
12553                                                 if (c == '&' && cc == '>') /* &> */
12554                                                         break; /* return readtoken1(...) */
12555 #endif
12556                                         }
12557                                 }
12558                         }
12559                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12560                         return lasttoken;
12561                 }
12562         } /* for (;;) */
12563
12564         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12565 }
12566 #else /* old xxreadtoken */
12567 #define RETURN(token)   return lasttoken = token
12568 static int
12569 xxreadtoken(void)
12570 {
12571         int c;
12572
12573         if (tokpushback) {
12574                 tokpushback = 0;
12575                 return lasttoken;
12576         }
12577         setprompt_if(needprompt, 2);
12578         startlinno = g_parsefile->linno;
12579         for (;;) {      /* until token or start of word found */
12580                 c = pgetc();
12581                 switch (c) {
12582                 case ' ': case '\t':
12583                 IF_ASH_ALIAS(case PEOA:)
12584                         continue;
12585                 case '#':
12586                         while ((c = pgetc()) != '\n' && c != PEOF)
12587                                 continue;
12588                         pungetc();
12589                         continue;
12590                 case '\\':
12591                         if (pgetc() == '\n') {
12592                                 nlprompt();
12593                                 continue;
12594                         }
12595                         pungetc();
12596                         goto breakloop;
12597                 case '\n':
12598                         nlnoprompt();
12599                         RETURN(TNL);
12600                 case PEOF:
12601                         RETURN(TEOF);
12602                 case '&':
12603                         if (pgetc() == '&')
12604                                 RETURN(TAND);
12605                         pungetc();
12606                         RETURN(TBACKGND);
12607                 case '|':
12608                         if (pgetc() == '|')
12609                                 RETURN(TOR);
12610                         pungetc();
12611                         RETURN(TPIPE);
12612                 case ';':
12613                         if (pgetc() == ';')
12614                                 RETURN(TENDCASE);
12615                         pungetc();
12616                         RETURN(TSEMI);
12617                 case '(':
12618                         RETURN(TLP);
12619                 case ')':
12620                         RETURN(TRP);
12621                 default:
12622                         goto breakloop;
12623                 }
12624         }
12625  breakloop:
12626         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12627 #undef RETURN
12628 }
12629 #endif /* old xxreadtoken */
12630
12631 static int
12632 readtoken(void)
12633 {
12634         int t;
12635         int kwd = checkkwd;
12636 #if DEBUG
12637         smallint alreadyseen = tokpushback;
12638 #endif
12639
12640 #if ENABLE_ASH_ALIAS
12641  top:
12642 #endif
12643
12644         t = xxreadtoken();
12645
12646         /*
12647          * eat newlines
12648          */
12649         if (kwd & CHKNL) {
12650                 while (t == TNL) {
12651                         parseheredoc();
12652                         t = xxreadtoken();
12653                 }
12654         }
12655
12656         if (t != TWORD || quoteflag) {
12657                 goto out;
12658         }
12659
12660         /*
12661          * check for keywords
12662          */
12663         if (kwd & CHKKWD) {
12664                 const char *const *pp;
12665
12666                 pp = findkwd(wordtext);
12667                 if (pp) {
12668                         lasttoken = t = pp - tokname_array;
12669                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12670                         goto out;
12671                 }
12672         }
12673
12674         if (checkkwd & CHKALIAS) {
12675 #if ENABLE_ASH_ALIAS
12676                 struct alias *ap;
12677                 ap = lookupalias(wordtext, 1);
12678                 if (ap != NULL) {
12679                         if (*ap->val) {
12680                                 pushstring(ap->val, ap);
12681                         }
12682                         goto top;
12683                 }
12684 #endif
12685         }
12686  out:
12687         checkkwd = 0;
12688 #if DEBUG
12689         if (!alreadyseen)
12690                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12691         else
12692                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12693 #endif
12694         return t;
12695 }
12696
12697 static int
12698 peektoken(void)
12699 {
12700         int t;
12701
12702         t = readtoken();
12703         tokpushback = 1;
12704         return t;
12705 }
12706
12707 /*
12708  * Read and parse a command.  Returns NODE_EOF on end of file.
12709  * (NULL is a valid parse tree indicating a blank line.)
12710  */
12711 static union node *
12712 parsecmd(int interact)
12713 {
12714         tokpushback = 0;
12715         checkkwd = 0;
12716         heredoclist = 0;
12717         doprompt = interact;
12718         setprompt_if(doprompt, doprompt);
12719         needprompt = 0;
12720         return list(1);
12721 }
12722
12723 /*
12724  * Input any here documents.
12725  */
12726 static void
12727 parseheredoc(void)
12728 {
12729         struct heredoc *here;
12730         union node *n;
12731
12732         here = heredoclist;
12733         heredoclist = NULL;
12734
12735         while (here) {
12736                 setprompt_if(needprompt, 2);
12737                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12738                                 here->eofmark, here->striptabs);
12739                 n = stzalloc(sizeof(struct narg));
12740                 n->narg.type = NARG;
12741                 /*n->narg.next = NULL; - stzalloc did it */
12742                 n->narg.text = wordtext;
12743                 n->narg.backquote = backquotelist;
12744                 here->here->nhere.doc = n;
12745                 here = here->next;
12746         }
12747 }
12748
12749
12750 static const char *
12751 expandstr(const char *ps, int syntax_type)
12752 {
12753         union node n;
12754         int saveprompt;
12755
12756         /* XXX Fix (char *) cast. */
12757         setinputstring((char *)ps);
12758
12759         saveprompt = doprompt;
12760         doprompt = 0;
12761
12762         /* readtoken1() might die horribly.
12763          * Try a prompt with syntactically wrong command:
12764          * PS1='$(date "+%H:%M:%S) > '
12765          */
12766         {
12767                 volatile int saveint;
12768                 struct jmploc *volatile savehandler = exception_handler;
12769                 struct jmploc jmploc;
12770                 SAVE_INT(saveint);
12771                 if (setjmp(jmploc.loc) == 0) {
12772                         exception_handler = &jmploc;
12773                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12774                 }
12775                 exception_handler = savehandler;
12776                 RESTORE_INT(saveint);
12777         }
12778
12779         doprompt = saveprompt;
12780
12781         popfile();
12782
12783         n.narg.type = NARG;
12784         n.narg.next = NULL;
12785         n.narg.text = wordtext;
12786         n.narg.backquote = backquotelist;
12787
12788         expandarg(&n, NULL, EXP_QUOTED);
12789         return stackblock();
12790 }
12791
12792 static inline int
12793 parser_eof(void)
12794 {
12795         return tokpushback && lasttoken == TEOF;
12796 }
12797
12798 /*
12799  * Execute a command or commands contained in a string.
12800  */
12801 static int
12802 evalstring(char *s, int flags)
12803 {
12804         struct jmploc *volatile savehandler;
12805         struct jmploc jmploc;
12806         int ex;
12807
12808         union node *n;
12809         struct stackmark smark;
12810         int status;
12811
12812         s = sstrdup(s);
12813         setinputstring(s);
12814         setstackmark(&smark);
12815
12816         status = 0;
12817         /* On exception inside execution loop, we must popfile().
12818          * Try interactively:
12819          *      readonly a=a
12820          *      command eval "a=b"  # throws "is read only" error
12821          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12822          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12823          */
12824         savehandler = exception_handler;
12825         ex = setjmp(jmploc.loc);
12826         if (ex)
12827                 goto out;
12828         exception_handler = &jmploc;
12829
12830         while ((n = parsecmd(0)) != NODE_EOF) {
12831                 int i;
12832
12833                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12834                 if (n)
12835                         status = i;
12836                 popstackmark(&smark);
12837                 if (evalskip)
12838                         break;
12839         }
12840  out:
12841         popstackmark(&smark);
12842         popfile();
12843         stunalloc(s);
12844
12845         exception_handler = savehandler;
12846         if (ex)
12847                 longjmp(exception_handler->loc, ex);
12848
12849         return status;
12850 }
12851
12852 /*
12853  * The eval command.
12854  */
12855 static int FAST_FUNC
12856 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12857 {
12858         char *p;
12859         char *concat;
12860
12861         if (argv[1]) {
12862                 p = argv[1];
12863                 argv += 2;
12864                 if (argv[0]) {
12865                         STARTSTACKSTR(concat);
12866                         for (;;) {
12867                                 concat = stack_putstr(p, concat);
12868                                 p = *argv++;
12869                                 if (p == NULL)
12870                                         break;
12871                                 STPUTC(' ', concat);
12872                         }
12873                         STPUTC('\0', concat);
12874                         p = grabstackstr(concat);
12875                 }
12876                 return evalstring(p, flags & EV_TESTED);
12877         }
12878         return 0;
12879 }
12880
12881 /*
12882  * Read and execute commands.
12883  * "Top" is nonzero for the top level command loop;
12884  * it turns on prompting if the shell is interactive.
12885  */
12886 static int
12887 cmdloop(int top)
12888 {
12889         union node *n;
12890         struct stackmark smark;
12891         int inter;
12892         int status = 0;
12893         int numeof = 0;
12894
12895         TRACE(("cmdloop(%d) called\n", top));
12896         for (;;) {
12897                 int skip;
12898
12899                 setstackmark(&smark);
12900 #if JOBS
12901                 if (doing_jobctl)
12902                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12903 #endif
12904                 inter = 0;
12905                 if (iflag && top) {
12906                         inter++;
12907                         chkmail();
12908                 }
12909                 n = parsecmd(inter);
12910 #if DEBUG
12911                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12912                         showtree(n);
12913 #endif
12914                 if (n == NODE_EOF) {
12915                         if (!top || numeof >= 50)
12916                                 break;
12917                         if (!stoppedjobs()) {
12918                                 if (!Iflag)
12919                                         break;
12920                                 out2str("\nUse \"exit\" to leave shell.\n");
12921                         }
12922                         numeof++;
12923                 } else if (nflag == 0) {
12924                         int i;
12925
12926                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12927                         job_warning >>= 1;
12928                         numeof = 0;
12929                         i = evaltree(n, 0);
12930                         if (n)
12931                                 status = i;
12932                 }
12933                 popstackmark(&smark);
12934                 skip = evalskip;
12935
12936                 if (skip) {
12937                         evalskip &= ~SKIPFUNC;
12938                         break;
12939                 }
12940         }
12941         return status;
12942 }
12943
12944 /*
12945  * Take commands from a file.  To be compatible we should do a path
12946  * search for the file, which is necessary to find sub-commands.
12947  */
12948 static char *
12949 find_dot_file(char *name)
12950 {
12951         char *fullname;
12952         const char *path = pathval();
12953         struct stat statb;
12954
12955         /* don't try this for absolute or relative paths */
12956         if (strchr(name, '/'))
12957                 return name;
12958
12959         while ((fullname = path_advance(&path, name)) != NULL) {
12960                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12961                         /*
12962                          * Don't bother freeing here, since it will
12963                          * be freed by the caller.
12964                          */
12965                         return fullname;
12966                 }
12967                 if (fullname != name)
12968                         stunalloc(fullname);
12969         }
12970
12971         /* not found in the PATH */
12972         ash_msg_and_raise_error("%s: not found", name);
12973         /* NOTREACHED */
12974 }
12975
12976 static int FAST_FUNC
12977 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12978 {
12979         /* "false; . empty_file; echo $?" should print 0, not 1: */
12980         int status = 0;
12981         char *fullname;
12982         char **argv;
12983         char *args_need_save;
12984         volatile struct shparam saveparam;
12985
12986 //???
12987 //      struct strlist *sp;
12988 //      for (sp = cmdenviron; sp; sp = sp->next)
12989 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12990
12991         nextopt(nullstr); /* handle possible "--" */
12992         argv = argptr;
12993
12994         if (!argv[0]) {
12995                 /* bash says: "bash: .: filename argument required" */
12996                 return 2; /* bash compat */
12997         }
12998
12999         /* This aborts if file isn't found, which is POSIXly correct.
13000          * bash returns exitcode 1 instead.
13001          */
13002         fullname = find_dot_file(argv[0]);
13003         argv++;
13004         args_need_save = argv[0];
13005         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13006                 int argc;
13007                 saveparam = shellparam;
13008                 shellparam.malloced = 0;
13009                 argc = 1;
13010                 while (argv[argc])
13011                         argc++;
13012                 shellparam.nparam = argc;
13013                 shellparam.p = argv;
13014         };
13015
13016         /* This aborts if file can't be opened, which is POSIXly correct.
13017          * bash returns exitcode 1 instead.
13018          */
13019         setinputfile(fullname, INPUT_PUSH_FILE);
13020         commandname = fullname;
13021         status = cmdloop(0);
13022         popfile();
13023
13024         if (args_need_save) {
13025                 freeparam(&shellparam);
13026                 shellparam = saveparam;
13027         };
13028
13029         return status;
13030 }
13031
13032 static int FAST_FUNC
13033 exitcmd(int argc UNUSED_PARAM, char **argv)
13034 {
13035         if (stoppedjobs())
13036                 return 0;
13037         if (argv[1])
13038                 exitstatus = number(argv[1]);
13039         raise_exception(EXEXIT);
13040         /* NOTREACHED */
13041 }
13042
13043 /*
13044  * Read a file containing shell functions.
13045  */
13046 static void
13047 readcmdfile(char *name)
13048 {
13049         setinputfile(name, INPUT_PUSH_FILE);
13050         cmdloop(0);
13051         popfile();
13052 }
13053
13054
13055 /* ============ find_command inplementation */
13056
13057 /*
13058  * Resolve a command name.  If you change this routine, you may have to
13059  * change the shellexec routine as well.
13060  */
13061 static void
13062 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13063 {
13064         struct tblentry *cmdp;
13065         int idx;
13066         int prev;
13067         char *fullname;
13068         struct stat statb;
13069         int e;
13070         int updatetbl;
13071         struct builtincmd *bcmd;
13072
13073         /* If name contains a slash, don't use PATH or hash table */
13074         if (strchr(name, '/') != NULL) {
13075                 entry->u.index = -1;
13076                 if (act & DO_ABS) {
13077                         while (stat(name, &statb) < 0) {
13078 #ifdef SYSV
13079                                 if (errno == EINTR)
13080                                         continue;
13081 #endif
13082                                 entry->cmdtype = CMDUNKNOWN;
13083                                 return;
13084                         }
13085                 }
13086                 entry->cmdtype = CMDNORMAL;
13087                 return;
13088         }
13089
13090 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13091
13092         updatetbl = (path == pathval());
13093         if (!updatetbl) {
13094                 act |= DO_ALTPATH;
13095                 if (strstr(path, "%builtin") != NULL)
13096                         act |= DO_ALTBLTIN;
13097         }
13098
13099         /* If name is in the table, check answer will be ok */
13100         cmdp = cmdlookup(name, 0);
13101         if (cmdp != NULL) {
13102                 int bit;
13103
13104                 switch (cmdp->cmdtype) {
13105                 default:
13106 #if DEBUG
13107                         abort();
13108 #endif
13109                 case CMDNORMAL:
13110                         bit = DO_ALTPATH;
13111                         break;
13112                 case CMDFUNCTION:
13113                         bit = DO_NOFUNC;
13114                         break;
13115                 case CMDBUILTIN:
13116                         bit = DO_ALTBLTIN;
13117                         break;
13118                 }
13119                 if (act & bit) {
13120                         updatetbl = 0;
13121                         cmdp = NULL;
13122                 } else if (cmdp->rehash == 0)
13123                         /* if not invalidated by cd, we're done */
13124                         goto success;
13125         }
13126
13127         /* If %builtin not in path, check for builtin next */
13128         bcmd = find_builtin(name);
13129         if (bcmd) {
13130                 if (IS_BUILTIN_REGULAR(bcmd))
13131                         goto builtin_success;
13132                 if (act & DO_ALTPATH) {
13133                         if (!(act & DO_ALTBLTIN))
13134                                 goto builtin_success;
13135                 } else if (builtinloc <= 0) {
13136                         goto builtin_success;
13137                 }
13138         }
13139
13140 #if ENABLE_FEATURE_SH_STANDALONE
13141         {
13142                 int applet_no = find_applet_by_name(name);
13143                 if (applet_no >= 0) {
13144                         entry->cmdtype = CMDNORMAL;
13145                         entry->u.index = -2 - applet_no;
13146                         return;
13147                 }
13148         }
13149 #endif
13150
13151         /* We have to search path. */
13152         prev = -1;              /* where to start */
13153         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13154                 if (cmdp->cmdtype == CMDBUILTIN)
13155                         prev = builtinloc;
13156                 else
13157                         prev = cmdp->param.index;
13158         }
13159
13160         e = ENOENT;
13161         idx = -1;
13162  loop:
13163         while ((fullname = path_advance(&path, name)) != NULL) {
13164                 stunalloc(fullname);
13165                 /* NB: code below will still use fullname
13166                  * despite it being "unallocated" */
13167                 idx++;
13168                 if (pathopt) {
13169                         if (prefix(pathopt, "builtin")) {
13170                                 if (bcmd)
13171                                         goto builtin_success;
13172                                 continue;
13173                         }
13174                         if ((act & DO_NOFUNC)
13175                          || !prefix(pathopt, "func")
13176                         ) {     /* ignore unimplemented options */
13177                                 continue;
13178                         }
13179                 }
13180                 /* if rehash, don't redo absolute path names */
13181                 if (fullname[0] == '/' && idx <= prev) {
13182                         if (idx < prev)
13183                                 continue;
13184                         TRACE(("searchexec \"%s\": no change\n", name));
13185                         goto success;
13186                 }
13187                 while (stat(fullname, &statb) < 0) {
13188 #ifdef SYSV
13189                         if (errno == EINTR)
13190                                 continue;
13191 #endif
13192                         if (errno != ENOENT && errno != ENOTDIR)
13193                                 e = errno;
13194                         goto loop;
13195                 }
13196                 e = EACCES;     /* if we fail, this will be the error */
13197                 if (!S_ISREG(statb.st_mode))
13198                         continue;
13199                 if (pathopt) {          /* this is a %func directory */
13200                         stalloc(strlen(fullname) + 1);
13201                         /* NB: stalloc will return space pointed by fullname
13202                          * (because we don't have any intervening allocations
13203                          * between stunalloc above and this stalloc) */
13204                         readcmdfile(fullname);
13205                         cmdp = cmdlookup(name, 0);
13206                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13207                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13208                         stunalloc(fullname);
13209                         goto success;
13210                 }
13211                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13212                 if (!updatetbl) {
13213                         entry->cmdtype = CMDNORMAL;
13214                         entry->u.index = idx;
13215                         return;
13216                 }
13217                 INT_OFF;
13218                 cmdp = cmdlookup(name, 1);
13219                 cmdp->cmdtype = CMDNORMAL;
13220                 cmdp->param.index = idx;
13221                 INT_ON;
13222                 goto success;
13223         }
13224
13225         /* We failed.  If there was an entry for this command, delete it */
13226         if (cmdp && updatetbl)
13227                 delete_cmd_entry();
13228         if (act & DO_ERR)
13229                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13230         entry->cmdtype = CMDUNKNOWN;
13231         return;
13232
13233  builtin_success:
13234         if (!updatetbl) {
13235                 entry->cmdtype = CMDBUILTIN;
13236                 entry->u.cmd = bcmd;
13237                 return;
13238         }
13239         INT_OFF;
13240         cmdp = cmdlookup(name, 1);
13241         cmdp->cmdtype = CMDBUILTIN;
13242         cmdp->param.cmd = bcmd;
13243         INT_ON;
13244  success:
13245         cmdp->rehash = 0;
13246         entry->cmdtype = cmdp->cmdtype;
13247         entry->u = cmdp->param;
13248 }
13249
13250
13251 /*
13252  * The trap builtin.
13253  */
13254 static int FAST_FUNC
13255 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13256 {
13257         char *action;
13258         char **ap;
13259         int signo, exitcode;
13260
13261         nextopt(nullstr);
13262         ap = argptr;
13263         if (!*ap) {
13264                 for (signo = 0; signo < NSIG; signo++) {
13265                         char *tr = trap_ptr[signo];
13266                         if (tr) {
13267                                 /* note: bash adds "SIG", but only if invoked
13268                                  * as "bash". If called as "sh", or if set -o posix,
13269                                  * then it prints short signal names.
13270                                  * We are printing short names: */
13271                                 out1fmt("trap -- %s %s\n",
13272                                                 single_quote(tr),
13273                                                 get_signame(signo));
13274                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13275                  * In this case, we will exit very soon, no need to free(). */
13276                                 /* if (trap_ptr != trap && tp[0]) */
13277                                 /*      free(tr); */
13278                         }
13279                 }
13280                 /*
13281                 if (trap_ptr != trap) {
13282                         free(trap_ptr);
13283                         trap_ptr = trap;
13284                 }
13285                 */
13286                 return 0;
13287         }
13288
13289         /* Why the second check?
13290          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13291          * In this case, NUM is signal no, not an action.
13292          */
13293         action = NULL;
13294         if (ap[1] && !is_number(ap[0]))
13295                 action = *ap++;
13296
13297         exitcode = 0;
13298         while (*ap) {
13299                 signo = get_signum(*ap);
13300                 if (signo < 0) {
13301                         /* Mimic bash message exactly */
13302                         ash_msg("%s: invalid signal specification", *ap);
13303                         exitcode = 1;
13304                         goto next;
13305                 }
13306                 INT_OFF;
13307                 if (action) {
13308                         if (LONE_DASH(action))
13309                                 action = NULL;
13310                         else {
13311                                 if (action[0]) /* not NULL and not "" and not "-" */
13312                                         may_have_traps = 1;
13313                                 action = ckstrdup(action);
13314                         }
13315                 }
13316                 free(trap[signo]);
13317                 trap[signo] = action;
13318                 if (signo != 0)
13319                         setsignal(signo);
13320                 INT_ON;
13321  next:
13322                 ap++;
13323         }
13324         return exitcode;
13325 }
13326
13327
13328 /* ============ Builtins */
13329
13330 #if ENABLE_ASH_HELP
13331 static int FAST_FUNC
13332 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13333 {
13334         unsigned col;
13335         unsigned i;
13336
13337         out1fmt(
13338                 "Built-in commands:\n"
13339                 "------------------\n");
13340         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13341                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13342                                         builtintab[i].name + 1);
13343                 if (col > 60) {
13344                         out1fmt("\n");
13345                         col = 0;
13346                 }
13347         }
13348 # if ENABLE_FEATURE_SH_STANDALONE
13349         {
13350                 const char *a = applet_names;
13351                 while (*a) {
13352                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13353                         if (col > 60) {
13354                                 out1fmt("\n");
13355                                 col = 0;
13356                         }
13357                         while (*a++ != '\0')
13358                                 continue;
13359                 }
13360         }
13361 # endif
13362         newline_and_flush(stdout);
13363         return EXIT_SUCCESS;
13364 }
13365 #endif
13366
13367 #if MAX_HISTORY
13368 static int FAST_FUNC
13369 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13370 {
13371         show_history(line_input_state);
13372         return EXIT_SUCCESS;
13373 }
13374 #endif
13375
13376 /*
13377  * The export and readonly commands.
13378  */
13379 static int FAST_FUNC
13380 exportcmd(int argc UNUSED_PARAM, char **argv)
13381 {
13382         struct var *vp;
13383         char *name;
13384         const char *p;
13385         char **aptr;
13386         char opt;
13387         int flag;
13388         int flag_off;
13389
13390         /* "readonly" in bash accepts, but ignores -n.
13391          * We do the same: it saves a conditional in nextopt's param.
13392          */
13393         flag_off = 0;
13394         while ((opt = nextopt("np")) != '\0') {
13395                 if (opt == 'n')
13396                         flag_off = VEXPORT;
13397         }
13398         flag = VEXPORT;
13399         if (argv[0][0] == 'r') {
13400                 flag = VREADONLY;
13401                 flag_off = 0; /* readonly ignores -n */
13402         }
13403         flag_off = ~flag_off;
13404
13405         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13406         {
13407                 aptr = argptr;
13408                 name = *aptr;
13409                 if (name) {
13410                         do {
13411                                 p = strchr(name, '=');
13412                                 if (p != NULL) {
13413                                         p++;
13414                                 } else {
13415                                         vp = *findvar(hashvar(name), name);
13416                                         if (vp) {
13417                                                 vp->flags = ((vp->flags | flag) & flag_off);
13418                                                 continue;
13419                                         }
13420                                 }
13421                                 setvar(name, p, (flag & flag_off));
13422                         } while ((name = *++aptr) != NULL);
13423                         return 0;
13424                 }
13425         }
13426
13427         /* No arguments. Show the list of exported or readonly vars.
13428          * -n is ignored.
13429          */
13430         showvars(argv[0], flag, 0);
13431         return 0;
13432 }
13433
13434 /*
13435  * Delete a function if it exists.
13436  */
13437 static void
13438 unsetfunc(const char *name)
13439 {
13440         struct tblentry *cmdp;
13441
13442         cmdp = cmdlookup(name, 0);
13443         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13444                 delete_cmd_entry();
13445 }
13446
13447 /*
13448  * The unset builtin command.  We unset the function before we unset the
13449  * variable to allow a function to be unset when there is a readonly variable
13450  * with the same name.
13451  */
13452 static int FAST_FUNC
13453 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13454 {
13455         char **ap;
13456         int i;
13457         int flag = 0;
13458
13459         while ((i = nextopt("vf")) != 0) {
13460                 flag = i;
13461         }
13462
13463         for (ap = argptr; *ap; ap++) {
13464                 if (flag != 'f') {
13465                         unsetvar(*ap);
13466                         continue;
13467                 }
13468                 if (flag != 'v')
13469                         unsetfunc(*ap);
13470         }
13471         return 0;
13472 }
13473
13474 static const unsigned char timescmd_str[] ALIGN1 = {
13475         ' ',  offsetof(struct tms, tms_utime),
13476         '\n', offsetof(struct tms, tms_stime),
13477         ' ',  offsetof(struct tms, tms_cutime),
13478         '\n', offsetof(struct tms, tms_cstime),
13479         0
13480 };
13481 static int FAST_FUNC
13482 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13483 {
13484         unsigned clk_tck;
13485         const unsigned char *p;
13486         struct tms buf;
13487
13488         clk_tck = bb_clk_tck();
13489
13490         times(&buf);
13491         p = timescmd_str;
13492         do {
13493                 unsigned sec, frac;
13494                 unsigned long t;
13495                 t = *(clock_t *)(((char *) &buf) + p[1]);
13496                 sec = t / clk_tck;
13497                 frac = t % clk_tck;
13498                 out1fmt("%um%u.%03us%c",
13499                         sec / 60, sec % 60,
13500                         (frac * 1000) / clk_tck,
13501                         p[0]);
13502                 p += 2;
13503         } while (*p);
13504
13505         return 0;
13506 }
13507
13508 #if ENABLE_FEATURE_SH_MATH
13509 /*
13510  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13511  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13512  *
13513  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13514  */
13515 static int FAST_FUNC
13516 letcmd(int argc UNUSED_PARAM, char **argv)
13517 {
13518         arith_t i;
13519
13520         argv++;
13521         if (!*argv)
13522                 ash_msg_and_raise_error("expression expected");
13523         do {
13524                 i = ash_arith(*argv);
13525         } while (*++argv);
13526
13527         return !i;
13528 }
13529 #endif
13530
13531 /*
13532  * The read builtin. Options:
13533  *      -r              Do not interpret '\' specially
13534  *      -s              Turn off echo (tty only)
13535  *      -n NCHARS       Read NCHARS max
13536  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13537  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13538  *      -u FD           Read from given FD instead of fd 0
13539  *      -d DELIM        End on DELIM char, not newline
13540  * This uses unbuffered input, which may be avoidable in some cases.
13541  * TODO: bash also has:
13542  *      -a ARRAY        Read into array[0],[1],etc
13543  *      -e              Use line editing (tty only)
13544  */
13545 static int FAST_FUNC
13546 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13547 {
13548         char *opt_n = NULL;
13549         char *opt_p = NULL;
13550         char *opt_t = NULL;
13551         char *opt_u = NULL;
13552         char *opt_d = NULL; /* optimized out if !BASH */
13553         int read_flags = 0;
13554         const char *r;
13555         int i;
13556
13557         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13558                 switch (i) {
13559                 case 'p':
13560                         opt_p = optionarg;
13561                         break;
13562                 case 'n':
13563                         opt_n = optionarg;
13564                         break;
13565                 case 's':
13566                         read_flags |= BUILTIN_READ_SILENT;
13567                         break;
13568                 case 't':
13569                         opt_t = optionarg;
13570                         break;
13571                 case 'r':
13572                         read_flags |= BUILTIN_READ_RAW;
13573                         break;
13574                 case 'u':
13575                         opt_u = optionarg;
13576                         break;
13577 #if BASH_READ_D
13578                 case 'd':
13579                         opt_d = optionarg;
13580                         break;
13581 #endif
13582                 default:
13583                         break;
13584                 }
13585         }
13586
13587         /* "read -s" needs to save/restore termios, can't allow ^C
13588          * to jump out of it.
13589          */
13590  again:
13591         INT_OFF;
13592         r = shell_builtin_read(setvar0,
13593                 argptr,
13594                 bltinlookup("IFS"), /* can be NULL */
13595                 read_flags,
13596                 opt_n,
13597                 opt_p,
13598                 opt_t,
13599                 opt_u,
13600                 opt_d
13601         );
13602         INT_ON;
13603
13604         if ((uintptr_t)r == 1 && errno == EINTR) {
13605                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13606                  * Correct behavior is to not exit "read"
13607                  */
13608                 if (pending_sig == 0)
13609                         goto again;
13610         }
13611
13612         if ((uintptr_t)r > 1)
13613                 ash_msg_and_raise_error(r);
13614
13615         return (uintptr_t)r;
13616 }
13617
13618 static int FAST_FUNC
13619 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13620 {
13621         static const char permuser[3] ALIGN1 = "ogu";
13622
13623         mode_t mask;
13624         int symbolic_mode = 0;
13625
13626         while (nextopt("S") != '\0') {
13627                 symbolic_mode = 1;
13628         }
13629
13630         INT_OFF;
13631         mask = umask(0);
13632         umask(mask);
13633         INT_ON;
13634
13635         if (*argptr == NULL) {
13636                 if (symbolic_mode) {
13637                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13638                         char *p = buf;
13639                         int i;
13640
13641                         i = 2;
13642                         for (;;) {
13643                                 *p++ = ',';
13644                                 *p++ = permuser[i];
13645                                 *p++ = '=';
13646                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13647                                 if (!(mask & 0400)) *p++ = 'r';
13648                                 if (!(mask & 0200)) *p++ = 'w';
13649                                 if (!(mask & 0100)) *p++ = 'x';
13650                                 mask <<= 3;
13651                                 if (--i < 0)
13652                                         break;
13653                         }
13654                         *p = '\0';
13655                         puts(buf + 1);
13656                 } else {
13657                         out1fmt("%04o\n", mask);
13658                 }
13659         } else {
13660                 char *modestr = *argptr;
13661                 /* numeric umasks are taken as-is */
13662                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13663                 if (!isdigit(modestr[0]))
13664                         mask ^= 0777;
13665                 mask = bb_parse_mode(modestr, mask);
13666                 if ((unsigned)mask > 0777) {
13667                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13668                 }
13669                 if (!isdigit(modestr[0]))
13670                         mask ^= 0777;
13671                 umask(mask);
13672         }
13673         return 0;
13674 }
13675
13676 static int FAST_FUNC
13677 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13678 {
13679         return shell_builtin_ulimit(argv);
13680 }
13681
13682 /* ============ main() and helpers */
13683
13684 /*
13685  * Called to exit the shell.
13686  */
13687 static void
13688 exitshell(void)
13689 {
13690         struct jmploc loc;
13691         char *p;
13692         int status;
13693
13694 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13695         save_history(line_input_state);
13696 #endif
13697         status = exitstatus;
13698         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13699         if (setjmp(loc.loc)) {
13700                 if (exception_type == EXEXIT)
13701                         status = exitstatus;
13702                 goto out;
13703         }
13704         exception_handler = &loc;
13705         p = trap[0];
13706         if (p) {
13707                 trap[0] = NULL;
13708                 evalskip = 0;
13709                 evalstring(p, 0);
13710                 /*free(p); - we'll exit soon */
13711         }
13712  out:
13713         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13714          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13715          */
13716         setjobctl(0);
13717         flush_stdout_stderr();
13718         _exit(status);
13719         /* NOTREACHED */
13720 }
13721
13722 /* Don't inline: conserve stack of caller from having our locals too */
13723 static NOINLINE void
13724 init(void)
13725 {
13726         /* we will never free this */
13727         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13728         basepf.linno = 1;
13729
13730         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13731         setsignal(SIGCHLD);
13732
13733         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13734          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13735          */
13736         signal(SIGHUP, SIG_DFL);
13737
13738         {
13739                 char **envp;
13740                 const char *p;
13741
13742                 initvar();
13743                 for (envp = environ; envp && *envp; envp++) {
13744 /* Used to have
13745  *                      p = endofname(*envp);
13746  *                      if (p != *envp && *p == '=') {
13747  * here to weed out badly-named variables, but this breaks
13748  * scenarios where people do want them passed to children:
13749  * import os
13750  * os.environ["test-test"]="test"
13751  * if os.fork() == 0:
13752  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13753  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13754  */
13755                         if (strchr(*envp, '=')) {
13756                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13757                         }
13758                 }
13759
13760                 setvareq((char*)defoptindvar, VTEXTFIXED);
13761
13762                 setvar0("PPID", utoa(getppid()));
13763 #if BASH_SHLVL_VAR
13764                 p = lookupvar("SHLVL");
13765                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13766 #endif
13767 #if BASH_HOSTNAME_VAR
13768                 if (!lookupvar("HOSTNAME")) {
13769                         struct utsname uts;
13770                         uname(&uts);
13771                         setvar0("HOSTNAME", uts.nodename);
13772                 }
13773 #endif
13774                 p = lookupvar("PWD");
13775                 if (p) {
13776                         struct stat st1, st2;
13777                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13778                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13779                         ) {
13780                                 p = NULL;
13781                         }
13782                 }
13783                 setpwd(p, 0);
13784         }
13785 }
13786
13787
13788 //usage:#define ash_trivial_usage
13789 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13790 //usage:#define ash_full_usage "\n\n"
13791 //usage:        "Unix shell interpreter"
13792
13793 /*
13794  * Process the shell command line arguments.
13795  */
13796 static int
13797 procargs(char **argv)
13798 {
13799         int i;
13800         const char *xminusc;
13801         char **xargv;
13802         int login_sh;
13803
13804         xargv = argv;
13805         login_sh = xargv[0] && xargv[0][0] == '-';
13806         arg0 = xargv[0];
13807         /* if (xargv[0]) - mmm, this is always true! */
13808                 xargv++;
13809         for (i = 0; i < NOPTS; i++)
13810                 optlist[i] = 2;
13811         argptr = xargv;
13812         if (options(/*cmdline:*/ 1, &login_sh)) {
13813                 /* it already printed err message */
13814                 raise_exception(EXERROR);
13815         }
13816         xargv = argptr;
13817         xminusc = minusc;
13818         if (*xargv == NULL) {
13819                 if (xminusc)
13820                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13821                 sflag = 1;
13822         }
13823         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13824                 iflag = 1;
13825         if (mflag == 2)
13826                 mflag = iflag;
13827         for (i = 0; i < NOPTS; i++)
13828                 if (optlist[i] == 2)
13829                         optlist[i] = 0;
13830 #if DEBUG == 2
13831         debug = 1;
13832 #endif
13833         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13834         if (xminusc) {
13835                 minusc = *xargv++;
13836                 if (*xargv)
13837                         goto setarg0;
13838         } else if (!sflag) {
13839                 setinputfile(*xargv, 0);
13840  setarg0:
13841                 arg0 = *xargv++;
13842                 commandname = arg0;
13843         }
13844
13845         shellparam.p = xargv;
13846 #if ENABLE_ASH_GETOPTS
13847         shellparam.optind = 1;
13848         shellparam.optoff = -1;
13849 #endif
13850         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13851         while (*xargv) {
13852                 shellparam.nparam++;
13853                 xargv++;
13854         }
13855         optschanged();
13856
13857         return login_sh;
13858 }
13859
13860 /*
13861  * Read /etc/profile, ~/.profile, $ENV.
13862  */
13863 static void
13864 read_profile(const char *name)
13865 {
13866         name = expandstr(name, DQSYNTAX);
13867         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13868                 return;
13869         cmdloop(0);
13870         popfile();
13871 }
13872
13873 /*
13874  * This routine is called when an error or an interrupt occurs in an
13875  * interactive shell and control is returned to the main command loop.
13876  * (In dash, this function is auto-generated by build machinery).
13877  */
13878 static void
13879 reset(void)
13880 {
13881         /* from eval.c: */
13882         evalskip = 0;
13883         loopnest = 0;
13884
13885         /* from expand.c: */
13886         ifsfree();
13887
13888         /* from input.c: */
13889         g_parsefile->left_in_buffer = 0;
13890         g_parsefile->left_in_line = 0;      /* clear input buffer */
13891         popallfiles();
13892
13893         /* from redir.c: */
13894         unwindredir(NULL);
13895
13896         /* from var.c: */
13897         unwindlocalvars(NULL);
13898 }
13899
13900 #if PROFILE
13901 static short profile_buf[16384];
13902 extern int etext();
13903 #endif
13904
13905 /*
13906  * Main routine.  We initialize things, parse the arguments, execute
13907  * profiles if we're a login shell, and then call cmdloop to execute
13908  * commands.  The setjmp call sets up the location to jump to when an
13909  * exception occurs.  When an exception occurs the variable "state"
13910  * is used to figure out how far we had gotten.
13911  */
13912 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13913 int ash_main(int argc UNUSED_PARAM, char **argv)
13914 {
13915         volatile smallint state;
13916         struct jmploc jmploc;
13917         struct stackmark smark;
13918         int login_sh;
13919
13920         /* Initialize global data */
13921         INIT_G_misc();
13922         INIT_G_memstack();
13923         INIT_G_var();
13924 #if ENABLE_ASH_ALIAS
13925         INIT_G_alias();
13926 #endif
13927         INIT_G_cmdtable();
13928
13929 #if PROFILE
13930         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13931 #endif
13932
13933 #if ENABLE_FEATURE_EDITING
13934         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13935 #endif
13936         state = 0;
13937         if (setjmp(jmploc.loc)) {
13938                 smallint e;
13939                 smallint s;
13940
13941                 reset();
13942
13943                 e = exception_type;
13944                 s = state;
13945                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13946                         exitshell();
13947                 }
13948                 if (e == EXINT) {
13949                         newline_and_flush(stderr);
13950                 }
13951
13952                 popstackmark(&smark);
13953                 FORCE_INT_ON; /* enable interrupts */
13954                 if (s == 1)
13955                         goto state1;
13956                 if (s == 2)
13957                         goto state2;
13958                 if (s == 3)
13959                         goto state3;
13960                 goto state4;
13961         }
13962         exception_handler = &jmploc;
13963         rootpid = getpid();
13964
13965         init();
13966         setstackmark(&smark);
13967         login_sh = procargs(argv);
13968 #if DEBUG
13969         TRACE(("Shell args: "));
13970         trace_puts_args(argv);
13971 #endif
13972
13973         if (login_sh) {
13974                 const char *hp;
13975
13976                 state = 1;
13977                 read_profile("/etc/profile");
13978  state1:
13979                 state = 2;
13980                 hp = lookupvar("HOME");
13981                 if (hp)
13982                         read_profile("$HOME/.profile");
13983         }
13984  state2:
13985         state = 3;
13986         if (
13987 #ifndef linux
13988          getuid() == geteuid() && getgid() == getegid() &&
13989 #endif
13990          iflag
13991         ) {
13992                 const char *shinit = lookupvar("ENV");
13993                 if (shinit != NULL && *shinit != '\0')
13994                         read_profile(shinit);
13995         }
13996         popstackmark(&smark);
13997  state3:
13998         state = 4;
13999         if (minusc) {
14000                 /* evalstring pushes parsefile stack.
14001                  * Ensure we don't falsely claim that 0 (stdin)
14002                  * is one of stacked source fds.
14003                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14004                 // if (!sflag) g_parsefile->pf_fd = -1;
14005                 // ^^ not necessary since now we special-case fd 0
14006                 // in save_fd_on_redirect()
14007                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14008         }
14009
14010         if (sflag || minusc == NULL) {
14011 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14012                 if (iflag) {
14013                         const char *hp = lookupvar("HISTFILE");
14014                         if (!hp) {
14015                                 hp = lookupvar("HOME");
14016                                 if (hp) {
14017                                         INT_OFF;
14018                                         hp = concat_path_file(hp, ".ash_history");
14019                                         setvar0("HISTFILE", hp);
14020                                         free((char*)hp);
14021                                         INT_ON;
14022                                         hp = lookupvar("HISTFILE");
14023                                 }
14024                         }
14025                         if (hp)
14026                                 line_input_state->hist_file = hp;
14027 # if ENABLE_FEATURE_SH_HISTFILESIZE
14028                         hp = lookupvar("HISTFILESIZE");
14029                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14030 # endif
14031                 }
14032 #endif
14033  state4: /* XXX ??? - why isn't this before the "if" statement */
14034                 cmdloop(1);
14035         }
14036 #if PROFILE
14037         monitor(0);
14038 #endif
14039 #ifdef GPROF
14040         {
14041                 extern void _mcleanup(void);
14042                 _mcleanup();
14043         }
14044 #endif
14045         TRACE(("End of main reached\n"));
14046         exitshell();
14047         /* NOTREACHED */
14048 }
14049
14050
14051 /*-
14052  * Copyright (c) 1989, 1991, 1993, 1994
14053  *      The Regents of the University of California.  All rights reserved.
14054  *
14055  * This code is derived from software contributed to Berkeley by
14056  * Kenneth Almquist.
14057  *
14058  * Redistribution and use in source and binary forms, with or without
14059  * modification, are permitted provided that the following conditions
14060  * are met:
14061  * 1. Redistributions of source code must retain the above copyright
14062  *    notice, this list of conditions and the following disclaimer.
14063  * 2. Redistributions in binary form must reproduce the above copyright
14064  *    notice, this list of conditions and the following disclaimer in the
14065  *    documentation and/or other materials provided with the distribution.
14066  * 3. Neither the name of the University nor the names of its contributors
14067  *    may be used to endorse or promote products derived from this software
14068  *    without specific prior written permission.
14069  *
14070  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14071  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14072  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14073  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14074  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14075  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14076  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14077  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14078  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14079  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14080  * SUCH DAMAGE.
14081  */