od_bloaty: fix debug code
[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 ALWAYS_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_STANDALONE \
10015  && ENABLE_FEATURE_SH_NOFORK \
10016  && NUM_APPLETS > 1
10017 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10018  *     around run_nofork_applet() call.
10019  * (2) Should this check also be done in forkshell()?
10020  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10021  */
10022                 /* find_command() encodes applet_no as (-2 - applet_no) */
10023                 int applet_no = (- cmdentry.u.index - 2);
10024                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10025                         char **sv_environ;
10026
10027                         INT_OFF;
10028                         sv_environ = environ;
10029                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10030                         /*
10031                          * Run <applet>_main().
10032                          * Signals (^C) can't interrupt here.
10033                          * Otherwise we can mangle stdio or malloc internal state.
10034                          * This makes applets which can run for a long time
10035                          * and/or wait for user input ineligible for NOFORK:
10036                          * for example, "yes" or "rm" (rm -i waits for input).
10037                          */
10038                         status = run_nofork_applet(applet_no, argv);
10039                         environ = sv_environ;
10040                         /*
10041                          * Try enabling NOFORK for "yes" applet.
10042                          * ^C _will_ stop it (write returns EINTR),
10043                          * but this causes stdout FILE to be stuck
10044                          * and needing clearerr(). What if other applets
10045                          * also can get EINTRs? Do we need to switch
10046                          * our signals to SA_RESTART?
10047                          */
10048                         /*clearerr(stdout);*/
10049                         INT_ON;
10050                         break;
10051                 }
10052 #endif
10053                 /* Can we avoid forking? For example, very last command
10054                  * in a script or a subshell does not need forking,
10055                  * we can just exec it.
10056                  */
10057                 if (!(flags & EV_EXIT) || may_have_traps) {
10058                         /* No, forking off a child is necessary */
10059                         INT_OFF;
10060                         get_tty_state();
10061                         jp = makejob(/*cmd,*/ 1);
10062                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10063                                 /* parent */
10064                                 status = waitforjob(jp);
10065                                 INT_ON;
10066                                 TRACE(("forked child exited with %d\n", status));
10067                                 break;
10068                         }
10069                         /* child */
10070                         FORCE_INT_ON;
10071                         /* fall through to exec'ing external program */
10072                 }
10073                 listsetvar(varlist.list, VEXPORT|VSTACK);
10074                 shellexec(argv[0], argv, path, cmdentry.u.index);
10075                 /* NOTREACHED */
10076         } /* default */
10077         case CMDBUILTIN:
10078                 if (spclbltin > 0 || argc == 0) {
10079                         poplocalvars(1);
10080                         if (cmd_is_exec && argc > 1)
10081                                 listsetvar(varlist.list, VEXPORT);
10082                 }
10083
10084                 /* Tight loop with builtins only:
10085                  * "while kill -0 $child; do true; done"
10086                  * will never exit even if $child died, unless we do this
10087                  * to reap the zombie and make kill detect that it's gone: */
10088                 dowait(DOWAIT_NONBLOCK, NULL);
10089
10090                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10091                         if (exception_type == EXERROR && spclbltin <= 0) {
10092                                 FORCE_INT_ON;
10093                                 goto readstatus;
10094                         }
10095  raise:
10096                         longjmp(exception_handler->loc, 1);
10097                 }
10098                 goto readstatus;
10099
10100         case CMDFUNCTION:
10101                 poplocalvars(1);
10102                 /* See above for the rationale */
10103                 dowait(DOWAIT_NONBLOCK, NULL);
10104                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10105                         goto raise;
10106  readstatus:
10107                 status = exitstatus;
10108                 break;
10109         } /* switch */
10110
10111  out:
10112         if (cmd->ncmd.redirect)
10113                 popredir(/*drop:*/ cmd_is_exec);
10114         unwindredir(redir_stop);
10115         unwindlocalvars(localvar_stop);
10116         if (lastarg) {
10117                 /* dsl: I think this is intended to be used to support
10118                  * '_' in 'vi' command mode during line editing...
10119                  * However I implemented that within libedit itself.
10120                  */
10121                 setvar0("_", lastarg);
10122         }
10123         popstackmark(&smark);
10124
10125         return status;
10126 }
10127
10128 static int
10129 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10130 {
10131         char *volatile savecmdname;
10132         struct jmploc *volatile savehandler;
10133         struct jmploc jmploc;
10134         int status;
10135         int i;
10136
10137         savecmdname = commandname;
10138         savehandler = exception_handler;
10139         i = setjmp(jmploc.loc);
10140         if (i)
10141                 goto cmddone;
10142         exception_handler = &jmploc;
10143         commandname = argv[0];
10144         argptr = argv + 1;
10145         optptr = NULL;                  /* initialize nextopt */
10146         if (cmd == EVALCMD)
10147                 status = evalcmd(argc, argv, flags);
10148         else
10149                 status = (*cmd->builtin)(argc, argv);
10150         flush_stdout_stderr();
10151         status |= ferror(stdout);
10152         exitstatus = status;
10153  cmddone:
10154         clearerr(stdout);
10155         commandname = savecmdname;
10156         exception_handler = savehandler;
10157
10158         return i;
10159 }
10160
10161 static int
10162 goodname(const char *p)
10163 {
10164         return endofname(p)[0] == '\0';
10165 }
10166
10167
10168 /*
10169  * Search for a command.  This is called before we fork so that the
10170  * location of the command will be available in the parent as well as
10171  * the child.  The check for "goodname" is an overly conservative
10172  * check that the name will not be subject to expansion.
10173  */
10174 static void
10175 prehash(union node *n)
10176 {
10177         struct cmdentry entry;
10178
10179         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10180                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10181 }
10182
10183
10184 /* ============ Builtin commands
10185  *
10186  * Builtin commands whose functions are closely tied to evaluation
10187  * are implemented here.
10188  */
10189
10190 /*
10191  * Handle break and continue commands.  Break, continue, and return are
10192  * all handled by setting the evalskip flag.  The evaluation routines
10193  * above all check this flag, and if it is set they start skipping
10194  * commands rather than executing them.  The variable skipcount is
10195  * the number of loops to break/continue, or the number of function
10196  * levels to return.  (The latter is always 1.)  It should probably
10197  * be an error to break out of more loops than exist, but it isn't
10198  * in the standard shell so we don't make it one here.
10199  */
10200 static int FAST_FUNC
10201 breakcmd(int argc UNUSED_PARAM, char **argv)
10202 {
10203         int n = argv[1] ? number(argv[1]) : 1;
10204
10205         if (n <= 0)
10206                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10207         if (n > loopnest)
10208                 n = loopnest;
10209         if (n > 0) {
10210                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10211                 skipcount = n;
10212         }
10213         return 0;
10214 }
10215
10216
10217 /*
10218  * This implements the input routines used by the parser.
10219  */
10220
10221 enum {
10222         INPUT_PUSH_FILE = 1,
10223         INPUT_NOFILE_OK = 2,
10224 };
10225
10226 static smallint checkkwd;
10227 /* values of checkkwd variable */
10228 #define CHKALIAS        0x1
10229 #define CHKKWD          0x2
10230 #define CHKNL           0x4
10231 #define CHKEOFMARK      0x8
10232
10233 /*
10234  * Push a string back onto the input at this current parsefile level.
10235  * We handle aliases this way.
10236  */
10237 #if !ENABLE_ASH_ALIAS
10238 #define pushstring(s, ap) pushstring(s)
10239 #endif
10240 static void
10241 pushstring(char *s, struct alias *ap)
10242 {
10243         struct strpush *sp;
10244         int len;
10245
10246         len = strlen(s);
10247         INT_OFF;
10248         if (g_parsefile->strpush) {
10249                 sp = ckzalloc(sizeof(*sp));
10250                 sp->prev = g_parsefile->strpush;
10251         } else {
10252                 sp = &(g_parsefile->basestrpush);
10253         }
10254         g_parsefile->strpush = sp;
10255         sp->prev_string = g_parsefile->next_to_pgetc;
10256         sp->prev_left_in_line = g_parsefile->left_in_line;
10257         sp->unget = g_parsefile->unget;
10258         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10259 #if ENABLE_ASH_ALIAS
10260         sp->ap = ap;
10261         if (ap) {
10262                 ap->flag |= ALIASINUSE;
10263                 sp->string = s;
10264         }
10265 #endif
10266         g_parsefile->next_to_pgetc = s;
10267         g_parsefile->left_in_line = len;
10268         g_parsefile->unget = 0;
10269         INT_ON;
10270 }
10271
10272 static void
10273 popstring(void)
10274 {
10275         struct strpush *sp = g_parsefile->strpush;
10276
10277         INT_OFF;
10278 #if ENABLE_ASH_ALIAS
10279         if (sp->ap) {
10280                 if (g_parsefile->next_to_pgetc[-1] == ' '
10281                  || g_parsefile->next_to_pgetc[-1] == '\t'
10282                 ) {
10283                         checkkwd |= CHKALIAS;
10284                 }
10285                 if (sp->string != sp->ap->val) {
10286                         free(sp->string);
10287                 }
10288                 sp->ap->flag &= ~ALIASINUSE;
10289                 if (sp->ap->flag & ALIASDEAD) {
10290                         unalias(sp->ap->name);
10291                 }
10292         }
10293 #endif
10294         g_parsefile->next_to_pgetc = sp->prev_string;
10295         g_parsefile->left_in_line = sp->prev_left_in_line;
10296         g_parsefile->unget = sp->unget;
10297         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10298         g_parsefile->strpush = sp->prev;
10299         if (sp != &(g_parsefile->basestrpush))
10300                 free(sp);
10301         INT_ON;
10302 }
10303
10304 static int
10305 preadfd(void)
10306 {
10307         int nr;
10308         char *buf = g_parsefile->buf;
10309
10310         g_parsefile->next_to_pgetc = buf;
10311 #if ENABLE_FEATURE_EDITING
10312  retry:
10313         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10314                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10315         else {
10316 # if ENABLE_ASH_IDLE_TIMEOUT
10317                 int timeout = -1;
10318                 if (iflag) {
10319                         const char *tmout_var = lookupvar("TMOUT");
10320                         if (tmout_var) {
10321                                 timeout = atoi(tmout_var) * 1000;
10322                                 if (timeout <= 0)
10323                                         timeout = -1;
10324                         }
10325                 }
10326                 line_input_state->timeout = timeout;
10327 # endif
10328 # if ENABLE_FEATURE_TAB_COMPLETION
10329                 line_input_state->path_lookup = pathval();
10330 # endif
10331                 reinit_unicode_for_ash();
10332                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10333                 if (nr == 0) {
10334                         /* ^C pressed, "convert" to SIGINT */
10335                         write(STDOUT_FILENO, "^C", 2);
10336                         if (trap[SIGINT]) {
10337                                 buf[0] = '\n';
10338                                 buf[1] = '\0';
10339                                 raise(SIGINT);
10340                                 return 1;
10341                         }
10342                         exitstatus = 128 + SIGINT;
10343                         bb_putchar('\n');
10344                         goto retry;
10345                 }
10346                 if (nr < 0) {
10347                         if (errno == 0) {
10348                                 /* Ctrl+D pressed */
10349                                 nr = 0;
10350                         }
10351 # if ENABLE_ASH_IDLE_TIMEOUT
10352                         else if (errno == EAGAIN && timeout > 0) {
10353                                 puts("\007timed out waiting for input: auto-logout");
10354                                 exitshell();
10355                         }
10356 # endif
10357                 }
10358         }
10359 #else
10360         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10361 #endif
10362
10363 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10364         if (nr < 0) {
10365                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10366                         int flags = fcntl(0, F_GETFL);
10367                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10368                                 flags &= ~O_NONBLOCK;
10369                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10370                                         out2str("sh: turning off NDELAY mode\n");
10371                                         goto retry;
10372                                 }
10373                         }
10374                 }
10375         }
10376 #endif
10377         return nr;
10378 }
10379
10380 /*
10381  * Refill the input buffer and return the next input character:
10382  *
10383  * 1) If a string was pushed back on the input, pop it;
10384  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10385  *    or we are reading from a string so we can't refill the buffer,
10386  *    return EOF.
10387  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10388  * 4) Process input up to the next newline, deleting nul characters.
10389  */
10390 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10391 #define pgetc_debug(...) ((void)0)
10392 static int pgetc(void);
10393 static int
10394 preadbuffer(void)
10395 {
10396         char *q;
10397         int more;
10398
10399         if (g_parsefile->strpush) {
10400 #if ENABLE_ASH_ALIAS
10401                 if (g_parsefile->left_in_line == -1
10402                  && g_parsefile->strpush->ap
10403                  && g_parsefile->next_to_pgetc[-1] != ' '
10404                  && g_parsefile->next_to_pgetc[-1] != '\t'
10405                 ) {
10406                         pgetc_debug("preadbuffer PEOA");
10407                         return PEOA;
10408                 }
10409 #endif
10410                 popstring();
10411                 return pgetc();
10412         }
10413         /* on both branches above g_parsefile->left_in_line < 0.
10414          * "pgetc" needs refilling.
10415          */
10416
10417         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10418          * pungetc() may increment it a few times.
10419          * Assuming it won't increment it to less than -90.
10420          */
10421         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10422                 pgetc_debug("preadbuffer PEOF1");
10423                 /* even in failure keep left_in_line and next_to_pgetc
10424                  * in lock step, for correct multi-layer pungetc.
10425                  * left_in_line was decremented before preadbuffer(),
10426                  * must inc next_to_pgetc: */
10427                 g_parsefile->next_to_pgetc++;
10428                 return PEOF;
10429         }
10430
10431         more = g_parsefile->left_in_buffer;
10432         if (more <= 0) {
10433                 flush_stdout_stderr();
10434  again:
10435                 more = preadfd();
10436                 if (more <= 0) {
10437                         /* don't try reading again */
10438                         g_parsefile->left_in_line = -99;
10439                         pgetc_debug("preadbuffer PEOF2");
10440                         g_parsefile->next_to_pgetc++;
10441                         return PEOF;
10442                 }
10443         }
10444
10445         /* Find out where's the end of line.
10446          * Set g_parsefile->left_in_line
10447          * and g_parsefile->left_in_buffer acordingly.
10448          * NUL chars are deleted.
10449          */
10450         q = g_parsefile->next_to_pgetc;
10451         for (;;) {
10452                 char c;
10453
10454                 more--;
10455
10456                 c = *q;
10457                 if (c == '\0') {
10458                         memmove(q, q + 1, more);
10459                 } else {
10460                         q++;
10461                         if (c == '\n') {
10462                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10463                                 break;
10464                         }
10465                 }
10466
10467                 if (more <= 0) {
10468                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10469                         if (g_parsefile->left_in_line < 0)
10470                                 goto again;
10471                         break;
10472                 }
10473         }
10474         g_parsefile->left_in_buffer = more;
10475
10476         if (vflag) {
10477                 char save = *q;
10478                 *q = '\0';
10479                 out2str(g_parsefile->next_to_pgetc);
10480                 *q = save;
10481         }
10482
10483         pgetc_debug("preadbuffer at %d:%p'%s'",
10484                         g_parsefile->left_in_line,
10485                         g_parsefile->next_to_pgetc,
10486                         g_parsefile->next_to_pgetc);
10487         return (unsigned char)*g_parsefile->next_to_pgetc++;
10488 }
10489
10490 static void
10491 nlprompt(void)
10492 {
10493         g_parsefile->linno++;
10494         setprompt_if(doprompt, 2);
10495 }
10496 static void
10497 nlnoprompt(void)
10498 {
10499         g_parsefile->linno++;
10500         needprompt = doprompt;
10501 }
10502
10503 static int
10504 pgetc(void)
10505 {
10506         int c;
10507
10508         pgetc_debug("pgetc at %d:%p'%s'",
10509                         g_parsefile->left_in_line,
10510                         g_parsefile->next_to_pgetc,
10511                         g_parsefile->next_to_pgetc);
10512         if (g_parsefile->unget)
10513                 return g_parsefile->lastc[--g_parsefile->unget];
10514
10515         if (--g_parsefile->left_in_line >= 0)
10516                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10517         else
10518                 c = preadbuffer();
10519
10520         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10521         g_parsefile->lastc[0] = c;
10522
10523         return c;
10524 }
10525
10526 #if ENABLE_ASH_ALIAS
10527 static int
10528 pgetc_without_PEOA(void)
10529 {
10530         int c;
10531         do {
10532                 pgetc_debug("pgetc at %d:%p'%s'",
10533                                 g_parsefile->left_in_line,
10534                                 g_parsefile->next_to_pgetc,
10535                                 g_parsefile->next_to_pgetc);
10536                 c = pgetc();
10537         } while (c == PEOA);
10538         return c;
10539 }
10540 #else
10541 # define pgetc_without_PEOA() pgetc()
10542 #endif
10543
10544 /*
10545  * Undo a call to pgetc.  Only two characters may be pushed back.
10546  * PEOF may be pushed back.
10547  */
10548 static void
10549 pungetc(void)
10550 {
10551         g_parsefile->unget++;
10552 }
10553
10554 /* This one eats backslash+newline */
10555 static int
10556 pgetc_eatbnl(void)
10557 {
10558         int c;
10559
10560         while ((c = pgetc()) == '\\') {
10561                 if (pgetc() != '\n') {
10562                         pungetc();
10563                         break;
10564                 }
10565
10566                 nlprompt();
10567         }
10568
10569         return c;
10570 }
10571
10572 /*
10573  * To handle the "." command, a stack of input files is used.  Pushfile
10574  * adds a new entry to the stack and popfile restores the previous level.
10575  */
10576 static void
10577 pushfile(void)
10578 {
10579         struct parsefile *pf;
10580
10581         pf = ckzalloc(sizeof(*pf));
10582         pf->prev = g_parsefile;
10583         pf->pf_fd = -1;
10584         /*pf->strpush = NULL; - ckzalloc did it */
10585         /*pf->basestrpush.prev = NULL;*/
10586         /*pf->unget = 0;*/
10587         g_parsefile = pf;
10588 }
10589
10590 static void
10591 popfile(void)
10592 {
10593         struct parsefile *pf = g_parsefile;
10594
10595         if (pf == &basepf)
10596                 return;
10597
10598         INT_OFF;
10599         if (pf->pf_fd >= 0)
10600                 close(pf->pf_fd);
10601         free(pf->buf);
10602         while (pf->strpush)
10603                 popstring();
10604         g_parsefile = pf->prev;
10605         free(pf);
10606         INT_ON;
10607 }
10608
10609 /*
10610  * Return to top level.
10611  */
10612 static void
10613 popallfiles(void)
10614 {
10615         while (g_parsefile != &basepf)
10616                 popfile();
10617 }
10618
10619 /*
10620  * Close the file(s) that the shell is reading commands from.  Called
10621  * after a fork is done.
10622  */
10623 static void
10624 closescript(void)
10625 {
10626         popallfiles();
10627         if (g_parsefile->pf_fd > 0) {
10628                 close(g_parsefile->pf_fd);
10629                 g_parsefile->pf_fd = 0;
10630         }
10631 }
10632
10633 /*
10634  * Like setinputfile, but takes an open file descriptor.  Call this with
10635  * interrupts off.
10636  */
10637 static void
10638 setinputfd(int fd, int push)
10639 {
10640         if (push) {
10641                 pushfile();
10642                 g_parsefile->buf = NULL;
10643         }
10644         g_parsefile->pf_fd = fd;
10645         if (g_parsefile->buf == NULL)
10646                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10647         g_parsefile->left_in_buffer = 0;
10648         g_parsefile->left_in_line = 0;
10649         g_parsefile->linno = 1;
10650 }
10651
10652 /*
10653  * Set the input to take input from a file.  If push is set, push the
10654  * old input onto the stack first.
10655  */
10656 static int
10657 setinputfile(const char *fname, int flags)
10658 {
10659         int fd;
10660
10661         INT_OFF;
10662         fd = open(fname, O_RDONLY);
10663         if (fd < 0) {
10664                 if (flags & INPUT_NOFILE_OK)
10665                         goto out;
10666                 exitstatus = 127;
10667                 ash_msg_and_raise_perror("can't open '%s'", fname);
10668         }
10669         if (fd < 10)
10670                 fd = savefd(fd);
10671         else
10672                 close_on_exec_on(fd);
10673         setinputfd(fd, flags & INPUT_PUSH_FILE);
10674  out:
10675         INT_ON;
10676         return fd;
10677 }
10678
10679 /*
10680  * Like setinputfile, but takes input from a string.
10681  */
10682 static void
10683 setinputstring(char *string)
10684 {
10685         INT_OFF;
10686         pushfile();
10687         g_parsefile->next_to_pgetc = string;
10688         g_parsefile->left_in_line = strlen(string);
10689         g_parsefile->buf = NULL;
10690         g_parsefile->linno = 1;
10691         INT_ON;
10692 }
10693
10694
10695 /*
10696  * Routines to check for mail.
10697  */
10698
10699 #if ENABLE_ASH_MAIL
10700
10701 /* Hash of mtimes of mailboxes */
10702 static unsigned mailtime_hash;
10703 /* Set if MAIL or MAILPATH is changed. */
10704 static smallint mail_var_path_changed;
10705
10706 /*
10707  * Print appropriate message(s) if mail has arrived.
10708  * If mail_var_path_changed is set,
10709  * then the value of MAIL has mail_var_path_changed,
10710  * so we just update the values.
10711  */
10712 static void
10713 chkmail(void)
10714 {
10715         const char *mpath;
10716         char *p;
10717         char *q;
10718         unsigned new_hash;
10719         struct stackmark smark;
10720         struct stat statb;
10721
10722         setstackmark(&smark);
10723         mpath = mpathset() ? mpathval() : mailval();
10724         new_hash = 0;
10725         for (;;) {
10726                 p = path_advance(&mpath, nullstr);
10727                 if (p == NULL)
10728                         break;
10729                 if (*p == '\0')
10730                         continue;
10731                 for (q = p; *q; q++)
10732                         continue;
10733 #if DEBUG
10734                 if (q[-1] != '/')
10735                         abort();
10736 #endif
10737                 q[-1] = '\0';                   /* delete trailing '/' */
10738                 if (stat(p, &statb) < 0) {
10739                         continue;
10740                 }
10741                 /* Very simplistic "hash": just a sum of all mtimes */
10742                 new_hash += (unsigned)statb.st_mtime;
10743         }
10744         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10745                 if (mailtime_hash != 0)
10746                         out2str("you have mail\n");
10747                 mailtime_hash = new_hash;
10748         }
10749         mail_var_path_changed = 0;
10750         popstackmark(&smark);
10751 }
10752
10753 static void FAST_FUNC
10754 changemail(const char *val UNUSED_PARAM)
10755 {
10756         mail_var_path_changed = 1;
10757 }
10758
10759 #endif /* ASH_MAIL */
10760
10761
10762 /* ============ ??? */
10763
10764 /*
10765  * Set the shell parameters.
10766  */
10767 static void
10768 setparam(char **argv)
10769 {
10770         char **newparam;
10771         char **ap;
10772         int nparam;
10773
10774         for (nparam = 0; argv[nparam]; nparam++)
10775                 continue;
10776         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10777         while (*argv) {
10778                 *ap++ = ckstrdup(*argv++);
10779         }
10780         *ap = NULL;
10781         freeparam(&shellparam);
10782         shellparam.malloced = 1;
10783         shellparam.nparam = nparam;
10784         shellparam.p = newparam;
10785 #if ENABLE_ASH_GETOPTS
10786         shellparam.optind = 1;
10787         shellparam.optoff = -1;
10788 #endif
10789 }
10790
10791 /*
10792  * Process shell options.  The global variable argptr contains a pointer
10793  * to the argument list; we advance it past the options.
10794  *
10795  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10796  * For a non-interactive shell, an error condition encountered
10797  * by a special built-in ... shall cause the shell to write a diagnostic message
10798  * to standard error and exit as shown in the following table:
10799  * Error                                           Special Built-In
10800  * ...
10801  * Utility syntax error (option or operand error)  Shall exit
10802  * ...
10803  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10804  * we see that bash does not do that (set "finishes" with error code 1 instead,
10805  * and shell continues), and people rely on this behavior!
10806  * Testcase:
10807  * set -o barfoo 2>/dev/null
10808  * echo $?
10809  *
10810  * Oh well. Let's mimic that.
10811  */
10812 static int
10813 plus_minus_o(char *name, int val)
10814 {
10815         int i;
10816
10817         if (name) {
10818                 for (i = 0; i < NOPTS; i++) {
10819                         if (strcmp(name, optnames(i)) == 0) {
10820                                 optlist[i] = val;
10821                                 return 0;
10822                         }
10823                 }
10824                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10825                 return 1;
10826         }
10827         for (i = 0; i < NOPTS; i++) {
10828                 if (val) {
10829                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10830                 } else {
10831                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10832                 }
10833         }
10834         return 0;
10835 }
10836 static void
10837 setoption(int flag, int val)
10838 {
10839         int i;
10840
10841         for (i = 0; i < NOPTS; i++) {
10842                 if (optletters(i) == flag) {
10843                         optlist[i] = val;
10844                         return;
10845                 }
10846         }
10847         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10848         /* NOTREACHED */
10849 }
10850 static int
10851 options(int cmdline, int *login_sh)
10852 {
10853         char *p;
10854         int val;
10855         int c;
10856
10857         if (cmdline)
10858                 minusc = NULL;
10859         while ((p = *argptr) != NULL) {
10860                 c = *p++;
10861                 if (c != '-' && c != '+')
10862                         break;
10863                 argptr++;
10864                 val = 0; /* val = 0 if c == '+' */
10865                 if (c == '-') {
10866                         val = 1;
10867                         if (p[0] == '\0' || LONE_DASH(p)) {
10868                                 if (!cmdline) {
10869                                         /* "-" means turn off -x and -v */
10870                                         if (p[0] == '\0')
10871                                                 xflag = vflag = 0;
10872                                         /* "--" means reset params */
10873                                         else if (*argptr == NULL)
10874                                                 setparam(argptr);
10875                                 }
10876                                 break;    /* "-" or "--" terminates options */
10877                         }
10878                 }
10879                 /* first char was + or - */
10880                 while ((c = *p++) != '\0') {
10881                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10882                         if (c == 'c' && cmdline) {
10883                                 minusc = p;     /* command is after shell args */
10884                         } else if (c == 'o') {
10885                                 if (plus_minus_o(*argptr, val)) {
10886                                         /* it already printed err message */
10887                                         return 1; /* error */
10888                                 }
10889                                 if (*argptr)
10890                                         argptr++;
10891                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10892                                 if (login_sh)
10893                                         *login_sh = 1;
10894                         /* bash does not accept +-login, we also won't */
10895                         } else if (cmdline && val && (c == '-')) { /* long options */
10896                                 if (strcmp(p, "login") == 0) {
10897                                         if (login_sh)
10898                                                 *login_sh = 1;
10899                                 }
10900                                 break;
10901                         } else {
10902                                 setoption(c, val);
10903                         }
10904                 }
10905         }
10906         return 0;
10907 }
10908
10909 /*
10910  * The shift builtin command.
10911  */
10912 static int FAST_FUNC
10913 shiftcmd(int argc UNUSED_PARAM, char **argv)
10914 {
10915         int n;
10916         char **ap1, **ap2;
10917
10918         n = 1;
10919         if (argv[1])
10920                 n = number(argv[1]);
10921         if (n > shellparam.nparam)
10922                 return 1;
10923         INT_OFF;
10924         shellparam.nparam -= n;
10925         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10926                 if (shellparam.malloced)
10927                         free(*ap1);
10928         }
10929         ap2 = shellparam.p;
10930         while ((*ap2++ = *ap1++) != NULL)
10931                 continue;
10932 #if ENABLE_ASH_GETOPTS
10933         shellparam.optind = 1;
10934         shellparam.optoff = -1;
10935 #endif
10936         INT_ON;
10937         return 0;
10938 }
10939
10940 /*
10941  * POSIX requires that 'set' (but not export or readonly) output the
10942  * variables in lexicographic order - by the locale's collating order (sigh).
10943  * Maybe we could keep them in an ordered balanced binary tree
10944  * instead of hashed lists.
10945  * For now just roll 'em through qsort for printing...
10946  */
10947 static int
10948 showvars(const char *sep_prefix, int on, int off)
10949 {
10950         const char *sep;
10951         char **ep, **epend;
10952
10953         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
10954         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10955
10956         sep = *sep_prefix ? " " : sep_prefix;
10957
10958         for (; ep < epend; ep++) {
10959                 const char *p;
10960                 const char *q;
10961
10962                 p = endofname(*ep);
10963 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
10964  * makes "export -p" to have output not suitable for "eval":
10965  * import os
10966  * os.environ["test-test"]="test"
10967  * if os.fork() == 0:
10968  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
10969  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
10970  */
10971                 q = nullstr;
10972                 if (*p == '=')
10973                         q = single_quote(++p);
10974                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10975         }
10976         return 0;
10977 }
10978
10979 /*
10980  * The set command builtin.
10981  */
10982 static int FAST_FUNC
10983 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10984 {
10985         int retval;
10986
10987         if (!argv[1])
10988                 return showvars(nullstr, 0, VUNSET);
10989
10990         INT_OFF;
10991         retval = options(/*cmdline:*/ 0, NULL);
10992         if (retval == 0) { /* if no parse error... */
10993                 optschanged();
10994                 if (*argptr != NULL) {
10995                         setparam(argptr);
10996                 }
10997         }
10998         INT_ON;
10999         return retval;
11000 }
11001
11002 #if ENABLE_ASH_RANDOM_SUPPORT
11003 static void FAST_FUNC
11004 change_random(const char *value)
11005 {
11006         uint32_t t;
11007
11008         if (value == NULL) {
11009                 /* "get", generate */
11010                 t = next_random(&random_gen);
11011                 /* set without recursion */
11012                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11013                 vrandom.flags &= ~VNOFUNC;
11014         } else {
11015                 /* set/reset */
11016                 t = strtoul(value, NULL, 10);
11017                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11018         }
11019 }
11020 #endif
11021
11022 #if ENABLE_ASH_GETOPTS
11023 static int
11024 getopts(char *optstr, char *optvar, char **optfirst)
11025 {
11026         char *p, *q;
11027         char c = '?';
11028         int done = 0;
11029         char sbuf[2];
11030         char **optnext;
11031         int ind = shellparam.optind;
11032         int off = shellparam.optoff;
11033
11034         sbuf[1] = '\0';
11035
11036         shellparam.optind = -1;
11037         optnext = optfirst + ind - 1;
11038
11039         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11040                 p = NULL;
11041         else
11042                 p = optnext[-1] + off;
11043         if (p == NULL || *p == '\0') {
11044                 /* Current word is done, advance */
11045                 p = *optnext;
11046                 if (p == NULL || *p != '-' || *++p == '\0') {
11047  atend:
11048                         unsetvar("OPTARG");
11049                         p = NULL;
11050                         done = 1;
11051                         goto out;
11052                 }
11053                 optnext++;
11054                 if (LONE_DASH(p))        /* check for "--" */
11055                         goto atend;
11056         }
11057
11058         c = *p++;
11059         for (q = optstr; *q != c;) {
11060                 if (*q == '\0') {
11061                         /* OPTERR is a bashism */
11062                         const char *cp = lookupvar("OPTERR");
11063                         if ((cp && LONE_CHAR(cp, '0'))
11064                          || (optstr[0] == ':')
11065                         ) {
11066                                 sbuf[0] = c;
11067                                 /*sbuf[1] = '\0'; - already is */
11068                                 setvar0("OPTARG", sbuf);
11069                         } else {
11070                                 fprintf(stderr, "Illegal option -%c\n", c);
11071                                 unsetvar("OPTARG");
11072                         }
11073                         c = '?';
11074                         goto out;
11075                 }
11076                 if (*++q == ':')
11077                         q++;
11078         }
11079
11080         if (*++q == ':') {
11081                 if (*p == '\0' && (p = *optnext) == NULL) {
11082                         /* OPTERR is a bashism */
11083                         const char *cp = lookupvar("OPTERR");
11084                         if ((cp && LONE_CHAR(cp, '0'))
11085                          || (optstr[0] == ':')
11086                         ) {
11087                                 sbuf[0] = c;
11088                                 /*sbuf[1] = '\0'; - already is */
11089                                 setvar0("OPTARG", sbuf);
11090                                 c = ':';
11091                         } else {
11092                                 fprintf(stderr, "No arg for -%c option\n", c);
11093                                 unsetvar("OPTARG");
11094                                 c = '?';
11095                         }
11096                         goto out;
11097                 }
11098
11099                 if (p == *optnext)
11100                         optnext++;
11101                 setvar0("OPTARG", p);
11102                 p = NULL;
11103         } else
11104                 setvar0("OPTARG", nullstr);
11105  out:
11106         ind = optnext - optfirst + 1;
11107         setvar("OPTIND", itoa(ind), VNOFUNC);
11108         sbuf[0] = c;
11109         /*sbuf[1] = '\0'; - already is */
11110         setvar0(optvar, sbuf);
11111
11112         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11113         shellparam.optind = ind;
11114
11115         return done;
11116 }
11117
11118 /*
11119  * The getopts builtin.  Shellparam.optnext points to the next argument
11120  * to be processed.  Shellparam.optptr points to the next character to
11121  * be processed in the current argument.  If shellparam.optnext is NULL,
11122  * then it's the first time getopts has been called.
11123  */
11124 static int FAST_FUNC
11125 getoptscmd(int argc, char **argv)
11126 {
11127         char **optbase;
11128
11129         if (argc < 3)
11130                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11131         if (argc == 3) {
11132                 optbase = shellparam.p;
11133                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11134                         shellparam.optind = 1;
11135                         shellparam.optoff = -1;
11136                 }
11137         } else {
11138                 optbase = &argv[3];
11139                 if ((unsigned)shellparam.optind > argc - 2) {
11140                         shellparam.optind = 1;
11141                         shellparam.optoff = -1;
11142                 }
11143         }
11144
11145         return getopts(argv[1], argv[2], optbase);
11146 }
11147 #endif /* ASH_GETOPTS */
11148
11149
11150 /* ============ Shell parser */
11151
11152 struct heredoc {
11153         struct heredoc *next;   /* next here document in list */
11154         union node *here;       /* redirection node */
11155         char *eofmark;          /* string indicating end of input */
11156         smallint striptabs;     /* if set, strip leading tabs */
11157 };
11158
11159 static smallint tokpushback;           /* last token pushed back */
11160 static smallint quoteflag;             /* set if (part of) last token was quoted */
11161 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11162 static struct heredoc *heredoclist;    /* list of here documents to read */
11163 static char *wordtext;                 /* text of last word returned by readtoken */
11164 static struct nodelist *backquotelist;
11165 static union node *redirnode;
11166 static struct heredoc *heredoc;
11167
11168 static const char *
11169 tokname(char *buf, int tok)
11170 {
11171         if (tok < TSEMI)
11172                 return tokname_array[tok];
11173         sprintf(buf, "\"%s\"", tokname_array[tok]);
11174         return buf;
11175 }
11176
11177 /* raise_error_unexpected_syntax:
11178  * Called when an unexpected token is read during the parse.  The argument
11179  * is the token that is expected, or -1 if more than one type of token can
11180  * occur at this point.
11181  */
11182 static void raise_error_unexpected_syntax(int) NORETURN;
11183 static void
11184 raise_error_unexpected_syntax(int token)
11185 {
11186         char msg[64];
11187         char buf[16];
11188         int l;
11189
11190         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11191         if (token >= 0)
11192                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11193         raise_error_syntax(msg);
11194         /* NOTREACHED */
11195 }
11196
11197 /* parsing is heavily cross-recursive, need these forward decls */
11198 static union node *andor(void);
11199 static union node *pipeline(void);
11200 static union node *parse_command(void);
11201 static void parseheredoc(void);
11202 static int peektoken(void);
11203 static int readtoken(void);
11204
11205 static union node *
11206 list(int nlflag)
11207 {
11208         union node *n1, *n2, *n3;
11209         int tok;
11210
11211         n1 = NULL;
11212         for (;;) {
11213                 switch (peektoken()) {
11214                 case TNL:
11215                         if (!(nlflag & 1))
11216                                 break;
11217                         parseheredoc();
11218                         return n1;
11219
11220                 case TEOF:
11221                         if (!n1 && (nlflag & 1))
11222                                 n1 = NODE_EOF;
11223                         parseheredoc();
11224                         return n1;
11225                 }
11226
11227                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11228                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11229                         return n1;
11230                 nlflag |= 2;
11231
11232                 n2 = andor();
11233                 tok = readtoken();
11234                 if (tok == TBACKGND) {
11235                         if (n2->type == NPIPE) {
11236                                 n2->npipe.pipe_backgnd = 1;
11237                         } else {
11238                                 if (n2->type != NREDIR) {
11239                                         n3 = stzalloc(sizeof(struct nredir));
11240                                         n3->nredir.n = n2;
11241                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11242                                         n2 = n3;
11243                                 }
11244                                 n2->type = NBACKGND;
11245                         }
11246                 }
11247                 if (n1 == NULL) {
11248                         n1 = n2;
11249                 } else {
11250                         n3 = stzalloc(sizeof(struct nbinary));
11251                         n3->type = NSEMI;
11252                         n3->nbinary.ch1 = n1;
11253                         n3->nbinary.ch2 = n2;
11254                         n1 = n3;
11255                 }
11256                 switch (tok) {
11257                 case TNL:
11258                 case TEOF:
11259                         tokpushback = 1;
11260                         /* fall through */
11261                 case TBACKGND:
11262                 case TSEMI:
11263                         break;
11264                 default:
11265                         if ((nlflag & 1))
11266                                 raise_error_unexpected_syntax(-1);
11267                         tokpushback = 1;
11268                         return n1;
11269                 }
11270         }
11271 }
11272
11273 static union node *
11274 andor(void)
11275 {
11276         union node *n1, *n2, *n3;
11277         int t;
11278
11279         n1 = pipeline();
11280         for (;;) {
11281                 t = readtoken();
11282                 if (t == TAND) {
11283                         t = NAND;
11284                 } else if (t == TOR) {
11285                         t = NOR;
11286                 } else {
11287                         tokpushback = 1;
11288                         return n1;
11289                 }
11290                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11291                 n2 = pipeline();
11292                 n3 = stzalloc(sizeof(struct nbinary));
11293                 n3->type = t;
11294                 n3->nbinary.ch1 = n1;
11295                 n3->nbinary.ch2 = n2;
11296                 n1 = n3;
11297         }
11298 }
11299
11300 static union node *
11301 pipeline(void)
11302 {
11303         union node *n1, *n2, *pipenode;
11304         struct nodelist *lp, *prev;
11305         int negate;
11306
11307         negate = 0;
11308         TRACE(("pipeline: entered\n"));
11309         if (readtoken() == TNOT) {
11310                 negate = !negate;
11311                 checkkwd = CHKKWD | CHKALIAS;
11312         } else
11313                 tokpushback = 1;
11314         n1 = parse_command();
11315         if (readtoken() == TPIPE) {
11316                 pipenode = stzalloc(sizeof(struct npipe));
11317                 pipenode->type = NPIPE;
11318                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11319                 lp = stzalloc(sizeof(struct nodelist));
11320                 pipenode->npipe.cmdlist = lp;
11321                 lp->n = n1;
11322                 do {
11323                         prev = lp;
11324                         lp = stzalloc(sizeof(struct nodelist));
11325                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11326                         lp->n = parse_command();
11327                         prev->next = lp;
11328                 } while (readtoken() == TPIPE);
11329                 lp->next = NULL;
11330                 n1 = pipenode;
11331         }
11332         tokpushback = 1;
11333         if (negate) {
11334                 n2 = stzalloc(sizeof(struct nnot));
11335                 n2->type = NNOT;
11336                 n2->nnot.com = n1;
11337                 return n2;
11338         }
11339         return n1;
11340 }
11341
11342 static union node *
11343 makename(void)
11344 {
11345         union node *n;
11346
11347         n = stzalloc(sizeof(struct narg));
11348         n->type = NARG;
11349         /*n->narg.next = NULL; - stzalloc did it */
11350         n->narg.text = wordtext;
11351         n->narg.backquote = backquotelist;
11352         return n;
11353 }
11354
11355 static void
11356 fixredir(union node *n, const char *text, int err)
11357 {
11358         int fd;
11359
11360         TRACE(("Fix redir %s %d\n", text, err));
11361         if (!err)
11362                 n->ndup.vname = NULL;
11363
11364         fd = bb_strtou(text, NULL, 10);
11365         if (!errno && fd >= 0)
11366                 n->ndup.dupfd = fd;
11367         else if (LONE_DASH(text))
11368                 n->ndup.dupfd = -1;
11369         else {
11370                 if (err)
11371                         raise_error_syntax("bad fd number");
11372                 n->ndup.vname = makename();
11373         }
11374 }
11375
11376 static void
11377 parsefname(void)
11378 {
11379         union node *n = redirnode;
11380
11381         if (n->type == NHERE)
11382                 checkkwd = CHKEOFMARK;
11383         if (readtoken() != TWORD)
11384                 raise_error_unexpected_syntax(-1);
11385         if (n->type == NHERE) {
11386                 struct heredoc *here = heredoc;
11387                 struct heredoc *p;
11388
11389                 if (quoteflag == 0)
11390                         n->type = NXHERE;
11391                 TRACE(("Here document %d\n", n->type));
11392                 rmescapes(wordtext, 0, NULL);
11393                 here->eofmark = wordtext;
11394                 here->next = NULL;
11395                 if (heredoclist == NULL)
11396                         heredoclist = here;
11397                 else {
11398                         for (p = heredoclist; p->next; p = p->next)
11399                                 continue;
11400                         p->next = here;
11401                 }
11402         } else if (n->type == NTOFD || n->type == NFROMFD) {
11403                 fixredir(n, wordtext, 0);
11404         } else {
11405                 n->nfile.fname = makename();
11406         }
11407 }
11408
11409 static union node *
11410 simplecmd(void)
11411 {
11412         union node *args, **app;
11413         union node *n = NULL;
11414         union node *vars, **vpp;
11415         union node **rpp, *redir;
11416         int savecheckkwd;
11417 #if BASH_TEST2
11418         smallint double_brackets_flag = 0;
11419 #endif
11420         IF_BASH_FUNCTION(smallint function_flag = 0;)
11421
11422         args = NULL;
11423         app = &args;
11424         vars = NULL;
11425         vpp = &vars;
11426         redir = NULL;
11427         rpp = &redir;
11428
11429         savecheckkwd = CHKALIAS;
11430         for (;;) {
11431                 int t;
11432                 checkkwd = savecheckkwd;
11433                 t = readtoken();
11434                 switch (t) {
11435 #if BASH_FUNCTION
11436                 case TFUNCTION:
11437                         if (peektoken() != TWORD)
11438                                 raise_error_unexpected_syntax(TWORD);
11439                         function_flag = 1;
11440                         break;
11441 #endif
11442 #if BASH_TEST2
11443                 case TAND: /* "&&" */
11444                 case TOR: /* "||" */
11445                         if (!double_brackets_flag) {
11446                                 tokpushback = 1;
11447                                 goto out;
11448                         }
11449                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11450 #endif
11451                 case TWORD:
11452                         n = stzalloc(sizeof(struct narg));
11453                         n->type = NARG;
11454                         /*n->narg.next = NULL; - stzalloc did it */
11455                         n->narg.text = wordtext;
11456 #if BASH_TEST2
11457                         if (strcmp("[[", wordtext) == 0)
11458                                 double_brackets_flag = 1;
11459                         else if (strcmp("]]", wordtext) == 0)
11460                                 double_brackets_flag = 0;
11461 #endif
11462                         n->narg.backquote = backquotelist;
11463                         if (savecheckkwd && isassignment(wordtext)) {
11464                                 *vpp = n;
11465                                 vpp = &n->narg.next;
11466                         } else {
11467                                 *app = n;
11468                                 app = &n->narg.next;
11469                                 savecheckkwd = 0;
11470                         }
11471 #if BASH_FUNCTION
11472                         if (function_flag) {
11473                                 checkkwd = CHKNL | CHKKWD;
11474                                 switch (peektoken()) {
11475                                 case TBEGIN:
11476                                 case TIF:
11477                                 case TCASE:
11478                                 case TUNTIL:
11479                                 case TWHILE:
11480                                 case TFOR:
11481                                         goto do_func;
11482                                 case TLP:
11483                                         function_flag = 0;
11484                                         break;
11485                                 case TWORD:
11486                                         if (strcmp("[[", wordtext) == 0)
11487                                                 goto do_func;
11488                                         /* fall through */
11489                                 default:
11490                                         raise_error_unexpected_syntax(-1);
11491                                 }
11492                         }
11493 #endif
11494                         break;
11495                 case TREDIR:
11496                         *rpp = n = redirnode;
11497                         rpp = &n->nfile.next;
11498                         parsefname();   /* read name of redirection file */
11499                         break;
11500                 case TLP:
11501  IF_BASH_FUNCTION(do_func:)
11502                         if (args && app == &args->narg.next
11503                          && !vars && !redir
11504                         ) {
11505                                 struct builtincmd *bcmd;
11506                                 const char *name;
11507
11508                                 /* We have a function */
11509                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11510                                         raise_error_unexpected_syntax(TRP);
11511                                 name = n->narg.text;
11512                                 if (!goodname(name)
11513                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11514                                 ) {
11515                                         raise_error_syntax("bad function name");
11516                                 }
11517                                 n->type = NDEFUN;
11518                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11519                                 n->narg.next = parse_command();
11520                                 return n;
11521                         }
11522                         IF_BASH_FUNCTION(function_flag = 0;)
11523                         /* fall through */
11524                 default:
11525                         tokpushback = 1;
11526                         goto out;
11527                 }
11528         }
11529  out:
11530         *app = NULL;
11531         *vpp = NULL;
11532         *rpp = NULL;
11533         n = stzalloc(sizeof(struct ncmd));
11534         n->type = NCMD;
11535         n->ncmd.args = args;
11536         n->ncmd.assign = vars;
11537         n->ncmd.redirect = redir;
11538         return n;
11539 }
11540
11541 static union node *
11542 parse_command(void)
11543 {
11544         union node *n1, *n2;
11545         union node *ap, **app;
11546         union node *cp, **cpp;
11547         union node *redir, **rpp;
11548         union node **rpp2;
11549         int t;
11550
11551         redir = NULL;
11552         rpp2 = &redir;
11553
11554         switch (readtoken()) {
11555         default:
11556                 raise_error_unexpected_syntax(-1);
11557                 /* NOTREACHED */
11558         case TIF:
11559                 n1 = stzalloc(sizeof(struct nif));
11560                 n1->type = NIF;
11561                 n1->nif.test = list(0);
11562                 if (readtoken() != TTHEN)
11563                         raise_error_unexpected_syntax(TTHEN);
11564                 n1->nif.ifpart = list(0);
11565                 n2 = n1;
11566                 while (readtoken() == TELIF) {
11567                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11568                         n2 = n2->nif.elsepart;
11569                         n2->type = NIF;
11570                         n2->nif.test = list(0);
11571                         if (readtoken() != TTHEN)
11572                                 raise_error_unexpected_syntax(TTHEN);
11573                         n2->nif.ifpart = list(0);
11574                 }
11575                 if (lasttoken == TELSE)
11576                         n2->nif.elsepart = list(0);
11577                 else {
11578                         n2->nif.elsepart = NULL;
11579                         tokpushback = 1;
11580                 }
11581                 t = TFI;
11582                 break;
11583         case TWHILE:
11584         case TUNTIL: {
11585                 int got;
11586                 n1 = stzalloc(sizeof(struct nbinary));
11587                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11588                 n1->nbinary.ch1 = list(0);
11589                 got = readtoken();
11590                 if (got != TDO) {
11591                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11592                                         got == TWORD ? wordtext : ""));
11593                         raise_error_unexpected_syntax(TDO);
11594                 }
11595                 n1->nbinary.ch2 = list(0);
11596                 t = TDONE;
11597                 break;
11598         }
11599         case TFOR:
11600                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11601                         raise_error_syntax("bad for loop variable");
11602                 n1 = stzalloc(sizeof(struct nfor));
11603                 n1->type = NFOR;
11604                 n1->nfor.var = wordtext;
11605                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11606                 if (readtoken() == TIN) {
11607                         app = &ap;
11608                         while (readtoken() == TWORD) {
11609                                 n2 = stzalloc(sizeof(struct narg));
11610                                 n2->type = NARG;
11611                                 /*n2->narg.next = NULL; - stzalloc did it */
11612                                 n2->narg.text = wordtext;
11613                                 n2->narg.backquote = backquotelist;
11614                                 *app = n2;
11615                                 app = &n2->narg.next;
11616                         }
11617                         *app = NULL;
11618                         n1->nfor.args = ap;
11619                         if (lasttoken != TNL && lasttoken != TSEMI)
11620                                 raise_error_unexpected_syntax(-1);
11621                 } else {
11622                         n2 = stzalloc(sizeof(struct narg));
11623                         n2->type = NARG;
11624                         /*n2->narg.next = NULL; - stzalloc did it */
11625                         n2->narg.text = (char *)dolatstr;
11626                         /*n2->narg.backquote = NULL;*/
11627                         n1->nfor.args = n2;
11628                         /*
11629                          * Newline or semicolon here is optional (but note
11630                          * that the original Bourne shell only allowed NL).
11631                          */
11632                         if (lasttoken != TSEMI)
11633                                 tokpushback = 1;
11634                 }
11635                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11636                 if (readtoken() != TDO)
11637                         raise_error_unexpected_syntax(TDO);
11638                 n1->nfor.body = list(0);
11639                 t = TDONE;
11640                 break;
11641         case TCASE:
11642                 n1 = stzalloc(sizeof(struct ncase));
11643                 n1->type = NCASE;
11644                 if (readtoken() != TWORD)
11645                         raise_error_unexpected_syntax(TWORD);
11646                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11647                 n2->type = NARG;
11648                 /*n2->narg.next = NULL; - stzalloc did it */
11649                 n2->narg.text = wordtext;
11650                 n2->narg.backquote = backquotelist;
11651                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11652                 if (readtoken() != TIN)
11653                         raise_error_unexpected_syntax(TIN);
11654                 cpp = &n1->ncase.cases;
11655  next_case:
11656                 checkkwd = CHKNL | CHKKWD;
11657                 t = readtoken();
11658                 while (t != TESAC) {
11659                         if (lasttoken == TLP)
11660                                 readtoken();
11661                         *cpp = cp = stzalloc(sizeof(struct nclist));
11662                         cp->type = NCLIST;
11663                         app = &cp->nclist.pattern;
11664                         for (;;) {
11665                                 *app = ap = stzalloc(sizeof(struct narg));
11666                                 ap->type = NARG;
11667                                 /*ap->narg.next = NULL; - stzalloc did it */
11668                                 ap->narg.text = wordtext;
11669                                 ap->narg.backquote = backquotelist;
11670                                 if (readtoken() != TPIPE)
11671                                         break;
11672                                 app = &ap->narg.next;
11673                                 readtoken();
11674                         }
11675                         //ap->narg.next = NULL;
11676                         if (lasttoken != TRP)
11677                                 raise_error_unexpected_syntax(TRP);
11678                         cp->nclist.body = list(2);
11679
11680                         cpp = &cp->nclist.next;
11681
11682                         checkkwd = CHKNL | CHKKWD;
11683                         t = readtoken();
11684                         if (t != TESAC) {
11685                                 if (t != TENDCASE)
11686                                         raise_error_unexpected_syntax(TENDCASE);
11687                                 goto next_case;
11688                         }
11689                 }
11690                 *cpp = NULL;
11691                 goto redir;
11692         case TLP:
11693                 n1 = stzalloc(sizeof(struct nredir));
11694                 n1->type = NSUBSHELL;
11695                 n1->nredir.n = list(0);
11696                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11697                 t = TRP;
11698                 break;
11699         case TBEGIN:
11700                 n1 = list(0);
11701                 t = TEND;
11702                 break;
11703         IF_BASH_FUNCTION(case TFUNCTION:)
11704         case TWORD:
11705         case TREDIR:
11706                 tokpushback = 1;
11707                 return simplecmd();
11708         }
11709
11710         if (readtoken() != t)
11711                 raise_error_unexpected_syntax(t);
11712
11713  redir:
11714         /* Now check for redirection which may follow command */
11715         checkkwd = CHKKWD | CHKALIAS;
11716         rpp = rpp2;
11717         while (readtoken() == TREDIR) {
11718                 *rpp = n2 = redirnode;
11719                 rpp = &n2->nfile.next;
11720                 parsefname();
11721         }
11722         tokpushback = 1;
11723         *rpp = NULL;
11724         if (redir) {
11725                 if (n1->type != NSUBSHELL) {
11726                         n2 = stzalloc(sizeof(struct nredir));
11727                         n2->type = NREDIR;
11728                         n2->nredir.n = n1;
11729                         n1 = n2;
11730                 }
11731                 n1->nredir.redirect = redir;
11732         }
11733         return n1;
11734 }
11735
11736 #if BASH_DOLLAR_SQUOTE
11737 static int
11738 decode_dollar_squote(void)
11739 {
11740         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11741         int c, cnt;
11742         char *p;
11743         char buf[4];
11744
11745         c = pgetc();
11746         p = strchr(C_escapes, c);
11747         if (p) {
11748                 buf[0] = c;
11749                 p = buf;
11750                 cnt = 3;
11751                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11752                         do {
11753                                 c = pgetc();
11754                                 *++p = c;
11755                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11756                         pungetc();
11757                 } else if (c == 'x') { /* \xHH */
11758                         do {
11759                                 c = pgetc();
11760                                 *++p = c;
11761                         } while (isxdigit(c) && --cnt);
11762                         pungetc();
11763                         if (cnt == 3) { /* \x but next char is "bad" */
11764                                 c = 'x';
11765                                 goto unrecognized;
11766                         }
11767                 } else { /* simple seq like \\ or \t */
11768                         p++;
11769                 }
11770                 *p = '\0';
11771                 p = buf;
11772                 c = bb_process_escape_sequence((void*)&p);
11773         } else { /* unrecognized "\z": print both chars unless ' or " */
11774                 if (c != '\'' && c != '"') {
11775  unrecognized:
11776                         c |= 0x100; /* "please encode \, then me" */
11777                 }
11778         }
11779         return c;
11780 }
11781 #endif
11782
11783 /* Used by expandstr to get here-doc like behaviour. */
11784 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11785
11786 static ALWAYS_INLINE int
11787 realeofmark(const char *eofmark)
11788 {
11789         return eofmark && eofmark != FAKEEOFMARK;
11790 }
11791
11792 /*
11793  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11794  * is not NULL, read a here document.  In the latter case, eofmark is the
11795  * word which marks the end of the document and striptabs is true if
11796  * leading tabs should be stripped from the document.  The argument c
11797  * is the first character of the input token or document.
11798  *
11799  * Because C does not have internal subroutines, I have simulated them
11800  * using goto's to implement the subroutine linkage.  The following macros
11801  * will run code that appears at the end of readtoken1.
11802  */
11803 #define CHECKEND()      {goto checkend; checkend_return:;}
11804 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11805 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11806 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11807 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11808 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11809 static int
11810 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11811 {
11812         /* NB: syntax parameter fits into smallint */
11813         /* c parameter is an unsigned char or PEOF or PEOA */
11814         char *out;
11815         size_t len;
11816         struct nodelist *bqlist;
11817         smallint quotef;
11818         smallint dblquote;
11819         smallint oldstyle;
11820         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11821         smallint pssyntax;   /* we are expanding a prompt string */
11822         int varnest;         /* levels of variables expansion */
11823         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11824         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11825         int dqvarnest;       /* levels of variables expansion within double quotes */
11826
11827         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11828
11829         startlinno = g_parsefile->linno;
11830         bqlist = NULL;
11831         quotef = 0;
11832         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11833 #if ENABLE_ASH_EXPAND_PRMT
11834         pssyntax = (syntax == PSSYNTAX);
11835         if (pssyntax)
11836                 syntax = DQSYNTAX;
11837 #else
11838         pssyntax = 0; /* constant */
11839 #endif
11840         dblquote = (syntax == DQSYNTAX);
11841         varnest = 0;
11842         IF_FEATURE_SH_MATH(arinest = 0;)
11843         IF_FEATURE_SH_MATH(parenlevel = 0;)
11844         dqvarnest = 0;
11845
11846         STARTSTACKSTR(out);
11847  loop:
11848         /* For each line, until end of word */
11849         CHECKEND();     /* set c to PEOF if at end of here document */
11850         for (;;) {      /* until end of line or end of word */
11851                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11852                 switch (SIT(c, syntax)) {
11853                 case CNL:       /* '\n' */
11854                         if (syntax == BASESYNTAX)
11855                                 goto endword;   /* exit outer loop */
11856                         USTPUTC(c, out);
11857                         nlprompt();
11858                         c = pgetc();
11859                         goto loop;              /* continue outer loop */
11860                 case CWORD:
11861                         USTPUTC(c, out);
11862                         break;
11863                 case CCTL:
11864 #if BASH_DOLLAR_SQUOTE
11865                         if (c == '\\' && bash_dollar_squote) {
11866                                 c = decode_dollar_squote();
11867                                 if (c == '\0') {
11868                                         /* skip $'\000', $'\x00' (like bash) */
11869                                         break;
11870                                 }
11871                                 if (c & 0x100) {
11872                                         /* Unknown escape. Encode as '\z' */
11873                                         c = (unsigned char)c;
11874                                         if (eofmark == NULL || dblquote)
11875                                                 USTPUTC(CTLESC, out);
11876                                         USTPUTC('\\', out);
11877                                 }
11878                         }
11879 #endif
11880                         if (eofmark == NULL || dblquote)
11881                                 USTPUTC(CTLESC, out);
11882                         USTPUTC(c, out);
11883                         break;
11884                 case CBACK:     /* backslash */
11885                         c = pgetc_without_PEOA();
11886                         if (c == PEOF) {
11887                                 USTPUTC(CTLESC, out);
11888                                 USTPUTC('\\', out);
11889                                 pungetc();
11890                         } else if (c == '\n') {
11891                                 nlprompt();
11892                         } else {
11893                                 if (pssyntax && c == '$') {
11894                                         USTPUTC(CTLESC, out);
11895                                         USTPUTC('\\', out);
11896                                 }
11897                                 /* Backslash is retained if we are in "str" and next char isn't special */
11898                                 if (dblquote
11899                                  && c != '\\'
11900                                  && c != '`'
11901                                  && c != '$'
11902                                  && (c != '"' || eofmark != NULL)
11903                                 ) {
11904                                         USTPUTC('\\', out);
11905                                 }
11906                                 USTPUTC(CTLESC, out);
11907                                 USTPUTC(c, out);
11908                                 quotef = 1;
11909                         }
11910                         break;
11911                 case CSQUOTE:
11912                         syntax = SQSYNTAX;
11913  quotemark:
11914                         if (eofmark == NULL) {
11915                                 USTPUTC(CTLQUOTEMARK, out);
11916                         }
11917                         break;
11918                 case CDQUOTE:
11919                         syntax = DQSYNTAX;
11920                         dblquote = 1;
11921                         goto quotemark;
11922                 case CENDQUOTE:
11923                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11924                         if (eofmark != NULL && varnest == 0) {
11925                                 USTPUTC(c, out);
11926                         } else {
11927                                 if (dqvarnest == 0) {
11928                                         syntax = BASESYNTAX;
11929                                         dblquote = 0;
11930                                 }
11931                                 quotef = 1;
11932                                 goto quotemark;
11933                         }
11934                         break;
11935                 case CVAR:      /* '$' */
11936                         PARSESUB();             /* parse substitution */
11937                         break;
11938                 case CENDVAR:   /* '}' */
11939                         if (varnest > 0) {
11940                                 varnest--;
11941                                 if (dqvarnest > 0) {
11942                                         dqvarnest--;
11943                                 }
11944                                 c = CTLENDVAR;
11945                         }
11946                         USTPUTC(c, out);
11947                         break;
11948 #if ENABLE_FEATURE_SH_MATH
11949                 case CLP:       /* '(' in arithmetic */
11950                         parenlevel++;
11951                         USTPUTC(c, out);
11952                         break;
11953                 case CRP:       /* ')' in arithmetic */
11954                         if (parenlevel > 0) {
11955                                 parenlevel--;
11956                         } else {
11957                                 if (pgetc_eatbnl() == ')') {
11958                                         c = CTLENDARI;
11959                                         if (--arinest == 0) {
11960                                                 syntax = prevsyntax;
11961                                         }
11962                                 } else {
11963                                         /*
11964                                          * unbalanced parens
11965                                          * (don't 2nd guess - no error)
11966                                          */
11967                                         pungetc();
11968                                 }
11969                         }
11970                         USTPUTC(c, out);
11971                         break;
11972 #endif
11973                 case CBQUOTE:   /* '`' */
11974                         PARSEBACKQOLD();
11975                         break;
11976                 case CENDFILE:
11977                         goto endword;           /* exit outer loop */
11978                 case CIGN:
11979                         break;
11980                 default:
11981                         if (varnest == 0) {
11982 #if BASH_REDIR_OUTPUT
11983                                 if (c == '&') {
11984 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11985                                         if (pgetc() == '>')
11986                                                 c = 0x100 + '>'; /* flag &> */
11987                                         pungetc();
11988                                 }
11989 #endif
11990                                 goto endword;   /* exit outer loop */
11991                         }
11992                         IF_ASH_ALIAS(if (c != PEOA))
11993                                 USTPUTC(c, out);
11994                 }
11995                 c = pgetc();
11996         } /* for (;;) */
11997  endword:
11998
11999 #if ENABLE_FEATURE_SH_MATH
12000         if (syntax == ARISYNTAX)
12001                 raise_error_syntax("missing '))'");
12002 #endif
12003         if (syntax != BASESYNTAX && eofmark == NULL)
12004                 raise_error_syntax("unterminated quoted string");
12005         if (varnest != 0) {
12006                 startlinno = g_parsefile->linno;
12007                 /* { */
12008                 raise_error_syntax("missing '}'");
12009         }
12010         USTPUTC('\0', out);
12011         len = out - (char *)stackblock();
12012         out = stackblock();
12013         if (eofmark == NULL) {
12014                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12015                  && quotef == 0
12016                 ) {
12017                         if (isdigit_str9(out)) {
12018                                 PARSEREDIR(); /* passed as params: out, c */
12019                                 lasttoken = TREDIR;
12020                                 return lasttoken;
12021                         }
12022                         /* else: non-number X seen, interpret it
12023                          * as "NNNX>file" = "NNNX >file" */
12024                 }
12025                 pungetc();
12026         }
12027         quoteflag = quotef;
12028         backquotelist = bqlist;
12029         grabstackblock(len);
12030         wordtext = out;
12031         lasttoken = TWORD;
12032         return lasttoken;
12033 /* end of readtoken routine */
12034
12035 /*
12036  * Check to see whether we are at the end of the here document.  When this
12037  * is called, c is set to the first character of the next input line.  If
12038  * we are at the end of the here document, this routine sets the c to PEOF.
12039  */
12040 checkend: {
12041         if (realeofmark(eofmark)) {
12042                 int markloc;
12043                 char *p;
12044
12045 #if ENABLE_ASH_ALIAS
12046                 if (c == PEOA)
12047                         c = pgetc_without_PEOA();
12048 #endif
12049                 if (striptabs) {
12050                         while (c == '\t') {
12051                                 c = pgetc_without_PEOA();
12052                         }
12053                 }
12054
12055                 markloc = out - (char *)stackblock();
12056                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12057                         if (c != *p)
12058                                 goto more_heredoc;
12059
12060                         c = pgetc_without_PEOA();
12061                 }
12062
12063                 if (c == '\n' || c == PEOF) {
12064                         c = PEOF;
12065                         g_parsefile->linno++;
12066                         needprompt = doprompt;
12067                 } else {
12068                         int len_here;
12069
12070  more_heredoc:
12071                         p = (char *)stackblock() + markloc + 1;
12072                         len_here = out - p;
12073
12074                         if (len_here) {
12075                                 len_here -= (c >= PEOF);
12076                                 c = p[-1];
12077
12078                                 if (len_here) {
12079                                         char *str;
12080
12081                                         str = alloca(len_here + 1);
12082                                         *(char *)mempcpy(str, p, len_here) = '\0';
12083
12084                                         pushstring(str, NULL);
12085                                 }
12086                         }
12087                 }
12088
12089                 STADJUST((char *)stackblock() + markloc - out, out);
12090         }
12091         goto checkend_return;
12092 }
12093
12094 /*
12095  * Parse a redirection operator.  The variable "out" points to a string
12096  * specifying the fd to be redirected.  The variable "c" contains the
12097  * first character of the redirection operator.
12098  */
12099 parseredir: {
12100         /* out is already checked to be a valid number or "" */
12101         int fd = (*out == '\0' ? -1 : atoi(out));
12102         union node *np;
12103
12104         np = stzalloc(sizeof(struct nfile));
12105         if (c == '>') {
12106                 np->nfile.fd = 1;
12107                 c = pgetc();
12108                 if (c == '>')
12109                         np->type = NAPPEND;
12110                 else if (c == '|')
12111                         np->type = NCLOBBER;
12112                 else if (c == '&')
12113                         np->type = NTOFD;
12114                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12115                 else {
12116                         np->type = NTO;
12117                         pungetc();
12118                 }
12119         }
12120 #if BASH_REDIR_OUTPUT
12121         else if (c == 0x100 + '>') { /* this flags &> redirection */
12122                 np->nfile.fd = 1;
12123                 pgetc(); /* this is '>', no need to check */
12124                 np->type = NTO2;
12125         }
12126 #endif
12127         else { /* c == '<' */
12128                 /*np->nfile.fd = 0; - stzalloc did it */
12129                 c = pgetc();
12130                 switch (c) {
12131                 case '<':
12132                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12133                                 np = stzalloc(sizeof(struct nhere));
12134                                 /*np->nfile.fd = 0; - stzalloc did it */
12135                         }
12136                         np->type = NHERE;
12137                         heredoc = stzalloc(sizeof(struct heredoc));
12138                         heredoc->here = np;
12139                         c = pgetc();
12140                         if (c == '-') {
12141                                 heredoc->striptabs = 1;
12142                         } else {
12143                                 /*heredoc->striptabs = 0; - stzalloc did it */
12144                                 pungetc();
12145                         }
12146                         break;
12147
12148                 case '&':
12149                         np->type = NFROMFD;
12150                         break;
12151
12152                 case '>':
12153                         np->type = NFROMTO;
12154                         break;
12155
12156                 default:
12157                         np->type = NFROM;
12158                         pungetc();
12159                         break;
12160                 }
12161         }
12162         if (fd >= 0)
12163                 np->nfile.fd = fd;
12164         redirnode = np;
12165         goto parseredir_return;
12166 }
12167
12168 /*
12169  * Parse a substitution.  At this point, we have read the dollar sign
12170  * and nothing else.
12171  */
12172
12173 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12174  * (assuming ascii char codes, as the original implementation did) */
12175 #define is_special(c) \
12176         (((unsigned)(c) - 33 < 32) \
12177                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12178 parsesub: {
12179         unsigned char subtype;
12180         int typeloc;
12181
12182         c = pgetc_eatbnl();
12183         if ((checkkwd & CHKEOFMARK)
12184          || c > 255 /* PEOA or PEOF */
12185          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12186         ) {
12187 #if BASH_DOLLAR_SQUOTE
12188                 if (syntax != DQSYNTAX && c == '\'')
12189                         bash_dollar_squote = 1;
12190                 else
12191 #endif
12192                         USTPUTC('$', out);
12193                 pungetc();
12194         } else if (c == '(') {
12195                 /* $(command) or $((arith)) */
12196                 if (pgetc_eatbnl() == '(') {
12197 #if ENABLE_FEATURE_SH_MATH
12198                         PARSEARITH();
12199 #else
12200                         raise_error_syntax("support for $((arith)) is disabled");
12201 #endif
12202                 } else {
12203                         pungetc();
12204                         PARSEBACKQNEW();
12205                 }
12206         } else {
12207                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12208                 USTPUTC(CTLVAR, out);
12209                 typeloc = out - (char *)stackblock();
12210                 STADJUST(1, out);
12211                 subtype = VSNORMAL;
12212                 if (c == '{') {
12213                         c = pgetc_eatbnl();
12214                         subtype = 0;
12215                 }
12216  varname:
12217                 if (is_name(c)) {
12218                         /* $[{[#]]NAME[}] */
12219                         do {
12220                                 STPUTC(c, out);
12221                                 c = pgetc_eatbnl();
12222                         } while (is_in_name(c));
12223                 } else if (isdigit(c)) {
12224                         /* $[{[#]]NUM[}] */
12225                         do {
12226                                 STPUTC(c, out);
12227                                 c = pgetc_eatbnl();
12228                         } while (isdigit(c));
12229                 } else {
12230                         /* $[{[#]]<specialchar>[}] */
12231                         int cc = c;
12232
12233                         c = pgetc_eatbnl();
12234                         if (!subtype && cc == '#') {
12235                                 subtype = VSLENGTH;
12236                                 if (c == '_' || isalnum(c))
12237                                         goto varname;
12238                                 cc = c;
12239                                 c = pgetc_eatbnl();
12240                                 if (cc == '}' || c != '}') {
12241                                         pungetc();
12242                                         subtype = 0;
12243                                         c = cc;
12244                                         cc = '#';
12245                                 }
12246                         }
12247
12248                         if (!is_special(cc)) {
12249                                 if (subtype == VSLENGTH)
12250                                         subtype = 0;
12251                                 goto badsub;
12252                         }
12253
12254                         USTPUTC(cc, out);
12255                 }
12256
12257                 if (c != '}' && subtype == VSLENGTH) {
12258                         /* ${#VAR didn't end with } */
12259                         goto badsub;
12260                 }
12261
12262                 if (subtype == 0) {
12263                         static const char types[] ALIGN1 = "}-+?=";
12264                         /* ${VAR...} but not $VAR or ${#VAR} */
12265                         /* c == first char after VAR */
12266                         switch (c) {
12267                         case ':':
12268                                 c = pgetc_eatbnl();
12269 #if BASH_SUBSTR
12270                                 /* This check is only needed to not misinterpret
12271                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12272                                  * constructs.
12273                                  */
12274                                 if (!strchr(types, c)) {
12275                                         subtype = VSSUBSTR;
12276                                         pungetc();
12277                                         break; /* "goto badsub" is bigger (!) */
12278                                 }
12279 #endif
12280                                 subtype = VSNUL;
12281                                 /*FALLTHROUGH*/
12282                         default: {
12283                                 const char *p = strchr(types, c);
12284                                 if (p == NULL)
12285                                         break;
12286                                 subtype |= p - types + VSNORMAL;
12287                                 break;
12288                         }
12289                         case '%':
12290                         case '#': {
12291                                 int cc = c;
12292                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12293                                 c = pgetc_eatbnl();
12294                                 if (c != cc)
12295                                         goto badsub;
12296                                 subtype++;
12297                                 break;
12298                         }
12299 #if BASH_PATTERN_SUBST
12300                         case '/':
12301                                 /* ${v/[/]pattern/repl} */
12302 //TODO: encode pattern and repl separately.
12303 // Currently ${v/$var_with_slash/repl} is horribly broken
12304                                 subtype = VSREPLACE;
12305                                 c = pgetc_eatbnl();
12306                                 if (c != '/')
12307                                         goto badsub;
12308                                 subtype++; /* VSREPLACEALL */
12309                                 break;
12310 #endif
12311                         }
12312                 } else {
12313  badsub:
12314                         pungetc();
12315                 }
12316                 ((unsigned char *)stackblock())[typeloc] = subtype;
12317                 if (subtype != VSNORMAL) {
12318                         varnest++;
12319                         if (dblquote)
12320                                 dqvarnest++;
12321                 }
12322                 STPUTC('=', out);
12323         }
12324         goto parsesub_return;
12325 }
12326
12327 /*
12328  * Called to parse command substitutions.  Newstyle is set if the command
12329  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12330  * list of commands (passed by reference), and savelen is the number of
12331  * characters on the top of the stack which must be preserved.
12332  */
12333 parsebackq: {
12334         struct nodelist **nlpp;
12335         union node *n;
12336         char *str;
12337         size_t savelen;
12338         smallint saveprompt = 0;
12339
12340         str = NULL;
12341         savelen = out - (char *)stackblock();
12342         if (savelen > 0) {
12343                 /*
12344                  * FIXME: this can allocate very large block on stack and SEGV.
12345                  * Example:
12346                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12347                  * allocates 100kb for every command subst. With about
12348                  * a hundred command substitutions stack overflows.
12349                  * With larger prepended string, SEGV happens sooner.
12350                  */
12351                 str = alloca(savelen);
12352                 memcpy(str, stackblock(), savelen);
12353         }
12354
12355         if (oldstyle) {
12356                 /* We must read until the closing backquote, giving special
12357                  * treatment to some slashes, and then push the string and
12358                  * reread it as input, interpreting it normally.
12359                  */
12360                 char *pout;
12361                 size_t psavelen;
12362                 char *pstr;
12363
12364                 STARTSTACKSTR(pout);
12365                 for (;;) {
12366                         int pc;
12367
12368                         setprompt_if(needprompt, 2);
12369                         pc = pgetc();
12370                         switch (pc) {
12371                         case '`':
12372                                 goto done;
12373
12374                         case '\\':
12375                                 pc = pgetc();
12376                                 if (pc == '\n') {
12377                                         nlprompt();
12378                                         /*
12379                                          * If eating a newline, avoid putting
12380                                          * the newline into the new character
12381                                          * stream (via the STPUTC after the
12382                                          * switch).
12383                                          */
12384                                         continue;
12385                                 }
12386                                 if (pc != '\\' && pc != '`' && pc != '$'
12387                                  && (!dblquote || pc != '"')
12388                                 ) {
12389                                         STPUTC('\\', pout);
12390                                 }
12391                                 if (pc <= 255 /* not PEOA or PEOF */) {
12392                                         break;
12393                                 }
12394                                 /* fall through */
12395
12396                         case PEOF:
12397                         IF_ASH_ALIAS(case PEOA:)
12398                                 startlinno = g_parsefile->linno;
12399                                 raise_error_syntax("EOF in backquote substitution");
12400
12401                         case '\n':
12402                                 nlnoprompt();
12403                                 break;
12404
12405                         default:
12406                                 break;
12407                         }
12408                         STPUTC(pc, pout);
12409                 }
12410  done:
12411                 STPUTC('\0', pout);
12412                 psavelen = pout - (char *)stackblock();
12413                 if (psavelen > 0) {
12414                         pstr = grabstackstr(pout);
12415                         setinputstring(pstr);
12416                 }
12417         }
12418         nlpp = &bqlist;
12419         while (*nlpp)
12420                 nlpp = &(*nlpp)->next;
12421         *nlpp = stzalloc(sizeof(**nlpp));
12422         /* (*nlpp)->next = NULL; - stzalloc did it */
12423
12424         if (oldstyle) {
12425                 saveprompt = doprompt;
12426                 doprompt = 0;
12427         }
12428
12429         n = list(2);
12430
12431         if (oldstyle)
12432                 doprompt = saveprompt;
12433         else if (readtoken() != TRP)
12434                 raise_error_unexpected_syntax(TRP);
12435
12436         (*nlpp)->n = n;
12437         if (oldstyle) {
12438                 /*
12439                  * Start reading from old file again, ignoring any pushed back
12440                  * tokens left from the backquote parsing
12441                  */
12442                 popfile();
12443                 tokpushback = 0;
12444         }
12445         while (stackblocksize() <= savelen)
12446                 growstackblock();
12447         STARTSTACKSTR(out);
12448         if (str) {
12449                 memcpy(out, str, savelen);
12450                 STADJUST(savelen, out);
12451         }
12452         USTPUTC(CTLBACKQ, out);
12453         if (oldstyle)
12454                 goto parsebackq_oldreturn;
12455         goto parsebackq_newreturn;
12456 }
12457
12458 #if ENABLE_FEATURE_SH_MATH
12459 /*
12460  * Parse an arithmetic expansion (indicate start of one and set state)
12461  */
12462 parsearith: {
12463         if (++arinest == 1) {
12464                 prevsyntax = syntax;
12465                 syntax = ARISYNTAX;
12466         }
12467         USTPUTC(CTLARI, out);
12468         goto parsearith_return;
12469 }
12470 #endif
12471 } /* end of readtoken */
12472
12473 /*
12474  * Read the next input token.
12475  * If the token is a word, we set backquotelist to the list of cmds in
12476  *      backquotes.  We set quoteflag to true if any part of the word was
12477  *      quoted.
12478  * If the token is TREDIR, then we set redirnode to a structure containing
12479  *      the redirection.
12480  * In all cases, the variable startlinno is set to the number of the line
12481  *      on which the token starts.
12482  *
12483  * [Change comment:  here documents and internal procedures]
12484  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12485  *  word parsing code into a separate routine.  In this case, readtoken
12486  *  doesn't need to have any internal procedures, but parseword does.
12487  *  We could also make parseoperator in essence the main routine, and
12488  *  have parseword (readtoken1?) handle both words and redirection.]
12489  */
12490 #define NEW_xxreadtoken
12491 #ifdef NEW_xxreadtoken
12492 /* singles must be first! */
12493 static const char xxreadtoken_chars[7] ALIGN1 = {
12494         '\n', '(', ')', /* singles */
12495         '&', '|', ';',  /* doubles */
12496         0
12497 };
12498
12499 #define xxreadtoken_singles 3
12500 #define xxreadtoken_doubles 3
12501
12502 static const char xxreadtoken_tokens[] ALIGN1 = {
12503         TNL, TLP, TRP,          /* only single occurrence allowed */
12504         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12505         TEOF,                   /* corresponds to trailing nul */
12506         TAND, TOR, TENDCASE     /* if double occurrence */
12507 };
12508
12509 static int
12510 xxreadtoken(void)
12511 {
12512         int c;
12513
12514         if (tokpushback) {
12515                 tokpushback = 0;
12516                 return lasttoken;
12517         }
12518         setprompt_if(needprompt, 2);
12519         startlinno = g_parsefile->linno;
12520         for (;;) {                      /* until token or start of word found */
12521                 c = pgetc();
12522                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12523                         continue;
12524
12525                 if (c == '#') {
12526                         while ((c = pgetc()) != '\n' && c != PEOF)
12527                                 continue;
12528                         pungetc();
12529                 } else if (c == '\\') {
12530                         if (pgetc() != '\n') {
12531                                 pungetc();
12532                                 break; /* return readtoken1(...) */
12533                         }
12534                         nlprompt();
12535                 } else {
12536                         const char *p;
12537
12538                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12539                         if (c != PEOF) {
12540                                 if (c == '\n') {
12541                                         nlnoprompt();
12542                                 }
12543
12544                                 p = strchr(xxreadtoken_chars, c);
12545                                 if (p == NULL)
12546                                         break; /* return readtoken1(...) */
12547
12548                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12549                                         int cc = pgetc();
12550                                         if (cc == c) {    /* double occurrence? */
12551                                                 p += xxreadtoken_doubles + 1;
12552                                         } else {
12553                                                 pungetc();
12554 #if BASH_REDIR_OUTPUT
12555                                                 if (c == '&' && cc == '>') /* &> */
12556                                                         break; /* return readtoken1(...) */
12557 #endif
12558                                         }
12559                                 }
12560                         }
12561                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12562                         return lasttoken;
12563                 }
12564         } /* for (;;) */
12565
12566         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12567 }
12568 #else /* old xxreadtoken */
12569 #define RETURN(token)   return lasttoken = token
12570 static int
12571 xxreadtoken(void)
12572 {
12573         int c;
12574
12575         if (tokpushback) {
12576                 tokpushback = 0;
12577                 return lasttoken;
12578         }
12579         setprompt_if(needprompt, 2);
12580         startlinno = g_parsefile->linno;
12581         for (;;) {      /* until token or start of word found */
12582                 c = pgetc();
12583                 switch (c) {
12584                 case ' ': case '\t':
12585                 IF_ASH_ALIAS(case PEOA:)
12586                         continue;
12587                 case '#':
12588                         while ((c = pgetc()) != '\n' && c != PEOF)
12589                                 continue;
12590                         pungetc();
12591                         continue;
12592                 case '\\':
12593                         if (pgetc() == '\n') {
12594                                 nlprompt();
12595                                 continue;
12596                         }
12597                         pungetc();
12598                         goto breakloop;
12599                 case '\n':
12600                         nlnoprompt();
12601                         RETURN(TNL);
12602                 case PEOF:
12603                         RETURN(TEOF);
12604                 case '&':
12605                         if (pgetc() == '&')
12606                                 RETURN(TAND);
12607                         pungetc();
12608                         RETURN(TBACKGND);
12609                 case '|':
12610                         if (pgetc() == '|')
12611                                 RETURN(TOR);
12612                         pungetc();
12613                         RETURN(TPIPE);
12614                 case ';':
12615                         if (pgetc() == ';')
12616                                 RETURN(TENDCASE);
12617                         pungetc();
12618                         RETURN(TSEMI);
12619                 case '(':
12620                         RETURN(TLP);
12621                 case ')':
12622                         RETURN(TRP);
12623                 default:
12624                         goto breakloop;
12625                 }
12626         }
12627  breakloop:
12628         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12629 #undef RETURN
12630 }
12631 #endif /* old xxreadtoken */
12632
12633 static int
12634 readtoken(void)
12635 {
12636         int t;
12637         int kwd = checkkwd;
12638 #if DEBUG
12639         smallint alreadyseen = tokpushback;
12640 #endif
12641
12642 #if ENABLE_ASH_ALIAS
12643  top:
12644 #endif
12645
12646         t = xxreadtoken();
12647
12648         /*
12649          * eat newlines
12650          */
12651         if (kwd & CHKNL) {
12652                 while (t == TNL) {
12653                         parseheredoc();
12654                         t = xxreadtoken();
12655                 }
12656         }
12657
12658         if (t != TWORD || quoteflag) {
12659                 goto out;
12660         }
12661
12662         /*
12663          * check for keywords
12664          */
12665         if (kwd & CHKKWD) {
12666                 const char *const *pp;
12667
12668                 pp = findkwd(wordtext);
12669                 if (pp) {
12670                         lasttoken = t = pp - tokname_array;
12671                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12672                         goto out;
12673                 }
12674         }
12675
12676         if (checkkwd & CHKALIAS) {
12677 #if ENABLE_ASH_ALIAS
12678                 struct alias *ap;
12679                 ap = lookupalias(wordtext, 1);
12680                 if (ap != NULL) {
12681                         if (*ap->val) {
12682                                 pushstring(ap->val, ap);
12683                         }
12684                         goto top;
12685                 }
12686 #endif
12687         }
12688  out:
12689         checkkwd = 0;
12690 #if DEBUG
12691         if (!alreadyseen)
12692                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12693         else
12694                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12695 #endif
12696         return t;
12697 }
12698
12699 static int
12700 peektoken(void)
12701 {
12702         int t;
12703
12704         t = readtoken();
12705         tokpushback = 1;
12706         return t;
12707 }
12708
12709 /*
12710  * Read and parse a command.  Returns NODE_EOF on end of file.
12711  * (NULL is a valid parse tree indicating a blank line.)
12712  */
12713 static union node *
12714 parsecmd(int interact)
12715 {
12716         tokpushback = 0;
12717         checkkwd = 0;
12718         heredoclist = 0;
12719         doprompt = interact;
12720         setprompt_if(doprompt, doprompt);
12721         needprompt = 0;
12722         return list(1);
12723 }
12724
12725 /*
12726  * Input any here documents.
12727  */
12728 static void
12729 parseheredoc(void)
12730 {
12731         struct heredoc *here;
12732         union node *n;
12733
12734         here = heredoclist;
12735         heredoclist = NULL;
12736
12737         while (here) {
12738                 setprompt_if(needprompt, 2);
12739                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12740                                 here->eofmark, here->striptabs);
12741                 n = stzalloc(sizeof(struct narg));
12742                 n->narg.type = NARG;
12743                 /*n->narg.next = NULL; - stzalloc did it */
12744                 n->narg.text = wordtext;
12745                 n->narg.backquote = backquotelist;
12746                 here->here->nhere.doc = n;
12747                 here = here->next;
12748         }
12749 }
12750
12751
12752 static const char *
12753 expandstr(const char *ps, int syntax_type)
12754 {
12755         union node n;
12756         int saveprompt;
12757
12758         /* XXX Fix (char *) cast. */
12759         setinputstring((char *)ps);
12760
12761         saveprompt = doprompt;
12762         doprompt = 0;
12763
12764         /* readtoken1() might die horribly.
12765          * Try a prompt with syntactically wrong command:
12766          * PS1='$(date "+%H:%M:%S) > '
12767          */
12768         {
12769                 volatile int saveint;
12770                 struct jmploc *volatile savehandler = exception_handler;
12771                 struct jmploc jmploc;
12772                 SAVE_INT(saveint);
12773                 if (setjmp(jmploc.loc) == 0) {
12774                         exception_handler = &jmploc;
12775                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12776                 }
12777                 exception_handler = savehandler;
12778                 RESTORE_INT(saveint);
12779         }
12780
12781         doprompt = saveprompt;
12782
12783         popfile();
12784
12785         n.narg.type = NARG;
12786         n.narg.next = NULL;
12787         n.narg.text = wordtext;
12788         n.narg.backquote = backquotelist;
12789
12790         expandarg(&n, NULL, EXP_QUOTED);
12791         return stackblock();
12792 }
12793
12794 static inline int
12795 parser_eof(void)
12796 {
12797         return tokpushback && lasttoken == TEOF;
12798 }
12799
12800 /*
12801  * Execute a command or commands contained in a string.
12802  */
12803 static int
12804 evalstring(char *s, int flags)
12805 {
12806         struct jmploc *volatile savehandler;
12807         struct jmploc jmploc;
12808         int ex;
12809
12810         union node *n;
12811         struct stackmark smark;
12812         int status;
12813
12814         s = sstrdup(s);
12815         setinputstring(s);
12816         setstackmark(&smark);
12817
12818         status = 0;
12819         /* On exception inside execution loop, we must popfile().
12820          * Try interactively:
12821          *      readonly a=a
12822          *      command eval "a=b"  # throws "is read only" error
12823          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12824          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12825          */
12826         savehandler = exception_handler;
12827         ex = setjmp(jmploc.loc);
12828         if (ex)
12829                 goto out;
12830         exception_handler = &jmploc;
12831
12832         while ((n = parsecmd(0)) != NODE_EOF) {
12833                 int i;
12834
12835                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12836                 if (n)
12837                         status = i;
12838                 popstackmark(&smark);
12839                 if (evalskip)
12840                         break;
12841         }
12842  out:
12843         popstackmark(&smark);
12844         popfile();
12845         stunalloc(s);
12846
12847         exception_handler = savehandler;
12848         if (ex)
12849                 longjmp(exception_handler->loc, ex);
12850
12851         return status;
12852 }
12853
12854 /*
12855  * The eval command.
12856  */
12857 static int FAST_FUNC
12858 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12859 {
12860         char *p;
12861         char *concat;
12862
12863         if (argv[1]) {
12864                 p = argv[1];
12865                 argv += 2;
12866                 if (argv[0]) {
12867                         STARTSTACKSTR(concat);
12868                         for (;;) {
12869                                 concat = stack_putstr(p, concat);
12870                                 p = *argv++;
12871                                 if (p == NULL)
12872                                         break;
12873                                 STPUTC(' ', concat);
12874                         }
12875                         STPUTC('\0', concat);
12876                         p = grabstackstr(concat);
12877                 }
12878                 return evalstring(p, flags & EV_TESTED);
12879         }
12880         return 0;
12881 }
12882
12883 /*
12884  * Read and execute commands.
12885  * "Top" is nonzero for the top level command loop;
12886  * it turns on prompting if the shell is interactive.
12887  */
12888 static int
12889 cmdloop(int top)
12890 {
12891         union node *n;
12892         struct stackmark smark;
12893         int inter;
12894         int status = 0;
12895         int numeof = 0;
12896
12897         TRACE(("cmdloop(%d) called\n", top));
12898         for (;;) {
12899                 int skip;
12900
12901                 setstackmark(&smark);
12902 #if JOBS
12903                 if (doing_jobctl)
12904                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12905 #endif
12906                 inter = 0;
12907                 if (iflag && top) {
12908                         inter++;
12909                         chkmail();
12910                 }
12911                 n = parsecmd(inter);
12912 #if DEBUG
12913                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12914                         showtree(n);
12915 #endif
12916                 if (n == NODE_EOF) {
12917                         if (!top || numeof >= 50)
12918                                 break;
12919                         if (!stoppedjobs()) {
12920                                 if (!Iflag)
12921                                         break;
12922                                 out2str("\nUse \"exit\" to leave shell.\n");
12923                         }
12924                         numeof++;
12925                 } else if (nflag == 0) {
12926                         int i;
12927
12928                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12929                         job_warning >>= 1;
12930                         numeof = 0;
12931                         i = evaltree(n, 0);
12932                         if (n)
12933                                 status = i;
12934                 }
12935                 popstackmark(&smark);
12936                 skip = evalskip;
12937
12938                 if (skip) {
12939                         evalskip &= ~SKIPFUNC;
12940                         break;
12941                 }
12942         }
12943         return status;
12944 }
12945
12946 /*
12947  * Take commands from a file.  To be compatible we should do a path
12948  * search for the file, which is necessary to find sub-commands.
12949  */
12950 static char *
12951 find_dot_file(char *name)
12952 {
12953         char *fullname;
12954         const char *path = pathval();
12955         struct stat statb;
12956
12957         /* don't try this for absolute or relative paths */
12958         if (strchr(name, '/'))
12959                 return name;
12960
12961         while ((fullname = path_advance(&path, name)) != NULL) {
12962                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12963                         /*
12964                          * Don't bother freeing here, since it will
12965                          * be freed by the caller.
12966                          */
12967                         return fullname;
12968                 }
12969                 if (fullname != name)
12970                         stunalloc(fullname);
12971         }
12972
12973         /* not found in the PATH */
12974         ash_msg_and_raise_error("%s: not found", name);
12975         /* NOTREACHED */
12976 }
12977
12978 static int FAST_FUNC
12979 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12980 {
12981         /* "false; . empty_file; echo $?" should print 0, not 1: */
12982         int status = 0;
12983         char *fullname;
12984         char **argv;
12985         char *args_need_save;
12986         volatile struct shparam saveparam;
12987
12988 //???
12989 //      struct strlist *sp;
12990 //      for (sp = cmdenviron; sp; sp = sp->next)
12991 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12992
12993         nextopt(nullstr); /* handle possible "--" */
12994         argv = argptr;
12995
12996         if (!argv[0]) {
12997                 /* bash says: "bash: .: filename argument required" */
12998                 return 2; /* bash compat */
12999         }
13000
13001         /* This aborts if file isn't found, which is POSIXly correct.
13002          * bash returns exitcode 1 instead.
13003          */
13004         fullname = find_dot_file(argv[0]);
13005         argv++;
13006         args_need_save = argv[0];
13007         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13008                 int argc;
13009                 saveparam = shellparam;
13010                 shellparam.malloced = 0;
13011                 argc = 1;
13012                 while (argv[argc])
13013                         argc++;
13014                 shellparam.nparam = argc;
13015                 shellparam.p = argv;
13016         };
13017
13018         /* This aborts if file can't be opened, which is POSIXly correct.
13019          * bash returns exitcode 1 instead.
13020          */
13021         setinputfile(fullname, INPUT_PUSH_FILE);
13022         commandname = fullname;
13023         status = cmdloop(0);
13024         popfile();
13025
13026         if (args_need_save) {
13027                 freeparam(&shellparam);
13028                 shellparam = saveparam;
13029         };
13030
13031         return status;
13032 }
13033
13034 static int FAST_FUNC
13035 exitcmd(int argc UNUSED_PARAM, char **argv)
13036 {
13037         if (stoppedjobs())
13038                 return 0;
13039         if (argv[1])
13040                 exitstatus = number(argv[1]);
13041         raise_exception(EXEXIT);
13042         /* NOTREACHED */
13043 }
13044
13045 /*
13046  * Read a file containing shell functions.
13047  */
13048 static void
13049 readcmdfile(char *name)
13050 {
13051         setinputfile(name, INPUT_PUSH_FILE);
13052         cmdloop(0);
13053         popfile();
13054 }
13055
13056
13057 /* ============ find_command inplementation */
13058
13059 /*
13060  * Resolve a command name.  If you change this routine, you may have to
13061  * change the shellexec routine as well.
13062  */
13063 static void
13064 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13065 {
13066         struct tblentry *cmdp;
13067         int idx;
13068         int prev;
13069         char *fullname;
13070         struct stat statb;
13071         int e;
13072         int updatetbl;
13073         struct builtincmd *bcmd;
13074
13075         /* If name contains a slash, don't use PATH or hash table */
13076         if (strchr(name, '/') != NULL) {
13077                 entry->u.index = -1;
13078                 if (act & DO_ABS) {
13079                         while (stat(name, &statb) < 0) {
13080 #ifdef SYSV
13081                                 if (errno == EINTR)
13082                                         continue;
13083 #endif
13084                                 entry->cmdtype = CMDUNKNOWN;
13085                                 return;
13086                         }
13087                 }
13088                 entry->cmdtype = CMDNORMAL;
13089                 return;
13090         }
13091
13092 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13093
13094         updatetbl = (path == pathval());
13095         if (!updatetbl) {
13096                 act |= DO_ALTPATH;
13097                 if (strstr(path, "%builtin") != NULL)
13098                         act |= DO_ALTBLTIN;
13099         }
13100
13101         /* If name is in the table, check answer will be ok */
13102         cmdp = cmdlookup(name, 0);
13103         if (cmdp != NULL) {
13104                 int bit;
13105
13106                 switch (cmdp->cmdtype) {
13107                 default:
13108 #if DEBUG
13109                         abort();
13110 #endif
13111                 case CMDNORMAL:
13112                         bit = DO_ALTPATH;
13113                         break;
13114                 case CMDFUNCTION:
13115                         bit = DO_NOFUNC;
13116                         break;
13117                 case CMDBUILTIN:
13118                         bit = DO_ALTBLTIN;
13119                         break;
13120                 }
13121                 if (act & bit) {
13122                         updatetbl = 0;
13123                         cmdp = NULL;
13124                 } else if (cmdp->rehash == 0)
13125                         /* if not invalidated by cd, we're done */
13126                         goto success;
13127         }
13128
13129         /* If %builtin not in path, check for builtin next */
13130         bcmd = find_builtin(name);
13131         if (bcmd) {
13132                 if (IS_BUILTIN_REGULAR(bcmd))
13133                         goto builtin_success;
13134                 if (act & DO_ALTPATH) {
13135                         if (!(act & DO_ALTBLTIN))
13136                                 goto builtin_success;
13137                 } else if (builtinloc <= 0) {
13138                         goto builtin_success;
13139                 }
13140         }
13141
13142 #if ENABLE_FEATURE_SH_STANDALONE
13143         {
13144                 int applet_no = find_applet_by_name(name);
13145                 if (applet_no >= 0) {
13146                         entry->cmdtype = CMDNORMAL;
13147                         entry->u.index = -2 - applet_no;
13148                         return;
13149                 }
13150         }
13151 #endif
13152
13153         /* We have to search path. */
13154         prev = -1;              /* where to start */
13155         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13156                 if (cmdp->cmdtype == CMDBUILTIN)
13157                         prev = builtinloc;
13158                 else
13159                         prev = cmdp->param.index;
13160         }
13161
13162         e = ENOENT;
13163         idx = -1;
13164  loop:
13165         while ((fullname = path_advance(&path, name)) != NULL) {
13166                 stunalloc(fullname);
13167                 /* NB: code below will still use fullname
13168                  * despite it being "unallocated" */
13169                 idx++;
13170                 if (pathopt) {
13171                         if (prefix(pathopt, "builtin")) {
13172                                 if (bcmd)
13173                                         goto builtin_success;
13174                                 continue;
13175                         }
13176                         if ((act & DO_NOFUNC)
13177                          || !prefix(pathopt, "func")
13178                         ) {     /* ignore unimplemented options */
13179                                 continue;
13180                         }
13181                 }
13182                 /* if rehash, don't redo absolute path names */
13183                 if (fullname[0] == '/' && idx <= prev) {
13184                         if (idx < prev)
13185                                 continue;
13186                         TRACE(("searchexec \"%s\": no change\n", name));
13187                         goto success;
13188                 }
13189                 while (stat(fullname, &statb) < 0) {
13190 #ifdef SYSV
13191                         if (errno == EINTR)
13192                                 continue;
13193 #endif
13194                         if (errno != ENOENT && errno != ENOTDIR)
13195                                 e = errno;
13196                         goto loop;
13197                 }
13198                 e = EACCES;     /* if we fail, this will be the error */
13199                 if (!S_ISREG(statb.st_mode))
13200                         continue;
13201                 if (pathopt) {          /* this is a %func directory */
13202                         stalloc(strlen(fullname) + 1);
13203                         /* NB: stalloc will return space pointed by fullname
13204                          * (because we don't have any intervening allocations
13205                          * between stunalloc above and this stalloc) */
13206                         readcmdfile(fullname);
13207                         cmdp = cmdlookup(name, 0);
13208                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13209                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13210                         stunalloc(fullname);
13211                         goto success;
13212                 }
13213                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13214                 if (!updatetbl) {
13215                         entry->cmdtype = CMDNORMAL;
13216                         entry->u.index = idx;
13217                         return;
13218                 }
13219                 INT_OFF;
13220                 cmdp = cmdlookup(name, 1);
13221                 cmdp->cmdtype = CMDNORMAL;
13222                 cmdp->param.index = idx;
13223                 INT_ON;
13224                 goto success;
13225         }
13226
13227         /* We failed.  If there was an entry for this command, delete it */
13228         if (cmdp && updatetbl)
13229                 delete_cmd_entry();
13230         if (act & DO_ERR)
13231                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13232         entry->cmdtype = CMDUNKNOWN;
13233         return;
13234
13235  builtin_success:
13236         if (!updatetbl) {
13237                 entry->cmdtype = CMDBUILTIN;
13238                 entry->u.cmd = bcmd;
13239                 return;
13240         }
13241         INT_OFF;
13242         cmdp = cmdlookup(name, 1);
13243         cmdp->cmdtype = CMDBUILTIN;
13244         cmdp->param.cmd = bcmd;
13245         INT_ON;
13246  success:
13247         cmdp->rehash = 0;
13248         entry->cmdtype = cmdp->cmdtype;
13249         entry->u = cmdp->param;
13250 }
13251
13252
13253 /*
13254  * The trap builtin.
13255  */
13256 static int FAST_FUNC
13257 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13258 {
13259         char *action;
13260         char **ap;
13261         int signo, exitcode;
13262
13263         nextopt(nullstr);
13264         ap = argptr;
13265         if (!*ap) {
13266                 for (signo = 0; signo < NSIG; signo++) {
13267                         char *tr = trap_ptr[signo];
13268                         if (tr) {
13269                                 /* note: bash adds "SIG", but only if invoked
13270                                  * as "bash". If called as "sh", or if set -o posix,
13271                                  * then it prints short signal names.
13272                                  * We are printing short names: */
13273                                 out1fmt("trap -- %s %s\n",
13274                                                 single_quote(tr),
13275                                                 get_signame(signo));
13276                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13277                  * In this case, we will exit very soon, no need to free(). */
13278                                 /* if (trap_ptr != trap && tp[0]) */
13279                                 /*      free(tr); */
13280                         }
13281                 }
13282                 /*
13283                 if (trap_ptr != trap) {
13284                         free(trap_ptr);
13285                         trap_ptr = trap;
13286                 }
13287                 */
13288                 return 0;
13289         }
13290
13291         /* Why the second check?
13292          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13293          * In this case, NUM is signal no, not an action.
13294          */
13295         action = NULL;
13296         if (ap[1] && !is_number(ap[0]))
13297                 action = *ap++;
13298
13299         exitcode = 0;
13300         while (*ap) {
13301                 signo = get_signum(*ap);
13302                 if (signo < 0) {
13303                         /* Mimic bash message exactly */
13304                         ash_msg("%s: invalid signal specification", *ap);
13305                         exitcode = 1;
13306                         goto next;
13307                 }
13308                 INT_OFF;
13309                 if (action) {
13310                         if (LONE_DASH(action))
13311                                 action = NULL;
13312                         else {
13313                                 if (action[0]) /* not NULL and not "" and not "-" */
13314                                         may_have_traps = 1;
13315                                 action = ckstrdup(action);
13316                         }
13317                 }
13318                 free(trap[signo]);
13319                 trap[signo] = action;
13320                 if (signo != 0)
13321                         setsignal(signo);
13322                 INT_ON;
13323  next:
13324                 ap++;
13325         }
13326         return exitcode;
13327 }
13328
13329
13330 /* ============ Builtins */
13331
13332 #if ENABLE_ASH_HELP
13333 static int FAST_FUNC
13334 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13335 {
13336         unsigned col;
13337         unsigned i;
13338
13339         out1fmt(
13340                 "Built-in commands:\n"
13341                 "------------------\n");
13342         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13343                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13344                                         builtintab[i].name + 1);
13345                 if (col > 60) {
13346                         out1fmt("\n");
13347                         col = 0;
13348                 }
13349         }
13350 # if ENABLE_FEATURE_SH_STANDALONE
13351         {
13352                 const char *a = applet_names;
13353                 while (*a) {
13354                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13355                         if (col > 60) {
13356                                 out1fmt("\n");
13357                                 col = 0;
13358                         }
13359                         while (*a++ != '\0')
13360                                 continue;
13361                 }
13362         }
13363 # endif
13364         newline_and_flush(stdout);
13365         return EXIT_SUCCESS;
13366 }
13367 #endif
13368
13369 #if MAX_HISTORY
13370 static int FAST_FUNC
13371 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13372 {
13373         show_history(line_input_state);
13374         return EXIT_SUCCESS;
13375 }
13376 #endif
13377
13378 /*
13379  * The export and readonly commands.
13380  */
13381 static int FAST_FUNC
13382 exportcmd(int argc UNUSED_PARAM, char **argv)
13383 {
13384         struct var *vp;
13385         char *name;
13386         const char *p;
13387         char **aptr;
13388         char opt;
13389         int flag;
13390         int flag_off;
13391
13392         /* "readonly" in bash accepts, but ignores -n.
13393          * We do the same: it saves a conditional in nextopt's param.
13394          */
13395         flag_off = 0;
13396         while ((opt = nextopt("np")) != '\0') {
13397                 if (opt == 'n')
13398                         flag_off = VEXPORT;
13399         }
13400         flag = VEXPORT;
13401         if (argv[0][0] == 'r') {
13402                 flag = VREADONLY;
13403                 flag_off = 0; /* readonly ignores -n */
13404         }
13405         flag_off = ~flag_off;
13406
13407         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13408         {
13409                 aptr = argptr;
13410                 name = *aptr;
13411                 if (name) {
13412                         do {
13413                                 p = strchr(name, '=');
13414                                 if (p != NULL) {
13415                                         p++;
13416                                 } else {
13417                                         vp = *findvar(hashvar(name), name);
13418                                         if (vp) {
13419                                                 vp->flags = ((vp->flags | flag) & flag_off);
13420                                                 continue;
13421                                         }
13422                                 }
13423                                 setvar(name, p, (flag & flag_off));
13424                         } while ((name = *++aptr) != NULL);
13425                         return 0;
13426                 }
13427         }
13428
13429         /* No arguments. Show the list of exported or readonly vars.
13430          * -n is ignored.
13431          */
13432         showvars(argv[0], flag, 0);
13433         return 0;
13434 }
13435
13436 /*
13437  * Delete a function if it exists.
13438  */
13439 static void
13440 unsetfunc(const char *name)
13441 {
13442         struct tblentry *cmdp;
13443
13444         cmdp = cmdlookup(name, 0);
13445         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13446                 delete_cmd_entry();
13447 }
13448
13449 /*
13450  * The unset builtin command.  We unset the function before we unset the
13451  * variable to allow a function to be unset when there is a readonly variable
13452  * with the same name.
13453  */
13454 static int FAST_FUNC
13455 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13456 {
13457         char **ap;
13458         int i;
13459         int flag = 0;
13460
13461         while ((i = nextopt("vf")) != 0) {
13462                 flag = i;
13463         }
13464
13465         for (ap = argptr; *ap; ap++) {
13466                 if (flag != 'f') {
13467                         unsetvar(*ap);
13468                         continue;
13469                 }
13470                 if (flag != 'v')
13471                         unsetfunc(*ap);
13472         }
13473         return 0;
13474 }
13475
13476 static const unsigned char timescmd_str[] ALIGN1 = {
13477         ' ',  offsetof(struct tms, tms_utime),
13478         '\n', offsetof(struct tms, tms_stime),
13479         ' ',  offsetof(struct tms, tms_cutime),
13480         '\n', offsetof(struct tms, tms_cstime),
13481         0
13482 };
13483 static int FAST_FUNC
13484 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13485 {
13486         unsigned clk_tck;
13487         const unsigned char *p;
13488         struct tms buf;
13489
13490         clk_tck = bb_clk_tck();
13491
13492         times(&buf);
13493         p = timescmd_str;
13494         do {
13495                 unsigned sec, frac;
13496                 unsigned long t;
13497                 t = *(clock_t *)(((char *) &buf) + p[1]);
13498                 sec = t / clk_tck;
13499                 frac = t % clk_tck;
13500                 out1fmt("%um%u.%03us%c",
13501                         sec / 60, sec % 60,
13502                         (frac * 1000) / clk_tck,
13503                         p[0]);
13504                 p += 2;
13505         } while (*p);
13506
13507         return 0;
13508 }
13509
13510 #if ENABLE_FEATURE_SH_MATH
13511 /*
13512  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13513  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13514  *
13515  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13516  */
13517 static int FAST_FUNC
13518 letcmd(int argc UNUSED_PARAM, char **argv)
13519 {
13520         arith_t i;
13521
13522         argv++;
13523         if (!*argv)
13524                 ash_msg_and_raise_error("expression expected");
13525         do {
13526                 i = ash_arith(*argv);
13527         } while (*++argv);
13528
13529         return !i;
13530 }
13531 #endif
13532
13533 /*
13534  * The read builtin. Options:
13535  *      -r              Do not interpret '\' specially
13536  *      -s              Turn off echo (tty only)
13537  *      -n NCHARS       Read NCHARS max
13538  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13539  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13540  *      -u FD           Read from given FD instead of fd 0
13541  *      -d DELIM        End on DELIM char, not newline
13542  * This uses unbuffered input, which may be avoidable in some cases.
13543  * TODO: bash also has:
13544  *      -a ARRAY        Read into array[0],[1],etc
13545  *      -e              Use line editing (tty only)
13546  */
13547 static int FAST_FUNC
13548 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13549 {
13550         char *opt_n = NULL;
13551         char *opt_p = NULL;
13552         char *opt_t = NULL;
13553         char *opt_u = NULL;
13554         char *opt_d = NULL; /* optimized out if !BASH */
13555         int read_flags = 0;
13556         const char *r;
13557         int i;
13558
13559         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13560                 switch (i) {
13561                 case 'p':
13562                         opt_p = optionarg;
13563                         break;
13564                 case 'n':
13565                         opt_n = optionarg;
13566                         break;
13567                 case 's':
13568                         read_flags |= BUILTIN_READ_SILENT;
13569                         break;
13570                 case 't':
13571                         opt_t = optionarg;
13572                         break;
13573                 case 'r':
13574                         read_flags |= BUILTIN_READ_RAW;
13575                         break;
13576                 case 'u':
13577                         opt_u = optionarg;
13578                         break;
13579 #if BASH_READ_D
13580                 case 'd':
13581                         opt_d = optionarg;
13582                         break;
13583 #endif
13584                 default:
13585                         break;
13586                 }
13587         }
13588
13589         /* "read -s" needs to save/restore termios, can't allow ^C
13590          * to jump out of it.
13591          */
13592  again:
13593         INT_OFF;
13594         r = shell_builtin_read(setvar0,
13595                 argptr,
13596                 bltinlookup("IFS"), /* can be NULL */
13597                 read_flags,
13598                 opt_n,
13599                 opt_p,
13600                 opt_t,
13601                 opt_u,
13602                 opt_d
13603         );
13604         INT_ON;
13605
13606         if ((uintptr_t)r == 1 && errno == EINTR) {
13607                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13608                  * Correct behavior is to not exit "read"
13609                  */
13610                 if (pending_sig == 0)
13611                         goto again;
13612         }
13613
13614         if ((uintptr_t)r > 1)
13615                 ash_msg_and_raise_error(r);
13616
13617         return (uintptr_t)r;
13618 }
13619
13620 static int FAST_FUNC
13621 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13622 {
13623         static const char permuser[3] ALIGN1 = "ogu";
13624
13625         mode_t mask;
13626         int symbolic_mode = 0;
13627
13628         while (nextopt("S") != '\0') {
13629                 symbolic_mode = 1;
13630         }
13631
13632         INT_OFF;
13633         mask = umask(0);
13634         umask(mask);
13635         INT_ON;
13636
13637         if (*argptr == NULL) {
13638                 if (symbolic_mode) {
13639                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13640                         char *p = buf;
13641                         int i;
13642
13643                         i = 2;
13644                         for (;;) {
13645                                 *p++ = ',';
13646                                 *p++ = permuser[i];
13647                                 *p++ = '=';
13648                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13649                                 if (!(mask & 0400)) *p++ = 'r';
13650                                 if (!(mask & 0200)) *p++ = 'w';
13651                                 if (!(mask & 0100)) *p++ = 'x';
13652                                 mask <<= 3;
13653                                 if (--i < 0)
13654                                         break;
13655                         }
13656                         *p = '\0';
13657                         puts(buf + 1);
13658                 } else {
13659                         out1fmt("%04o\n", mask);
13660                 }
13661         } else {
13662                 char *modestr = *argptr;
13663                 /* numeric umasks are taken as-is */
13664                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13665                 if (!isdigit(modestr[0]))
13666                         mask ^= 0777;
13667                 mask = bb_parse_mode(modestr, mask);
13668                 if ((unsigned)mask > 0777) {
13669                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13670                 }
13671                 if (!isdigit(modestr[0]))
13672                         mask ^= 0777;
13673                 umask(mask);
13674         }
13675         return 0;
13676 }
13677
13678 static int FAST_FUNC
13679 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13680 {
13681         return shell_builtin_ulimit(argv);
13682 }
13683
13684 /* ============ main() and helpers */
13685
13686 /*
13687  * Called to exit the shell.
13688  */
13689 static void
13690 exitshell(void)
13691 {
13692         struct jmploc loc;
13693         char *p;
13694         int status;
13695
13696 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13697         save_history(line_input_state);
13698 #endif
13699         status = exitstatus;
13700         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13701         if (setjmp(loc.loc)) {
13702                 if (exception_type == EXEXIT)
13703                         status = exitstatus;
13704                 goto out;
13705         }
13706         exception_handler = &loc;
13707         p = trap[0];
13708         if (p) {
13709                 trap[0] = NULL;
13710                 evalskip = 0;
13711                 evalstring(p, 0);
13712                 /*free(p); - we'll exit soon */
13713         }
13714  out:
13715         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13716          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13717          */
13718         setjobctl(0);
13719         flush_stdout_stderr();
13720         _exit(status);
13721         /* NOTREACHED */
13722 }
13723
13724 /* Don't inline: conserve stack of caller from having our locals too */
13725 static NOINLINE void
13726 init(void)
13727 {
13728         /* we will never free this */
13729         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13730         basepf.linno = 1;
13731
13732         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13733         setsignal(SIGCHLD);
13734
13735         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13736          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13737          */
13738         signal(SIGHUP, SIG_DFL);
13739
13740         {
13741                 char **envp;
13742                 const char *p;
13743
13744                 initvar();
13745                 for (envp = environ; envp && *envp; envp++) {
13746 /* Used to have
13747  *                      p = endofname(*envp);
13748  *                      if (p != *envp && *p == '=') {
13749  * here to weed out badly-named variables, but this breaks
13750  * scenarios where people do want them passed to children:
13751  * import os
13752  * os.environ["test-test"]="test"
13753  * if os.fork() == 0:
13754  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13755  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13756  */
13757                         if (strchr(*envp, '=')) {
13758                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13759                         }
13760                 }
13761
13762                 setvareq((char*)defoptindvar, VTEXTFIXED);
13763
13764                 setvar0("PPID", utoa(getppid()));
13765 #if BASH_SHLVL_VAR
13766                 p = lookupvar("SHLVL");
13767                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13768 #endif
13769 #if BASH_HOSTNAME_VAR
13770                 if (!lookupvar("HOSTNAME")) {
13771                         struct utsname uts;
13772                         uname(&uts);
13773                         setvar0("HOSTNAME", uts.nodename);
13774                 }
13775 #endif
13776                 p = lookupvar("PWD");
13777                 if (p) {
13778                         struct stat st1, st2;
13779                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13780                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13781                         ) {
13782                                 p = NULL;
13783                         }
13784                 }
13785                 setpwd(p, 0);
13786         }
13787 }
13788
13789
13790 //usage:#define ash_trivial_usage
13791 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13792 //usage:#define ash_full_usage "\n\n"
13793 //usage:        "Unix shell interpreter"
13794
13795 /*
13796  * Process the shell command line arguments.
13797  */
13798 static int
13799 procargs(char **argv)
13800 {
13801         int i;
13802         const char *xminusc;
13803         char **xargv;
13804         int login_sh;
13805
13806         xargv = argv;
13807         login_sh = xargv[0] && xargv[0][0] == '-';
13808         arg0 = xargv[0];
13809         /* if (xargv[0]) - mmm, this is always true! */
13810                 xargv++;
13811         for (i = 0; i < NOPTS; i++)
13812                 optlist[i] = 2;
13813         argptr = xargv;
13814         if (options(/*cmdline:*/ 1, &login_sh)) {
13815                 /* it already printed err message */
13816                 raise_exception(EXERROR);
13817         }
13818         xargv = argptr;
13819         xminusc = minusc;
13820         if (*xargv == NULL) {
13821                 if (xminusc)
13822                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13823                 sflag = 1;
13824         }
13825         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13826                 iflag = 1;
13827         if (mflag == 2)
13828                 mflag = iflag;
13829         for (i = 0; i < NOPTS; i++)
13830                 if (optlist[i] == 2)
13831                         optlist[i] = 0;
13832 #if DEBUG == 2
13833         debug = 1;
13834 #endif
13835         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13836         if (xminusc) {
13837                 minusc = *xargv++;
13838                 if (*xargv)
13839                         goto setarg0;
13840         } else if (!sflag) {
13841                 setinputfile(*xargv, 0);
13842  setarg0:
13843                 arg0 = *xargv++;
13844                 commandname = arg0;
13845         }
13846
13847         shellparam.p = xargv;
13848 #if ENABLE_ASH_GETOPTS
13849         shellparam.optind = 1;
13850         shellparam.optoff = -1;
13851 #endif
13852         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13853         while (*xargv) {
13854                 shellparam.nparam++;
13855                 xargv++;
13856         }
13857         optschanged();
13858
13859         return login_sh;
13860 }
13861
13862 /*
13863  * Read /etc/profile, ~/.profile, $ENV.
13864  */
13865 static void
13866 read_profile(const char *name)
13867 {
13868         name = expandstr(name, DQSYNTAX);
13869         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13870                 return;
13871         cmdloop(0);
13872         popfile();
13873 }
13874
13875 /*
13876  * This routine is called when an error or an interrupt occurs in an
13877  * interactive shell and control is returned to the main command loop.
13878  * (In dash, this function is auto-generated by build machinery).
13879  */
13880 static void
13881 reset(void)
13882 {
13883         /* from eval.c: */
13884         evalskip = 0;
13885         loopnest = 0;
13886
13887         /* from expand.c: */
13888         ifsfree();
13889
13890         /* from input.c: */
13891         g_parsefile->left_in_buffer = 0;
13892         g_parsefile->left_in_line = 0;      /* clear input buffer */
13893         popallfiles();
13894
13895         /* from redir.c: */
13896         unwindredir(NULL);
13897
13898         /* from var.c: */
13899         unwindlocalvars(NULL);
13900 }
13901
13902 #if PROFILE
13903 static short profile_buf[16384];
13904 extern int etext();
13905 #endif
13906
13907 /*
13908  * Main routine.  We initialize things, parse the arguments, execute
13909  * profiles if we're a login shell, and then call cmdloop to execute
13910  * commands.  The setjmp call sets up the location to jump to when an
13911  * exception occurs.  When an exception occurs the variable "state"
13912  * is used to figure out how far we had gotten.
13913  */
13914 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13915 int ash_main(int argc UNUSED_PARAM, char **argv)
13916 {
13917         volatile smallint state;
13918         struct jmploc jmploc;
13919         struct stackmark smark;
13920         int login_sh;
13921
13922         /* Initialize global data */
13923         INIT_G_misc();
13924         INIT_G_memstack();
13925         INIT_G_var();
13926 #if ENABLE_ASH_ALIAS
13927         INIT_G_alias();
13928 #endif
13929         INIT_G_cmdtable();
13930
13931 #if PROFILE
13932         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13933 #endif
13934
13935 #if ENABLE_FEATURE_EDITING
13936         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13937 #endif
13938         state = 0;
13939         if (setjmp(jmploc.loc)) {
13940                 smallint e;
13941                 smallint s;
13942
13943                 reset();
13944
13945                 e = exception_type;
13946                 s = state;
13947                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13948                         exitshell();
13949                 }
13950                 if (e == EXINT) {
13951                         newline_and_flush(stderr);
13952                 }
13953
13954                 popstackmark(&smark);
13955                 FORCE_INT_ON; /* enable interrupts */
13956                 if (s == 1)
13957                         goto state1;
13958                 if (s == 2)
13959                         goto state2;
13960                 if (s == 3)
13961                         goto state3;
13962                 goto state4;
13963         }
13964         exception_handler = &jmploc;
13965         rootpid = getpid();
13966
13967         init();
13968         setstackmark(&smark);
13969         login_sh = procargs(argv);
13970 #if DEBUG
13971         TRACE(("Shell args: "));
13972         trace_puts_args(argv);
13973 #endif
13974
13975         if (login_sh) {
13976                 const char *hp;
13977
13978                 state = 1;
13979                 read_profile("/etc/profile");
13980  state1:
13981                 state = 2;
13982                 hp = lookupvar("HOME");
13983                 if (hp)
13984                         read_profile("$HOME/.profile");
13985         }
13986  state2:
13987         state = 3;
13988         if (
13989 #ifndef linux
13990          getuid() == geteuid() && getgid() == getegid() &&
13991 #endif
13992          iflag
13993         ) {
13994                 const char *shinit = lookupvar("ENV");
13995                 if (shinit != NULL && *shinit != '\0')
13996                         read_profile(shinit);
13997         }
13998         popstackmark(&smark);
13999  state3:
14000         state = 4;
14001         if (minusc) {
14002                 /* evalstring pushes parsefile stack.
14003                  * Ensure we don't falsely claim that 0 (stdin)
14004                  * is one of stacked source fds.
14005                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14006                 // if (!sflag) g_parsefile->pf_fd = -1;
14007                 // ^^ not necessary since now we special-case fd 0
14008                 // in save_fd_on_redirect()
14009                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14010         }
14011
14012         if (sflag || minusc == NULL) {
14013 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14014                 if (iflag) {
14015                         const char *hp = lookupvar("HISTFILE");
14016                         if (!hp) {
14017                                 hp = lookupvar("HOME");
14018                                 if (hp) {
14019                                         INT_OFF;
14020                                         hp = concat_path_file(hp, ".ash_history");
14021                                         setvar0("HISTFILE", hp);
14022                                         free((char*)hp);
14023                                         INT_ON;
14024                                         hp = lookupvar("HISTFILE");
14025                                 }
14026                         }
14027                         if (hp)
14028                                 line_input_state->hist_file = hp;
14029 # if ENABLE_FEATURE_SH_HISTFILESIZE
14030                         hp = lookupvar("HISTFILESIZE");
14031                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14032 # endif
14033                 }
14034 #endif
14035  state4: /* XXX ??? - why isn't this before the "if" statement */
14036                 cmdloop(1);
14037         }
14038 #if PROFILE
14039         monitor(0);
14040 #endif
14041 #ifdef GPROF
14042         {
14043                 extern void _mcleanup(void);
14044                 _mcleanup();
14045         }
14046 #endif
14047         TRACE(("End of main reached\n"));
14048         exitshell();
14049         /* NOTREACHED */
14050 }
14051
14052
14053 /*-
14054  * Copyright (c) 1989, 1991, 1993, 1994
14055  *      The Regents of the University of California.  All rights reserved.
14056  *
14057  * This code is derived from software contributed to Berkeley by
14058  * Kenneth Almquist.
14059  *
14060  * Redistribution and use in source and binary forms, with or without
14061  * modification, are permitted provided that the following conditions
14062  * are met:
14063  * 1. Redistributions of source code must retain the above copyright
14064  *    notice, this list of conditions and the following disclaimer.
14065  * 2. Redistributions in binary form must reproduce the above copyright
14066  *    notice, this list of conditions and the following disclaimer in the
14067  *    documentation and/or other materials provided with the distribution.
14068  * 3. Neither the name of the University nor the names of its contributors
14069  *    may be used to endorse or promote products derived from this software
14070  *    without specific prior written permission.
14071  *
14072  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14073  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14074  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14075  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14076  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14077  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14078  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14079  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14080  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14081  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14082  * SUCH DAMAGE.
14083  */