ash: add support for command_not_found_handle hook function (bashism)
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_BASH_NOT_FOUND_HOOK
55 //config:       bool "command_not_found_handle hook support"
56 //config:       default y
57 //config:       depends ASH_BASH_COMPAT
58 //config:       help
59 //config:       Enable support for the 'command_not_found_handle' hook function,
60 //config:       from GNU bash, which allows for alternative command not found
61 //config:       handling.
62 //config:
63 //config:config ASH_JOB_CONTROL
64 //config:       bool "Job control"
65 //config:       default y
66 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
67 //config:
68 //config:config ASH_ALIAS
69 //config:       bool "Alias support"
70 //config:       default y
71 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
72 //config:
73 //config:config ASH_RANDOM_SUPPORT
74 //config:       bool "Pseudorandom generator and $RANDOM variable"
75 //config:       default y
76 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
77 //config:       help
78 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
79 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
80 //config:       You can reset the generator by using a specified start value.
81 //config:       After "unset RANDOM" the generator will switch off and this
82 //config:       variable will no longer have special treatment.
83 //config:
84 //config:config ASH_EXPAND_PRMT
85 //config:       bool "Expand prompt string"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       $PS# may contain volatile content, such as backquote commands.
90 //config:       This option recreates the prompt string from the environment
91 //config:       variable each time it is displayed.
92 //config:
93 //config:config ASH_IDLE_TIMEOUT
94 //config:       bool "Idle timeout variable $TMOUT"
95 //config:       default y
96 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
97 //config:       help
98 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
99 //config:
100 //config:config ASH_MAIL
101 //config:       bool "Check for new mail in interactive shell"
102 //config:       default y
103 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
104 //config:       help
105 //config:       Enable "check for new mail" function:
106 //config:       if set, $MAIL file and $MAILPATH list of files
107 //config:       are checked for mtime changes, and "you have mail"
108 //config:       message is printed if change is detected.
109 //config:
110 //config:config ASH_ECHO
111 //config:       bool "echo builtin"
112 //config:       default y
113 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
114 //config:
115 //config:config ASH_PRINTF
116 //config:       bool "printf builtin"
117 //config:       default y
118 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
119 //config:
120 //config:config ASH_TEST
121 //config:       bool "test builtin"
122 //config:       default y
123 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
124 //config:
125 //config:config ASH_HELP
126 //config:       bool "help builtin"
127 //config:       default y
128 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
129 //config:
130 //config:config ASH_GETOPTS
131 //config:       bool "getopts builtin"
132 //config:       default y
133 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
134 //config:
135 //config:config ASH_CMDCMD
136 //config:       bool "command builtin"
137 //config:       default y
138 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
139 //config:       help
140 //config:       Enable support for the 'command' builtin, which allows
141 //config:       you to run the specified command or builtin,
142 //config:       even when there is a function with the same name.
143 //config:
144 //config:endif # ash options
145
146 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
147 //                      APPLET_ODDNAME:name  main location    suid_type     help
148 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
149 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
150
151 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
152 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
153 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
154 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
155
156 /*
157  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
158  * DEBUG=2 to compile in and turn on debugging.
159  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
160  * debugging info is written to ./trace, quit signal generates core dump.
161  */
162 #define DEBUG 0
163 /* Tweak debug output verbosity here */
164 #define DEBUG_TIME 0
165 #define DEBUG_PID 1
166 #define DEBUG_SIG 1
167 #define DEBUG_INTONOFF 0
168
169 #define PROFILE 0
170
171 #define JOBS ENABLE_ASH_JOB_CONTROL
172
173 #include <setjmp.h>
174 #include <fnmatch.h>
175 #include <sys/times.h>
176 #include <sys/utsname.h> /* for setting $HOSTNAME */
177 #include "busybox.h" /* for applet_names */
178
179 /* So far, all bash compat is controlled by one config option */
180 /* Separate defines document which part of code implements what */
181 /* function keyword */
182 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
183 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
184 /* &>file */
185 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
186 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
187 /* $'...' */
188 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
189 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
190 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
191 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
192 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
193 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
194 /* [[ EXPR ]] */
195 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
196 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
197 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
198 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
199 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
200 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
201 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
202 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
203
204 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
205 /* Bionic at least up to version 24 has no glob() */
206 # undef  ENABLE_ASH_INTERNAL_GLOB
207 # define ENABLE_ASH_INTERNAL_GLOB 1
208 #endif
209
210 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
211 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
212 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
213 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
214 # error glob() should unbackslash them and match. uClibc does not unbackslash,
215 # error fails to match dirname, subsequently not expanding <pattern> in it.
216 // Testcase:
217 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
218 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
219 #endif
220
221 #if !ENABLE_ASH_INTERNAL_GLOB
222 # include <glob.h>
223 #endif
224
225 #include "unicode.h"
226 #include "shell_common.h"
227 #if ENABLE_FEATURE_SH_MATH
228 # include "math.h"
229 #else
230 typedef long arith_t;
231 # define ARITH_FMT "%ld"
232 #endif
233 #if ENABLE_ASH_RANDOM_SUPPORT
234 # include "random.h"
235 #else
236 # define CLEAR_RANDOM_T(rnd) ((void)0)
237 #endif
238
239 #include "NUM_APPLETS.h"
240 #if NUM_APPLETS == 1
241 /* STANDALONE does not make sense, and won't compile */
242 # undef CONFIG_FEATURE_SH_STANDALONE
243 # undef ENABLE_FEATURE_SH_STANDALONE
244 # undef IF_FEATURE_SH_STANDALONE
245 # undef IF_NOT_FEATURE_SH_STANDALONE
246 # define ENABLE_FEATURE_SH_STANDALONE 0
247 # define IF_FEATURE_SH_STANDALONE(...)
248 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
249 #endif
250
251 #ifndef PIPE_BUF
252 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
253 #endif
254
255 #if !BB_MMU
256 # error "Do not even bother, ash will not run on NOMMU machine"
257 #endif
258
259
260 /* ============ Hash table sizes. Configurable. */
261
262 #define VTABSIZE 39
263 #define ATABSIZE 39
264 #define CMDTABLESIZE 31         /* should be prime */
265
266
267 /* ============ Shell options */
268
269 static const char *const optletters_optnames[] = {
270         "e"   "errexit",
271         "f"   "noglob",
272         "I"   "ignoreeof",
273         "i"   "interactive",
274         "m"   "monitor",
275         "n"   "noexec",
276         "s"   "stdin",
277         "x"   "xtrace",
278         "v"   "verbose",
279         "C"   "noclobber",
280         "a"   "allexport",
281         "b"   "notify",
282         "u"   "nounset",
283         "\0"  "vi"
284 #if BASH_PIPEFAIL
285         ,"\0"  "pipefail"
286 #endif
287 #if DEBUG
288         ,"\0"  "nolog"
289         ,"\0"  "debug"
290 #endif
291 };
292
293 #define optletters(n)  optletters_optnames[n][0]
294 #define optnames(n)   (optletters_optnames[n] + 1)
295
296 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
297
298
299 /* ============ Misc data */
300
301 #define msg_illnum "Illegal number: %s"
302
303 /*
304  * We enclose jmp_buf in a structure so that we can declare pointers to
305  * jump locations.  The global variable handler contains the location to
306  * jump to when an exception occurs, and the global variable exception_type
307  * contains a code identifying the exception.  To implement nested
308  * exception handlers, the user should save the value of handler on entry
309  * to an inner scope, set handler to point to a jmploc structure for the
310  * inner scope, and restore handler on exit from the scope.
311  */
312 struct jmploc {
313         jmp_buf loc;
314 };
315
316 struct globals_misc {
317         uint8_t exitstatus;     /* exit status of last command */
318         uint8_t back_exitstatus;/* exit status of backquoted command */
319         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
320         int rootpid;            /* pid of main shell */
321         /* shell level: 0 for the main shell, 1 for its children, and so on */
322         int shlvl;
323 #define rootshell (!shlvl)
324         char *minusc;  /* argument to -c option */
325
326         char *curdir; // = nullstr;     /* current working directory */
327         char *physdir; // = nullstr;    /* physical working directory */
328
329         char *arg0; /* value of $0 */
330
331         struct jmploc *exception_handler;
332
333         volatile int suppress_int; /* counter */
334         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
335         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
336         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
337         smallint exception_type; /* kind of exception (0..5) */
338         /* exceptions */
339 #define EXINT 0         /* SIGINT received */
340 #define EXERROR 1       /* a generic error */
341 #define EXEXIT 4        /* exit the shell */
342
343         char nullstr[1];        /* zero length string */
344
345         char optlist[NOPTS];
346 #define eflag optlist[0]
347 #define fflag optlist[1]
348 #define Iflag optlist[2]
349 #define iflag optlist[3]
350 #define mflag optlist[4]
351 #define nflag optlist[5]
352 #define sflag optlist[6]
353 #define xflag optlist[7]
354 #define vflag optlist[8]
355 #define Cflag optlist[9]
356 #define aflag optlist[10]
357 #define bflag optlist[11]
358 #define uflag optlist[12]
359 #define viflag optlist[13]
360 #if BASH_PIPEFAIL
361 # define pipefail optlist[14]
362 #else
363 # define pipefail 0
364 #endif
365 #if DEBUG
366 # define nolog optlist[14 + BASH_PIPEFAIL]
367 # define debug optlist[15 + BASH_PIPEFAIL]
368 #endif
369
370         /* trap handler commands */
371         /*
372          * Sigmode records the current value of the signal handlers for the various
373          * modes.  A value of zero means that the current handler is not known.
374          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
375          */
376         char sigmode[NSIG - 1];
377 #define S_DFL      1            /* default signal handling (SIG_DFL) */
378 #define S_CATCH    2            /* signal is caught */
379 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
380 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
381
382         /* indicates specified signal received */
383         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
384         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
385         char *trap[NSIG];
386         char **trap_ptr;        /* used only by "trap hack" */
387
388         /* Rarely referenced stuff */
389 #if ENABLE_ASH_RANDOM_SUPPORT
390         random_t random_gen;
391 #endif
392         pid_t backgndpid;        /* pid of last background process */
393 };
394 extern struct globals_misc *const ash_ptr_to_globals_misc;
395 #define G_misc (*ash_ptr_to_globals_misc)
396 #define exitstatus        (G_misc.exitstatus )
397 #define back_exitstatus   (G_misc.back_exitstatus )
398 #define job_warning       (G_misc.job_warning)
399 #define rootpid     (G_misc.rootpid    )
400 #define shlvl       (G_misc.shlvl      )
401 #define minusc      (G_misc.minusc     )
402 #define curdir      (G_misc.curdir     )
403 #define physdir     (G_misc.physdir    )
404 #define arg0        (G_misc.arg0       )
405 #define exception_handler (G_misc.exception_handler)
406 #define exception_type    (G_misc.exception_type   )
407 #define suppress_int      (G_misc.suppress_int     )
408 #define pending_int       (G_misc.pending_int      )
409 #define got_sigchld       (G_misc.got_sigchld      )
410 #define pending_sig       (G_misc.pending_sig      )
411 #define nullstr     (G_misc.nullstr    )
412 #define optlist     (G_misc.optlist    )
413 #define sigmode     (G_misc.sigmode    )
414 #define gotsig      (G_misc.gotsig     )
415 #define may_have_traps    (G_misc.may_have_traps   )
416 #define trap        (G_misc.trap       )
417 #define trap_ptr    (G_misc.trap_ptr   )
418 #define random_gen  (G_misc.random_gen )
419 #define backgndpid  (G_misc.backgndpid )
420 #define INIT_G_misc() do { \
421         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
422         barrier(); \
423         curdir = nullstr; \
424         physdir = nullstr; \
425         trap_ptr = trap; \
426 } while (0)
427
428
429 /* ============ DEBUG */
430 #if DEBUG
431 static void trace_printf(const char *fmt, ...);
432 static void trace_vprintf(const char *fmt, va_list va);
433 # define TRACE(param)    trace_printf param
434 # define TRACEV(param)   trace_vprintf param
435 # define close(fd) do { \
436         int dfd = (fd); \
437         if (close(dfd) < 0) \
438                 bb_error_msg("bug on %d: closing %d(0x%x)", \
439                         __LINE__, dfd, dfd); \
440 } while (0)
441 #else
442 # define TRACE(param)
443 # define TRACEV(param)
444 #endif
445
446
447 /* ============ Utility functions */
448 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
449 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
450
451 static int
452 isdigit_str9(const char *str)
453 {
454         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
455         while (--maxlen && isdigit(*str))
456                 str++;
457         return (*str == '\0');
458 }
459
460 static const char *
461 var_end(const char *var)
462 {
463         while (*var)
464                 if (*var++ == '=')
465                         break;
466         return var;
467 }
468
469
470 /* ============ Interrupts / exceptions */
471
472 static void exitshell(void) NORETURN;
473
474 /*
475  * These macros allow the user to suspend the handling of interrupt signals
476  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
477  * much more efficient and portable.  (But hacking the kernel is so much
478  * more fun than worrying about efficiency and portability. :-))
479  */
480 #if DEBUG_INTONOFF
481 # define INT_OFF do { \
482         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
483         suppress_int++; \
484         barrier(); \
485 } while (0)
486 #else
487 # define INT_OFF do { \
488         suppress_int++; \
489         barrier(); \
490 } while (0)
491 #endif
492
493 /*
494  * Called to raise an exception.  Since C doesn't include exceptions, we
495  * just do a longjmp to the exception handler.  The type of exception is
496  * stored in the global variable "exception_type".
497  */
498 static void raise_exception(int) NORETURN;
499 static void
500 raise_exception(int e)
501 {
502 #if DEBUG
503         if (exception_handler == NULL)
504                 abort();
505 #endif
506         INT_OFF;
507         exception_type = e;
508         longjmp(exception_handler->loc, 1);
509 }
510 #if DEBUG
511 #define raise_exception(e) do { \
512         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
513         raise_exception(e); \
514 } while (0)
515 #endif
516
517 /*
518  * Called when a SIGINT is received.  (If the user specifies
519  * that SIGINT is to be trapped or ignored using the trap builtin, then
520  * this routine is not called.)  Suppressint is nonzero when interrupts
521  * are held using the INT_OFF macro.  (The test for iflag is just
522  * defensive programming.)
523  */
524 static void raise_interrupt(void) NORETURN;
525 static void
526 raise_interrupt(void)
527 {
528         pending_int = 0;
529         /* Signal is not automatically unmasked after it is raised,
530          * do it ourself - unmask all signals */
531         sigprocmask_allsigs(SIG_UNBLOCK);
532         /* pending_sig = 0; - now done in signal_handler() */
533
534         if (!(rootshell && iflag)) {
535                 /* Kill ourself with SIGINT */
536                 signal(SIGINT, SIG_DFL);
537                 raise(SIGINT);
538         }
539         /* bash: ^C even on empty command line sets $? */
540         exitstatus = SIGINT + 128;
541         raise_exception(EXINT);
542         /* NOTREACHED */
543 }
544 #if DEBUG
545 #define raise_interrupt() do { \
546         TRACE(("raising interrupt on line %d\n", __LINE__)); \
547         raise_interrupt(); \
548 } while (0)
549 #endif
550
551 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
552 int_on(void)
553 {
554         barrier();
555         if (--suppress_int == 0 && pending_int) {
556                 raise_interrupt();
557         }
558 }
559 #if DEBUG_INTONOFF
560 # define INT_ON do { \
561         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
562         int_on(); \
563 } while (0)
564 #else
565 # define INT_ON int_on()
566 #endif
567 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
568 force_int_on(void)
569 {
570         barrier();
571         suppress_int = 0;
572         if (pending_int)
573                 raise_interrupt();
574 }
575 #define FORCE_INT_ON force_int_on()
576
577 #define SAVE_INT(v) ((v) = suppress_int)
578
579 #define RESTORE_INT(v) do { \
580         barrier(); \
581         suppress_int = (v); \
582         if (suppress_int == 0 && pending_int) \
583                 raise_interrupt(); \
584 } while (0)
585
586
587 /* ============ Stdout/stderr output */
588
589 static void
590 outstr(const char *p, FILE *file)
591 {
592         INT_OFF;
593         fputs(p, file);
594         INT_ON;
595 }
596
597 static void
598 flush_stdout_stderr(void)
599 {
600         INT_OFF;
601         fflush_all();
602         INT_ON;
603 }
604
605 /* Was called outcslow(c,FILE*), but c was always '\n' */
606 static void
607 newline_and_flush(FILE *dest)
608 {
609         INT_OFF;
610         putc('\n', dest);
611         fflush(dest);
612         INT_ON;
613 }
614
615 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
616 static int
617 out1fmt(const char *fmt, ...)
618 {
619         va_list ap;
620         int r;
621
622         INT_OFF;
623         va_start(ap, fmt);
624         r = vprintf(fmt, ap);
625         va_end(ap);
626         INT_ON;
627         return r;
628 }
629
630 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
631 static int
632 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
633 {
634         va_list ap;
635         int ret;
636
637         INT_OFF;
638         va_start(ap, fmt);
639         ret = vsnprintf(outbuf, length, fmt, ap);
640         va_end(ap);
641         INT_ON;
642         return ret;
643 }
644
645 static void
646 out1str(const char *p)
647 {
648         outstr(p, stdout);
649 }
650
651 static void
652 out2str(const char *p)
653 {
654         outstr(p, stderr);
655         flush_stdout_stderr();
656 }
657
658
659 /* ============ Parser structures */
660
661 /* control characters in argument strings */
662 #define CTL_FIRST CTLESC
663 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
664 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
665 #define CTLENDVAR    ((unsigned char)'\203')
666 #define CTLBACKQ     ((unsigned char)'\204')
667 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
668 #define CTLENDARI    ((unsigned char)'\207')
669 #define CTLQUOTEMARK ((unsigned char)'\210')
670 #define CTL_LAST CTLQUOTEMARK
671
672 /* variable substitution byte (follows CTLVAR) */
673 #define VSTYPE  0x0f            /* type of variable substitution */
674 #define VSNUL   0x10            /* colon--treat the empty string as unset */
675
676 /* values of VSTYPE field */
677 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
678 #define VSMINUS         0x2     /* ${var-text} */
679 #define VSPLUS          0x3     /* ${var+text} */
680 #define VSQUESTION      0x4     /* ${var?message} */
681 #define VSASSIGN        0x5     /* ${var=text} */
682 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
683 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
684 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
685 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
686 #define VSLENGTH        0xa     /* ${#var} */
687 #if BASH_SUBSTR
688 #define VSSUBSTR        0xc     /* ${var:position:length} */
689 #endif
690 #if BASH_PATTERN_SUBST
691 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
692 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
693 #endif
694
695 static const char dolatstr[] ALIGN1 = {
696         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
697 };
698 #define DOLATSTRLEN 6
699
700 #define NCMD      0
701 #define NPIPE     1
702 #define NREDIR    2
703 #define NBACKGND  3
704 #define NSUBSHELL 4
705 #define NAND      5
706 #define NOR       6
707 #define NSEMI     7
708 #define NIF       8
709 #define NWHILE    9
710 #define NUNTIL   10
711 #define NFOR     11
712 #define NCASE    12
713 #define NCLIST   13
714 #define NDEFUN   14
715 #define NARG     15
716 #define NTO      16
717 #if BASH_REDIR_OUTPUT
718 #define NTO2     17
719 #endif
720 #define NCLOBBER 18
721 #define NFROM    19
722 #define NFROMTO  20
723 #define NAPPEND  21
724 #define NTOFD    22
725 #define NFROMFD  23
726 #define NHERE    24
727 #define NXHERE   25
728 #define NNOT     26
729 #define N_NUMBER 27
730
731 union node;
732
733 struct ncmd {
734         smallint type; /* Nxxxx */
735         union node *assign;
736         union node *args;
737         union node *redirect;
738 };
739
740 struct npipe {
741         smallint type;
742         smallint pipe_backgnd;
743         struct nodelist *cmdlist;
744 };
745
746 struct nredir {
747         smallint type;
748         union node *n;
749         union node *redirect;
750 };
751
752 struct nbinary {
753         smallint type;
754         union node *ch1;
755         union node *ch2;
756 };
757
758 struct nif {
759         smallint type;
760         union node *test;
761         union node *ifpart;
762         union node *elsepart;
763 };
764
765 struct nfor {
766         smallint type;
767         union node *args;
768         union node *body;
769         char *var;
770 };
771
772 struct ncase {
773         smallint type;
774         union node *expr;
775         union node *cases;
776 };
777
778 struct nclist {
779         smallint type;
780         union node *next;
781         union node *pattern;
782         union node *body;
783 };
784
785 struct narg {
786         smallint type;
787         union node *next;
788         char *text;
789         struct nodelist *backquote;
790 };
791
792 /* nfile and ndup layout must match!
793  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
794  * that it is actually NTO2 (>&file), and change its type.
795  */
796 struct nfile {
797         smallint type;
798         union node *next;
799         int fd;
800         int _unused_dupfd;
801         union node *fname;
802         char *expfname;
803 };
804
805 struct ndup {
806         smallint type;
807         union node *next;
808         int fd;
809         int dupfd;
810         union node *vname;
811         char *_unused_expfname;
812 };
813
814 struct nhere {
815         smallint type;
816         union node *next;
817         int fd;
818         union node *doc;
819 };
820
821 struct nnot {
822         smallint type;
823         union node *com;
824 };
825
826 union node {
827         smallint type;
828         struct ncmd ncmd;
829         struct npipe npipe;
830         struct nredir nredir;
831         struct nbinary nbinary;
832         struct nif nif;
833         struct nfor nfor;
834         struct ncase ncase;
835         struct nclist nclist;
836         struct narg narg;
837         struct nfile nfile;
838         struct ndup ndup;
839         struct nhere nhere;
840         struct nnot nnot;
841 };
842
843 /*
844  * NODE_EOF is returned by parsecmd when it encounters an end of file.
845  * It must be distinct from NULL.
846  */
847 #define NODE_EOF ((union node *) -1L)
848
849 struct nodelist {
850         struct nodelist *next;
851         union node *n;
852 };
853
854 struct funcnode {
855         int count;
856         union node n;
857 };
858
859 /*
860  * Free a parse tree.
861  */
862 static void
863 freefunc(struct funcnode *f)
864 {
865         if (f && --f->count < 0)
866                 free(f);
867 }
868
869
870 /* ============ Debugging output */
871
872 #if DEBUG
873
874 static FILE *tracefile;
875
876 static void
877 trace_printf(const char *fmt, ...)
878 {
879         va_list va;
880
881         if (debug != 1)
882                 return;
883         if (DEBUG_TIME)
884                 fprintf(tracefile, "%u ", (int) time(NULL));
885         if (DEBUG_PID)
886                 fprintf(tracefile, "[%u] ", (int) getpid());
887         if (DEBUG_SIG)
888                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
889         va_start(va, fmt);
890         vfprintf(tracefile, fmt, va);
891         va_end(va);
892 }
893
894 static void
895 trace_vprintf(const char *fmt, va_list va)
896 {
897         if (debug != 1)
898                 return;
899         vfprintf(tracefile, fmt, va);
900         fprintf(tracefile, "\n");
901 }
902
903 static void
904 trace_puts(const char *s)
905 {
906         if (debug != 1)
907                 return;
908         fputs(s, tracefile);
909 }
910
911 static void
912 trace_puts_quoted(char *s)
913 {
914         char *p;
915         char c;
916
917         if (debug != 1)
918                 return;
919         putc('"', tracefile);
920         for (p = s; *p; p++) {
921                 switch ((unsigned char)*p) {
922                 case '\n': c = 'n'; goto backslash;
923                 case '\t': c = 't'; goto backslash;
924                 case '\r': c = 'r'; goto backslash;
925                 case '\"': c = '\"'; goto backslash;
926                 case '\\': c = '\\'; goto backslash;
927                 case CTLESC: c = 'e'; goto backslash;
928                 case CTLVAR: c = 'v'; goto backslash;
929                 case CTLBACKQ: c = 'q'; goto backslash;
930  backslash:
931                         putc('\\', tracefile);
932                         putc(c, tracefile);
933                         break;
934                 default:
935                         if (*p >= ' ' && *p <= '~')
936                                 putc(*p, tracefile);
937                         else {
938                                 putc('\\', tracefile);
939                                 putc((*p >> 6) & 03, tracefile);
940                                 putc((*p >> 3) & 07, tracefile);
941                                 putc(*p & 07, tracefile);
942                         }
943                         break;
944                 }
945         }
946         putc('"', tracefile);
947 }
948
949 static void
950 trace_puts_args(char **ap)
951 {
952         if (debug != 1)
953                 return;
954         if (!*ap)
955                 return;
956         while (1) {
957                 trace_puts_quoted(*ap);
958                 if (!*++ap) {
959                         putc('\n', tracefile);
960                         break;
961                 }
962                 putc(' ', tracefile);
963         }
964 }
965
966 static void
967 opentrace(void)
968 {
969         char s[100];
970 #ifdef O_APPEND
971         int flags;
972 #endif
973
974         if (debug != 1) {
975                 if (tracefile)
976                         fflush(tracefile);
977                 /* leave open because libedit might be using it */
978                 return;
979         }
980         strcpy(s, "./trace");
981         if (tracefile) {
982                 if (!freopen(s, "a", tracefile)) {
983                         fprintf(stderr, "Can't re-open %s\n", s);
984                         debug = 0;
985                         return;
986                 }
987         } else {
988                 tracefile = fopen(s, "a");
989                 if (tracefile == NULL) {
990                         fprintf(stderr, "Can't open %s\n", s);
991                         debug = 0;
992                         return;
993                 }
994         }
995 #ifdef O_APPEND
996         flags = fcntl(fileno(tracefile), F_GETFL);
997         if (flags >= 0)
998                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
999 #endif
1000         setlinebuf(tracefile);
1001         fputs("\nTracing started.\n", tracefile);
1002 }
1003
1004 static void
1005 indent(int amount, char *pfx, FILE *fp)
1006 {
1007         int i;
1008
1009         for (i = 0; i < amount; i++) {
1010                 if (pfx && i == amount - 1)
1011                         fputs(pfx, fp);
1012                 putc('\t', fp);
1013         }
1014 }
1015
1016 /* little circular references here... */
1017 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1018
1019 static void
1020 sharg(union node *arg, FILE *fp)
1021 {
1022         char *p;
1023         struct nodelist *bqlist;
1024         unsigned char subtype;
1025
1026         if (arg->type != NARG) {
1027                 out1fmt("<node type %d>\n", arg->type);
1028                 abort();
1029         }
1030         bqlist = arg->narg.backquote;
1031         for (p = arg->narg.text; *p; p++) {
1032                 switch ((unsigned char)*p) {
1033                 case CTLESC:
1034                         p++;
1035                         putc(*p, fp);
1036                         break;
1037                 case CTLVAR:
1038                         putc('$', fp);
1039                         putc('{', fp);
1040                         subtype = *++p;
1041                         if (subtype == VSLENGTH)
1042                                 putc('#', fp);
1043
1044                         while (*p != '=') {
1045                                 putc(*p, fp);
1046                                 p++;
1047                         }
1048
1049                         if (subtype & VSNUL)
1050                                 putc(':', fp);
1051
1052                         switch (subtype & VSTYPE) {
1053                         case VSNORMAL:
1054                                 putc('}', fp);
1055                                 break;
1056                         case VSMINUS:
1057                                 putc('-', fp);
1058                                 break;
1059                         case VSPLUS:
1060                                 putc('+', fp);
1061                                 break;
1062                         case VSQUESTION:
1063                                 putc('?', fp);
1064                                 break;
1065                         case VSASSIGN:
1066                                 putc('=', fp);
1067                                 break;
1068                         case VSTRIMLEFT:
1069                                 putc('#', fp);
1070                                 break;
1071                         case VSTRIMLEFTMAX:
1072                                 putc('#', fp);
1073                                 putc('#', fp);
1074                                 break;
1075                         case VSTRIMRIGHT:
1076                                 putc('%', fp);
1077                                 break;
1078                         case VSTRIMRIGHTMAX:
1079                                 putc('%', fp);
1080                                 putc('%', fp);
1081                                 break;
1082                         case VSLENGTH:
1083                                 break;
1084                         default:
1085                                 out1fmt("<subtype %d>", subtype);
1086                         }
1087                         break;
1088                 case CTLENDVAR:
1089                         putc('}', fp);
1090                         break;
1091                 case CTLBACKQ:
1092                         putc('$', fp);
1093                         putc('(', fp);
1094                         shtree(bqlist->n, -1, NULL, fp);
1095                         putc(')', fp);
1096                         break;
1097                 default:
1098                         putc(*p, fp);
1099                         break;
1100                 }
1101         }
1102 }
1103
1104 static void
1105 shcmd(union node *cmd, FILE *fp)
1106 {
1107         union node *np;
1108         int first;
1109         const char *s;
1110         int dftfd;
1111
1112         first = 1;
1113         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1114                 if (!first)
1115                         putc(' ', fp);
1116                 sharg(np, fp);
1117                 first = 0;
1118         }
1119         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1120                 if (!first)
1121                         putc(' ', fp);
1122                 dftfd = 0;
1123                 switch (np->nfile.type) {
1124                 case NTO:      s = ">>"+1; dftfd = 1; break;
1125                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1126                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1127 #if BASH_REDIR_OUTPUT
1128                 case NTO2:
1129 #endif
1130                 case NTOFD:    s = ">&"; dftfd = 1; break;
1131                 case NFROM:    s = "<"; break;
1132                 case NFROMFD:  s = "<&"; break;
1133                 case NFROMTO:  s = "<>"; break;
1134                 default:       s = "*error*"; break;
1135                 }
1136                 if (np->nfile.fd != dftfd)
1137                         fprintf(fp, "%d", np->nfile.fd);
1138                 fputs(s, fp);
1139                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1140                         fprintf(fp, "%d", np->ndup.dupfd);
1141                 } else {
1142                         sharg(np->nfile.fname, fp);
1143                 }
1144                 first = 0;
1145         }
1146 }
1147
1148 static void
1149 shtree(union node *n, int ind, char *pfx, FILE *fp)
1150 {
1151         struct nodelist *lp;
1152         const char *s;
1153
1154         if (n == NULL)
1155                 return;
1156
1157         indent(ind, pfx, fp);
1158
1159         if (n == NODE_EOF) {
1160                 fputs("<EOF>", fp);
1161                 return;
1162         }
1163
1164         switch (n->type) {
1165         case NSEMI:
1166                 s = "; ";
1167                 goto binop;
1168         case NAND:
1169                 s = " && ";
1170                 goto binop;
1171         case NOR:
1172                 s = " || ";
1173  binop:
1174                 shtree(n->nbinary.ch1, ind, NULL, fp);
1175                 /* if (ind < 0) */
1176                         fputs(s, fp);
1177                 shtree(n->nbinary.ch2, ind, NULL, fp);
1178                 break;
1179         case NCMD:
1180                 shcmd(n, fp);
1181                 if (ind >= 0)
1182                         putc('\n', fp);
1183                 break;
1184         case NPIPE:
1185                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1186                         shtree(lp->n, 0, NULL, fp);
1187                         if (lp->next)
1188                                 fputs(" | ", fp);
1189                 }
1190                 if (n->npipe.pipe_backgnd)
1191                         fputs(" &", fp);
1192                 if (ind >= 0)
1193                         putc('\n', fp);
1194                 break;
1195         default:
1196                 fprintf(fp, "<node type %d>", n->type);
1197                 if (ind >= 0)
1198                         putc('\n', fp);
1199                 break;
1200         }
1201 }
1202
1203 static void
1204 showtree(union node *n)
1205 {
1206         trace_puts("showtree called\n");
1207         shtree(n, 1, NULL, stderr);
1208 }
1209
1210 #endif /* DEBUG */
1211
1212
1213 /* ============ Parser data */
1214
1215 /*
1216  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1217  */
1218 struct strlist {
1219         struct strlist *next;
1220         char *text;
1221 };
1222
1223 struct alias;
1224
1225 struct strpush {
1226         struct strpush *prev;   /* preceding string on stack */
1227         char *prev_string;
1228         int prev_left_in_line;
1229 #if ENABLE_ASH_ALIAS
1230         struct alias *ap;       /* if push was associated with an alias */
1231 #endif
1232         char *string;           /* remember the string since it may change */
1233
1234         /* Remember last two characters for pungetc. */
1235         int lastc[2];
1236
1237         /* Number of outstanding calls to pungetc. */
1238         int unget;
1239 };
1240
1241 /*
1242  * The parsefile structure pointed to by the global variable parsefile
1243  * contains information about the current file being read.
1244  */
1245 struct parsefile {
1246         struct parsefile *prev; /* preceding file on stack */
1247         int linno;              /* current line */
1248         int pf_fd;              /* file descriptor (or -1 if string) */
1249         int left_in_line;       /* number of chars left in this line */
1250         int left_in_buffer;     /* number of chars left in this buffer past the line */
1251         char *next_to_pgetc;    /* next char in buffer */
1252         char *buf;              /* input buffer */
1253         struct strpush *strpush; /* for pushing strings at this level */
1254         struct strpush basestrpush; /* so pushing one is fast */
1255
1256         /* Remember last two characters for pungetc. */
1257         int lastc[2];
1258
1259         /* Number of outstanding calls to pungetc. */
1260         int unget;
1261 };
1262
1263 static struct parsefile basepf;        /* top level input file */
1264 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1265 static int startlinno;                 /* line # where last token started */
1266 static char *commandname;              /* currently executing command */
1267
1268
1269 /* ============ Message printing */
1270
1271 static void
1272 ash_vmsg(const char *msg, va_list ap)
1273 {
1274         fprintf(stderr, "%s: ", arg0);
1275         if (commandname) {
1276                 if (strcmp(arg0, commandname))
1277                         fprintf(stderr, "%s: ", commandname);
1278                 if (!iflag || g_parsefile->pf_fd > 0)
1279                         fprintf(stderr, "line %d: ", startlinno);
1280         }
1281         vfprintf(stderr, msg, ap);
1282         newline_and_flush(stderr);
1283 }
1284
1285 /*
1286  * Exverror is called to raise the error exception.  If the second argument
1287  * is not NULL then error prints an error message using printf style
1288  * formatting.  It then raises the error exception.
1289  */
1290 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1291 static void
1292 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1293 {
1294 #if DEBUG
1295         if (msg) {
1296                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1297                 TRACEV((msg, ap));
1298         } else
1299                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1300         if (msg)
1301 #endif
1302                 ash_vmsg(msg, ap);
1303
1304         flush_stdout_stderr();
1305         raise_exception(cond);
1306         /* NOTREACHED */
1307 }
1308
1309 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1310 static void
1311 ash_msg_and_raise_error(const char *msg, ...)
1312 {
1313         va_list ap;
1314
1315         exitstatus = 2;
1316
1317         va_start(ap, msg);
1318         ash_vmsg_and_raise(EXERROR, msg, ap);
1319         /* NOTREACHED */
1320         va_end(ap);
1321 }
1322
1323 /*
1324  * 'fmt' must be a string literal.
1325  */
1326 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1327
1328 static void raise_error_syntax(const char *) NORETURN;
1329 static void
1330 raise_error_syntax(const char *msg)
1331 {
1332         ash_msg_and_raise_error("syntax error: %s", msg);
1333         /* NOTREACHED */
1334 }
1335
1336 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1337 static void
1338 ash_msg_and_raise(int cond, const char *msg, ...)
1339 {
1340         va_list ap;
1341
1342         va_start(ap, msg);
1343         ash_vmsg_and_raise(cond, msg, ap);
1344         /* NOTREACHED */
1345         va_end(ap);
1346 }
1347
1348 /*
1349  * error/warning routines for external builtins
1350  */
1351 static void
1352 ash_msg(const char *fmt, ...)
1353 {
1354         va_list ap;
1355
1356         va_start(ap, fmt);
1357         ash_vmsg(fmt, ap);
1358         va_end(ap);
1359 }
1360
1361 /*
1362  * Return a string describing an error.  The returned string may be a
1363  * pointer to a static buffer that will be overwritten on the next call.
1364  * Action describes the operation that got the error.
1365  */
1366 static const char *
1367 errmsg(int e, const char *em)
1368 {
1369         if (e == ENOENT || e == ENOTDIR) {
1370                 return em;
1371         }
1372         return strerror(e);
1373 }
1374
1375
1376 /* ============ Memory allocation */
1377
1378 #if 0
1379 /* I consider these wrappers nearly useless:
1380  * ok, they return you to nearest exception handler, but
1381  * how much memory do you leak in the process, making
1382  * memory starvation worse?
1383  */
1384 static void *
1385 ckrealloc(void * p, size_t nbytes)
1386 {
1387         p = realloc(p, nbytes);
1388         if (!p)
1389                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1390         return p;
1391 }
1392
1393 static void *
1394 ckmalloc(size_t nbytes)
1395 {
1396         return ckrealloc(NULL, nbytes);
1397 }
1398
1399 static void *
1400 ckzalloc(size_t nbytes)
1401 {
1402         return memset(ckmalloc(nbytes), 0, nbytes);
1403 }
1404
1405 static char *
1406 ckstrdup(const char *s)
1407 {
1408         char *p = strdup(s);
1409         if (!p)
1410                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1411         return p;
1412 }
1413 #else
1414 /* Using bbox equivalents. They exit if out of memory */
1415 # define ckrealloc xrealloc
1416 # define ckmalloc  xmalloc
1417 # define ckzalloc  xzalloc
1418 # define ckstrdup  xstrdup
1419 #endif
1420
1421 /*
1422  * It appears that grabstackstr() will barf with such alignments
1423  * because stalloc() will return a string allocated in a new stackblock.
1424  */
1425 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1426 enum {
1427         /* Most machines require the value returned from malloc to be aligned
1428          * in some way.  The following macro will get this right
1429          * on many machines.  */
1430         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1431         /* Minimum size of a block */
1432         MINSIZE = SHELL_ALIGN(504),
1433 };
1434
1435 struct stack_block {
1436         struct stack_block *prev;
1437         char space[MINSIZE];
1438 };
1439
1440 struct stackmark {
1441         struct stack_block *stackp;
1442         char *stacknxt;
1443         size_t stacknleft;
1444 };
1445
1446
1447 struct globals_memstack {
1448         struct stack_block *g_stackp; // = &stackbase;
1449         char *g_stacknxt; // = stackbase.space;
1450         char *sstrend; // = stackbase.space + MINSIZE;
1451         size_t g_stacknleft; // = MINSIZE;
1452         struct stack_block stackbase;
1453 };
1454 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1455 #define G_memstack (*ash_ptr_to_globals_memstack)
1456 #define g_stackp     (G_memstack.g_stackp    )
1457 #define g_stacknxt   (G_memstack.g_stacknxt  )
1458 #define sstrend      (G_memstack.sstrend     )
1459 #define g_stacknleft (G_memstack.g_stacknleft)
1460 #define stackbase    (G_memstack.stackbase   )
1461 #define INIT_G_memstack() do { \
1462         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1463         barrier(); \
1464         g_stackp = &stackbase; \
1465         g_stacknxt = stackbase.space; \
1466         g_stacknleft = MINSIZE; \
1467         sstrend = stackbase.space + MINSIZE; \
1468 } while (0)
1469
1470
1471 #define stackblock()     ((void *)g_stacknxt)
1472 #define stackblocksize() g_stacknleft
1473
1474 /*
1475  * Parse trees for commands are allocated in lifo order, so we use a stack
1476  * to make this more efficient, and also to avoid all sorts of exception
1477  * handling code to handle interrupts in the middle of a parse.
1478  *
1479  * The size 504 was chosen because the Ultrix malloc handles that size
1480  * well.
1481  */
1482 static void *
1483 stalloc(size_t nbytes)
1484 {
1485         char *p;
1486         size_t aligned;
1487
1488         aligned = SHELL_ALIGN(nbytes);
1489         if (aligned > g_stacknleft) {
1490                 size_t len;
1491                 size_t blocksize;
1492                 struct stack_block *sp;
1493
1494                 blocksize = aligned;
1495                 if (blocksize < MINSIZE)
1496                         blocksize = MINSIZE;
1497                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1498                 if (len < blocksize)
1499                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1500                 INT_OFF;
1501                 sp = ckmalloc(len);
1502                 sp->prev = g_stackp;
1503                 g_stacknxt = sp->space;
1504                 g_stacknleft = blocksize;
1505                 sstrend = g_stacknxt + blocksize;
1506                 g_stackp = sp;
1507                 INT_ON;
1508         }
1509         p = g_stacknxt;
1510         g_stacknxt += aligned;
1511         g_stacknleft -= aligned;
1512         return p;
1513 }
1514
1515 static void *
1516 stzalloc(size_t nbytes)
1517 {
1518         return memset(stalloc(nbytes), 0, nbytes);
1519 }
1520
1521 static void
1522 stunalloc(void *p)
1523 {
1524 #if DEBUG
1525         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1526                 write(STDERR_FILENO, "stunalloc\n", 10);
1527                 abort();
1528         }
1529 #endif
1530         g_stacknleft += g_stacknxt - (char *)p;
1531         g_stacknxt = p;
1532 }
1533
1534 /*
1535  * Like strdup but works with the ash stack.
1536  */
1537 static char *
1538 sstrdup(const char *p)
1539 {
1540         size_t len = strlen(p) + 1;
1541         return memcpy(stalloc(len), p, len);
1542 }
1543
1544 static ALWAYS_INLINE void
1545 grabstackblock(size_t len)
1546 {
1547         stalloc(len);
1548 }
1549
1550 static void
1551 pushstackmark(struct stackmark *mark, size_t len)
1552 {
1553         mark->stackp = g_stackp;
1554         mark->stacknxt = g_stacknxt;
1555         mark->stacknleft = g_stacknleft;
1556         grabstackblock(len);
1557 }
1558
1559 static void
1560 setstackmark(struct stackmark *mark)
1561 {
1562         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1563 }
1564
1565 static void
1566 popstackmark(struct stackmark *mark)
1567 {
1568         struct stack_block *sp;
1569
1570         if (!mark->stackp)
1571                 return;
1572
1573         INT_OFF;
1574         while (g_stackp != mark->stackp) {
1575                 sp = g_stackp;
1576                 g_stackp = sp->prev;
1577                 free(sp);
1578         }
1579         g_stacknxt = mark->stacknxt;
1580         g_stacknleft = mark->stacknleft;
1581         sstrend = mark->stacknxt + mark->stacknleft;
1582         INT_ON;
1583 }
1584
1585 /*
1586  * When the parser reads in a string, it wants to stick the string on the
1587  * stack and only adjust the stack pointer when it knows how big the
1588  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1589  * of space on top of the stack and stackblocklen returns the length of
1590  * this block.  Growstackblock will grow this space by at least one byte,
1591  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1592  * part of the block that has been used.
1593  */
1594 static void
1595 growstackblock(void)
1596 {
1597         size_t newlen;
1598
1599         newlen = g_stacknleft * 2;
1600         if (newlen < g_stacknleft)
1601                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1602         if (newlen < 128)
1603                 newlen += 128;
1604
1605         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1606                 struct stack_block *sp;
1607                 struct stack_block *prevstackp;
1608                 size_t grosslen;
1609
1610                 INT_OFF;
1611                 sp = g_stackp;
1612                 prevstackp = sp->prev;
1613                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1614                 sp = ckrealloc(sp, grosslen);
1615                 sp->prev = prevstackp;
1616                 g_stackp = sp;
1617                 g_stacknxt = sp->space;
1618                 g_stacknleft = newlen;
1619                 sstrend = sp->space + newlen;
1620                 INT_ON;
1621         } else {
1622                 char *oldspace = g_stacknxt;
1623                 size_t oldlen = g_stacknleft;
1624                 char *p = stalloc(newlen);
1625
1626                 /* free the space we just allocated */
1627                 g_stacknxt = memcpy(p, oldspace, oldlen);
1628                 g_stacknleft += newlen;
1629         }
1630 }
1631
1632 /*
1633  * The following routines are somewhat easier to use than the above.
1634  * The user declares a variable of type STACKSTR, which may be declared
1635  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1636  * the user uses the macro STPUTC to add characters to the string.  In
1637  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1638  * grown as necessary.  When the user is done, she can just leave the
1639  * string there and refer to it using stackblock().  Or she can allocate
1640  * the space for it using grabstackstr().  If it is necessary to allow
1641  * someone else to use the stack temporarily and then continue to grow
1642  * the string, the user should use grabstack to allocate the space, and
1643  * then call ungrabstr(p) to return to the previous mode of operation.
1644  *
1645  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1646  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1647  * is space for at least one character.
1648  */
1649 static void *
1650 growstackstr(void)
1651 {
1652         size_t len = stackblocksize();
1653         growstackblock();
1654         return (char *)stackblock() + len;
1655 }
1656
1657 /*
1658  * Called from CHECKSTRSPACE.
1659  */
1660 static char *
1661 makestrspace(size_t newlen, char *p)
1662 {
1663         size_t len = p - g_stacknxt;
1664         size_t size;
1665
1666         for (;;) {
1667                 size_t nleft;
1668
1669                 size = stackblocksize();
1670                 nleft = size - len;
1671                 if (nleft >= newlen)
1672                         break;
1673                 growstackblock();
1674         }
1675         return (char *)stackblock() + len;
1676 }
1677
1678 static char *
1679 stack_nputstr(const char *s, size_t n, char *p)
1680 {
1681         p = makestrspace(n, p);
1682         p = (char *)mempcpy(p, s, n);
1683         return p;
1684 }
1685
1686 static char *
1687 stack_putstr(const char *s, char *p)
1688 {
1689         return stack_nputstr(s, strlen(s), p);
1690 }
1691
1692 static char *
1693 _STPUTC(int c, char *p)
1694 {
1695         if (p == sstrend)
1696                 p = growstackstr();
1697         *p++ = c;
1698         return p;
1699 }
1700
1701 #define STARTSTACKSTR(p)        ((p) = stackblock())
1702 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1703 #define CHECKSTRSPACE(n, p) do { \
1704         char *q = (p); \
1705         size_t l = (n); \
1706         size_t m = sstrend - q; \
1707         if (l > m) \
1708                 (p) = makestrspace(l, q); \
1709 } while (0)
1710 #define USTPUTC(c, p)           (*(p)++ = (c))
1711 #define STACKSTRNUL(p) do { \
1712         if ((p) == sstrend) \
1713                 (p) = growstackstr(); \
1714         *(p) = '\0'; \
1715 } while (0)
1716 #define STUNPUTC(p)             (--(p))
1717 #define STTOPC(p)               ((p)[-1])
1718 #define STADJUST(amount, p)     ((p) += (amount))
1719
1720 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1721 #define ungrabstackstr(s, p)    stunalloc(s)
1722 #define stackstrend()           ((void *)sstrend)
1723
1724
1725 /* ============ String helpers */
1726
1727 /*
1728  * prefix -- see if pfx is a prefix of string.
1729  */
1730 static char *
1731 prefix(const char *string, const char *pfx)
1732 {
1733         while (*pfx) {
1734                 if (*pfx++ != *string++)
1735                         return NULL;
1736         }
1737         return (char *) string;
1738 }
1739
1740 /*
1741  * Check for a valid number.  This should be elsewhere.
1742  */
1743 static int
1744 is_number(const char *p)
1745 {
1746         do {
1747                 if (!isdigit(*p))
1748                         return 0;
1749         } while (*++p != '\0');
1750         return 1;
1751 }
1752
1753 /*
1754  * Convert a string of digits to an integer, printing an error message on
1755  * failure.
1756  */
1757 static int
1758 number(const char *s)
1759 {
1760         if (!is_number(s))
1761                 ash_msg_and_raise_error(msg_illnum, s);
1762         return atoi(s);
1763 }
1764
1765 /*
1766  * Produce a single quoted string suitable as input to the shell.
1767  * The return string is allocated on the stack.
1768  */
1769 static char *
1770 single_quote(const char *s)
1771 {
1772         char *p;
1773
1774         STARTSTACKSTR(p);
1775
1776         do {
1777                 char *q;
1778                 size_t len;
1779
1780                 len = strchrnul(s, '\'') - s;
1781
1782                 q = p = makestrspace(len + 3, p);
1783
1784                 *q++ = '\'';
1785                 q = (char *)mempcpy(q, s, len);
1786                 *q++ = '\'';
1787                 s += len;
1788
1789                 STADJUST(q - p, p);
1790
1791                 if (*s != '\'')
1792                         break;
1793                 len = 0;
1794                 do len++; while (*++s == '\'');
1795
1796                 q = p = makestrspace(len + 3, p);
1797
1798                 *q++ = '"';
1799                 q = (char *)mempcpy(q, s - len, len);
1800                 *q++ = '"';
1801
1802                 STADJUST(q - p, p);
1803         } while (*s);
1804
1805         USTPUTC('\0', p);
1806
1807         return stackblock();
1808 }
1809
1810 /*
1811  * Produce a possibly single quoted string suitable as input to the shell.
1812  * If quoting was done, the return string is allocated on the stack,
1813  * otherwise a pointer to the original string is returned.
1814  */
1815 static const char *
1816 maybe_single_quote(const char *s)
1817 {
1818         const char *p = s;
1819
1820         while (*p) {
1821                 /* Assuming ACSII */
1822                 /* quote ctrl_chars space !"#$%&'()* */
1823                 if (*p < '+')
1824                         goto need_quoting;
1825                 /* quote ;<=>? */
1826                 if (*p >= ';' && *p <= '?')
1827                         goto need_quoting;
1828                 /* quote `[\ */
1829                 if (*p == '`')
1830                         goto need_quoting;
1831                 if (*p == '[')
1832                         goto need_quoting;
1833                 if (*p == '\\')
1834                         goto need_quoting;
1835                 /* quote {|}~ DEL and high bytes */
1836                 if (*p > 'z')
1837                         goto need_quoting;
1838                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1839                 /* TODO: maybe avoid quoting % */
1840                 p++;
1841         }
1842         return s;
1843
1844  need_quoting:
1845         return single_quote(s);
1846 }
1847
1848
1849 /* ============ nextopt */
1850
1851 static char **argptr;                  /* argument list for builtin commands */
1852 static char *optionarg;                /* set by nextopt (like getopt) */
1853 static char *optptr;                   /* used by nextopt */
1854
1855 /*
1856  * XXX - should get rid of. Have all builtins use getopt(3).
1857  * The library getopt must have the BSD extension static variable
1858  * "optreset", otherwise it can't be used within the shell safely.
1859  *
1860  * Standard option processing (a la getopt) for builtin routines.
1861  * The only argument that is passed to nextopt is the option string;
1862  * the other arguments are unnecessary. It returns the character,
1863  * or '\0' on end of input.
1864  */
1865 static int
1866 nextopt(const char *optstring)
1867 {
1868         char *p;
1869         const char *q;
1870         char c;
1871
1872         p = optptr;
1873         if (p == NULL || *p == '\0') {
1874                 /* We ate entire "-param", take next one */
1875                 p = *argptr;
1876                 if (p == NULL)
1877                         return '\0';
1878                 if (*p != '-')
1879                         return '\0';
1880                 if (*++p == '\0') /* just "-" ? */
1881                         return '\0';
1882                 argptr++;
1883                 if (LONE_DASH(p)) /* "--" ? */
1884                         return '\0';
1885                 /* p => next "-param" */
1886         }
1887         /* p => some option char in the middle of a "-param" */
1888         c = *p++;
1889         for (q = optstring; *q != c;) {
1890                 if (*q == '\0')
1891                         ash_msg_and_raise_error("illegal option -%c", c);
1892                 if (*++q == ':')
1893                         q++;
1894         }
1895         if (*++q == ':') {
1896                 if (*p == '\0') {
1897                         p = *argptr++;
1898                         if (p == NULL)
1899                                 ash_msg_and_raise_error("no arg for -%c option", c);
1900                 }
1901                 optionarg = p;
1902                 p = NULL;
1903         }
1904         optptr = p;
1905         return c;
1906 }
1907
1908
1909 /* ============ Shell variables */
1910
1911 struct shparam {
1912         int nparam;             /* # of positional parameters (without $0) */
1913 #if ENABLE_ASH_GETOPTS
1914         int optind;             /* next parameter to be processed by getopts */
1915         int optoff;             /* used by getopts */
1916 #endif
1917         unsigned char malloced; /* if parameter list dynamically allocated */
1918         char **p;               /* parameter list */
1919 };
1920
1921 /*
1922  * Free the list of positional parameters.
1923  */
1924 static void
1925 freeparam(volatile struct shparam *param)
1926 {
1927         if (param->malloced) {
1928                 char **ap, **ap1;
1929                 ap = ap1 = param->p;
1930                 while (*ap)
1931                         free(*ap++);
1932                 free(ap1);
1933         }
1934 }
1935
1936 #if ENABLE_ASH_GETOPTS
1937 static void FAST_FUNC getoptsreset(const char *value);
1938 #endif
1939
1940 struct var {
1941         struct var *next;               /* next entry in hash list */
1942         int flags;                      /* flags are defined above */
1943         const char *var_text;           /* name=value */
1944         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1945                                         /* the variable gets set/unset */
1946 };
1947
1948 struct localvar {
1949         struct localvar *next;          /* next local variable in list */
1950         struct var *vp;                 /* the variable that was made local */
1951         int flags;                      /* saved flags */
1952         const char *text;               /* saved text */
1953 };
1954
1955 /* flags */
1956 #define VEXPORT         0x01    /* variable is exported */
1957 #define VREADONLY       0x02    /* variable cannot be modified */
1958 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1959 #define VTEXTFIXED      0x08    /* text is statically allocated */
1960 #define VSTACK          0x10    /* text is allocated on the stack */
1961 #define VUNSET          0x20    /* the variable is not set */
1962 #define VNOFUNC         0x40    /* don't call the callback function */
1963 #define VNOSET          0x80    /* do not set variable - just readonly test */
1964 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1965 #if ENABLE_ASH_RANDOM_SUPPORT
1966 # define VDYNAMIC       0x200   /* dynamic variable */
1967 #else
1968 # define VDYNAMIC       0
1969 #endif
1970
1971
1972 /* Need to be before varinit_data[] */
1973 #if ENABLE_LOCALE_SUPPORT
1974 static void FAST_FUNC
1975 change_lc_all(const char *value)
1976 {
1977         if (value && *value != '\0')
1978                 setlocale(LC_ALL, value);
1979 }
1980 static void FAST_FUNC
1981 change_lc_ctype(const char *value)
1982 {
1983         if (value && *value != '\0')
1984                 setlocale(LC_CTYPE, value);
1985 }
1986 #endif
1987 #if ENABLE_ASH_MAIL
1988 static void chkmail(void);
1989 static void changemail(const char *var_value) FAST_FUNC;
1990 #else
1991 # define chkmail()  ((void)0)
1992 #endif
1993 static void changepath(const char *) FAST_FUNC;
1994 #if ENABLE_ASH_RANDOM_SUPPORT
1995 static void change_random(const char *) FAST_FUNC;
1996 #endif
1997
1998 static const struct {
1999         int flags;
2000         const char *var_text;
2001         void (*var_func)(const char *) FAST_FUNC;
2002 } varinit_data[] = {
2003         /*
2004          * Note: VEXPORT would not work correctly here for NOFORK applets:
2005          * some environment strings may be constant.
2006          */
2007         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2008 #if ENABLE_ASH_MAIL
2009         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2010         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2011 #endif
2012         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2013         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2014         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2015         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2016 #if ENABLE_ASH_GETOPTS
2017         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2018 #endif
2019 #if ENABLE_ASH_RANDOM_SUPPORT
2020         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2021 #endif
2022 #if ENABLE_LOCALE_SUPPORT
2023         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2024         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2025 #endif
2026 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2027         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2028 #endif
2029 };
2030
2031 struct redirtab;
2032
2033 struct globals_var {
2034         struct shparam shellparam;      /* $@ current positional parameters */
2035         struct redirtab *redirlist;
2036         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2037         struct var *vartab[VTABSIZE];
2038         struct var varinit[ARRAY_SIZE(varinit_data)];
2039 };
2040 extern struct globals_var *const ash_ptr_to_globals_var;
2041 #define G_var (*ash_ptr_to_globals_var)
2042 #define shellparam    (G_var.shellparam   )
2043 //#define redirlist     (G_var.redirlist    )
2044 #define preverrout_fd (G_var.preverrout_fd)
2045 #define vartab        (G_var.vartab       )
2046 #define varinit       (G_var.varinit      )
2047 #define INIT_G_var() do { \
2048         unsigned i; \
2049         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2050         barrier(); \
2051         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2052                 varinit[i].flags    = varinit_data[i].flags; \
2053                 varinit[i].var_text = varinit_data[i].var_text; \
2054                 varinit[i].var_func = varinit_data[i].var_func; \
2055         } \
2056 } while (0)
2057
2058 #define vifs      varinit[0]
2059 #if ENABLE_ASH_MAIL
2060 # define vmail    (&vifs)[1]
2061 # define vmpath   (&vmail)[1]
2062 # define vpath    (&vmpath)[1]
2063 #else
2064 # define vpath    (&vifs)[1]
2065 #endif
2066 #define vps1      (&vpath)[1]
2067 #define vps2      (&vps1)[1]
2068 #define vps4      (&vps2)[1]
2069 #if ENABLE_ASH_GETOPTS
2070 # define voptind  (&vps4)[1]
2071 # if ENABLE_ASH_RANDOM_SUPPORT
2072 #  define vrandom (&voptind)[1]
2073 # endif
2074 #else
2075 # if ENABLE_ASH_RANDOM_SUPPORT
2076 #  define vrandom (&vps4)[1]
2077 # endif
2078 #endif
2079
2080 /*
2081  * The following macros access the values of the above variables.
2082  * They have to skip over the name.  They return the null string
2083  * for unset variables.
2084  */
2085 #define ifsval()        (vifs.var_text + 4)
2086 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2087 #if ENABLE_ASH_MAIL
2088 # define mailval()      (vmail.var_text + 5)
2089 # define mpathval()     (vmpath.var_text + 9)
2090 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2091 #endif
2092 #define pathval()       (vpath.var_text + 5)
2093 #define ps1val()        (vps1.var_text + 4)
2094 #define ps2val()        (vps2.var_text + 4)
2095 #define ps4val()        (vps4.var_text + 4)
2096 #if ENABLE_ASH_GETOPTS
2097 # define optindval()    (voptind.var_text + 7)
2098 #endif
2099
2100 #if ENABLE_ASH_GETOPTS
2101 static void FAST_FUNC
2102 getoptsreset(const char *value)
2103 {
2104         shellparam.optind = 1;
2105         if (is_number(value))
2106                 shellparam.optind = number(value) ?: 1;
2107         shellparam.optoff = -1;
2108 }
2109 #endif
2110
2111 /*
2112  * Compares two strings up to the first = or '\0'.  The first
2113  * string must be terminated by '='; the second may be terminated by
2114  * either '=' or '\0'.
2115  */
2116 static int
2117 varcmp(const char *p, const char *q)
2118 {
2119         int c, d;
2120
2121         while ((c = *p) == (d = *q)) {
2122                 if (c == '\0' || c == '=')
2123                         goto out;
2124                 p++;
2125                 q++;
2126         }
2127         if (c == '=')
2128                 c = '\0';
2129         if (d == '=')
2130                 d = '\0';
2131  out:
2132         return c - d;
2133 }
2134
2135 /*
2136  * Find the appropriate entry in the hash table from the name.
2137  */
2138 static struct var **
2139 hashvar(const char *p)
2140 {
2141         unsigned hashval;
2142
2143         hashval = ((unsigned char) *p) << 4;
2144         while (*p && *p != '=')
2145                 hashval += (unsigned char) *p++;
2146         return &vartab[hashval % VTABSIZE];
2147 }
2148
2149 static int
2150 vpcmp(const void *a, const void *b)
2151 {
2152         return varcmp(*(const char **)a, *(const char **)b);
2153 }
2154
2155 /*
2156  * This routine initializes the builtin variables.
2157  */
2158 static void
2159 initvar(void)
2160 {
2161         struct var *vp;
2162         struct var *end;
2163         struct var **vpp;
2164
2165         /*
2166          * PS1 depends on uid
2167          */
2168 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2169         vps1.var_text = "PS1=\\w \\$ ";
2170 #else
2171         if (!geteuid())
2172                 vps1.var_text = "PS1=# ";
2173 #endif
2174         vp = varinit;
2175         end = vp + ARRAY_SIZE(varinit);
2176         do {
2177                 vpp = hashvar(vp->var_text);
2178                 vp->next = *vpp;
2179                 *vpp = vp;
2180         } while (++vp < end);
2181 }
2182
2183 static struct var **
2184 findvar(struct var **vpp, const char *name)
2185 {
2186         for (; *vpp; vpp = &(*vpp)->next) {
2187                 if (varcmp((*vpp)->var_text, name) == 0) {
2188                         break;
2189                 }
2190         }
2191         return vpp;
2192 }
2193
2194 /*
2195  * Find the value of a variable.  Returns NULL if not set.
2196  */
2197 static const char* FAST_FUNC
2198 lookupvar(const char *name)
2199 {
2200         struct var *v;
2201
2202         v = *findvar(hashvar(name), name);
2203         if (v) {
2204 #if ENABLE_ASH_RANDOM_SUPPORT
2205         /*
2206          * Dynamic variables are implemented roughly the same way they are
2207          * in bash. Namely, they're "special" so long as they aren't unset.
2208          * As soon as they're unset, they're no longer dynamic, and dynamic
2209          * lookup will no longer happen at that point. -- PFM.
2210          */
2211                 if (v->flags & VDYNAMIC)
2212                         v->var_func(NULL);
2213 #endif
2214                 if (!(v->flags & VUNSET))
2215                         return var_end(v->var_text);
2216         }
2217         return NULL;
2218 }
2219
2220 #if ENABLE_UNICODE_SUPPORT
2221 static void
2222 reinit_unicode_for_ash(void)
2223 {
2224         /* Unicode support should be activated even if LANG is set
2225          * _during_ shell execution, not only if it was set when
2226          * shell was started. Therefore, re-check LANG every time:
2227          */
2228         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2229          || ENABLE_UNICODE_USING_LOCALE
2230         ) {
2231                 const char *s = lookupvar("LC_ALL");
2232                 if (!s) s = lookupvar("LC_CTYPE");
2233                 if (!s) s = lookupvar("LANG");
2234                 reinit_unicode(s);
2235         }
2236 }
2237 #else
2238 # define reinit_unicode_for_ash() ((void)0)
2239 #endif
2240
2241 /*
2242  * Search the environment of a builtin command.
2243  */
2244 static ALWAYS_INLINE const char *
2245 bltinlookup(const char *name)
2246 {
2247         return lookupvar(name);
2248 }
2249
2250 /*
2251  * Same as setvar except that the variable and value are passed in
2252  * the first argument as name=value.  Since the first argument will
2253  * be actually stored in the table, it should not be a string that
2254  * will go away.
2255  * Called with interrupts off.
2256  */
2257 static struct var *
2258 setvareq(char *s, int flags)
2259 {
2260         struct var *vp, **vpp;
2261
2262         vpp = hashvar(s);
2263         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2264         vpp = findvar(vpp, s);
2265         vp = *vpp;
2266         if (vp) {
2267                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2268                         const char *n;
2269
2270                         if (flags & VNOSAVE)
2271                                 free(s);
2272                         n = vp->var_text;
2273                         exitstatus = 1;
2274                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2275                 }
2276
2277                 if (flags & VNOSET)
2278                         goto out;
2279
2280                 if (vp->var_func && !(flags & VNOFUNC))
2281                         vp->var_func(var_end(s));
2282
2283                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2284                         free((char*)vp->var_text);
2285
2286                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2287                         *vpp = vp->next;
2288                         free(vp);
2289  out_free:
2290                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2291                                 free(s);
2292                         goto out;
2293                 }
2294
2295                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2296         } else {
2297                 /* variable s is not found */
2298                 if (flags & VNOSET)
2299                         goto out;
2300                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2301                         goto out_free;
2302                 vp = ckzalloc(sizeof(*vp));
2303                 vp->next = *vpp;
2304                 /*vp->func = NULL; - ckzalloc did it */
2305                 *vpp = vp;
2306         }
2307         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2308                 s = ckstrdup(s);
2309         vp->var_text = s;
2310         vp->flags = flags;
2311
2312  out:
2313         return vp;
2314 }
2315
2316 /*
2317  * Set the value of a variable.  The flags argument is ored with the
2318  * flags of the variable.  If val is NULL, the variable is unset.
2319  */
2320 static struct var *
2321 setvar(const char *name, const char *val, int flags)
2322 {
2323         const char *q;
2324         char *p;
2325         char *nameeq;
2326         size_t namelen;
2327         size_t vallen;
2328         struct var *vp;
2329
2330         q = endofname(name);
2331         p = strchrnul(q, '=');
2332         namelen = p - name;
2333         if (!namelen || p != q)
2334                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2335         vallen = 0;
2336         if (val == NULL) {
2337                 flags |= VUNSET;
2338         } else {
2339                 vallen = strlen(val);
2340         }
2341
2342         INT_OFF;
2343         nameeq = ckmalloc(namelen + vallen + 2);
2344         p = mempcpy(nameeq, name, namelen);
2345         if (val) {
2346                 *p++ = '=';
2347                 p = mempcpy(p, val, vallen);
2348         }
2349         *p = '\0';
2350         vp = setvareq(nameeq, flags | VNOSAVE);
2351         INT_ON;
2352
2353         return vp;
2354 }
2355
2356 static void FAST_FUNC
2357 setvar0(const char *name, const char *val)
2358 {
2359         setvar(name, val, 0);
2360 }
2361
2362 /*
2363  * Unset the specified variable.
2364  */
2365 static void
2366 unsetvar(const char *s)
2367 {
2368         setvar(s, NULL, 0);
2369 }
2370
2371 /*
2372  * Process a linked list of variable assignments.
2373  */
2374 static void
2375 listsetvar(struct strlist *list_set_var, int flags)
2376 {
2377         struct strlist *lp = list_set_var;
2378
2379         if (!lp)
2380                 return;
2381         INT_OFF;
2382         do {
2383                 setvareq(lp->text, flags);
2384                 lp = lp->next;
2385         } while (lp);
2386         INT_ON;
2387 }
2388
2389 /*
2390  * Generate a list of variables satisfying the given conditions.
2391  */
2392 #if !ENABLE_FEATURE_SH_NOFORK
2393 # define listvars(on, off, lp, end) listvars(on, off, end)
2394 #endif
2395 static char **
2396 listvars(int on, int off, struct strlist *lp, char ***end)
2397 {
2398         struct var **vpp;
2399         struct var *vp;
2400         char **ep;
2401         int mask;
2402
2403         STARTSTACKSTR(ep);
2404         vpp = vartab;
2405         mask = on | off;
2406         do {
2407                 for (vp = *vpp; vp; vp = vp->next) {
2408                         if ((vp->flags & mask) == on) {
2409 #if ENABLE_FEATURE_SH_NOFORK
2410                                 /* If variable with the same name is both
2411                                  * exported and temporarily set for a command:
2412                                  *  export ZVAR=5
2413                                  *  ZVAR=6 printenv
2414                                  * then "ZVAR=6" will be both in vartab and
2415                                  * lp lists. Do not pass it twice to printenv.
2416                                  */
2417                                 struct strlist *lp1 = lp;
2418                                 while (lp1) {
2419                                         if (strcmp(lp1->text, vp->var_text) == 0)
2420                                                 goto skip;
2421                                         lp1 = lp1->next;
2422                                 }
2423 #endif
2424                                 if (ep == stackstrend())
2425                                         ep = growstackstr();
2426                                 *ep++ = (char*)vp->var_text;
2427 #if ENABLE_FEATURE_SH_NOFORK
2428  skip: ;
2429 #endif
2430                         }
2431                 }
2432         } while (++vpp < vartab + VTABSIZE);
2433
2434 #if ENABLE_FEATURE_SH_NOFORK
2435         while (lp) {
2436                 if (ep == stackstrend())
2437                         ep = growstackstr();
2438                 *ep++ = lp->text;
2439                 lp = lp->next;
2440         }
2441 #endif
2442
2443         if (ep == stackstrend())
2444                 ep = growstackstr();
2445         if (end)
2446                 *end = ep;
2447         *ep++ = NULL;
2448         return grabstackstr(ep);
2449 }
2450
2451
2452 /* ============ Path search helper
2453  *
2454  * The variable path (passed by reference) should be set to the start
2455  * of the path before the first call; path_advance will update
2456  * this value as it proceeds.  Successive calls to path_advance will return
2457  * the possible path expansions in sequence.  If an option (indicated by
2458  * a percent sign) appears in the path entry then the global variable
2459  * pathopt will be set to point to it; otherwise pathopt will be set to
2460  * NULL.
2461  */
2462 static const char *pathopt;     /* set by path_advance */
2463
2464 static char *
2465 path_advance(const char **path, const char *name)
2466 {
2467         const char *p;
2468         char *q;
2469         const char *start;
2470         size_t len;
2471
2472         if (*path == NULL)
2473                 return NULL;
2474         start = *path;
2475         for (p = start; *p && *p != ':' && *p != '%'; p++)
2476                 continue;
2477         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2478         while (stackblocksize() < len)
2479                 growstackblock();
2480         q = stackblock();
2481         if (p != start) {
2482                 q = mempcpy(q, start, p - start);
2483                 *q++ = '/';
2484         }
2485         strcpy(q, name);
2486         pathopt = NULL;
2487         if (*p == '%') {
2488                 pathopt = ++p;
2489                 while (*p && *p != ':')
2490                         p++;
2491         }
2492         if (*p == ':')
2493                 *path = p + 1;
2494         else
2495                 *path = NULL;
2496         return stalloc(len);
2497 }
2498
2499
2500 /* ============ Prompt */
2501
2502 static smallint doprompt;                   /* if set, prompt the user */
2503 static smallint needprompt;                 /* true if interactive and at start of line */
2504
2505 #if ENABLE_FEATURE_EDITING
2506 static line_input_t *line_input_state;
2507 static const char *cmdedit_prompt;
2508 static void
2509 putprompt(const char *s)
2510 {
2511         if (ENABLE_ASH_EXPAND_PRMT) {
2512                 free((char*)cmdedit_prompt);
2513                 cmdedit_prompt = ckstrdup(s);
2514                 return;
2515         }
2516         cmdedit_prompt = s;
2517 }
2518 #else
2519 static void
2520 putprompt(const char *s)
2521 {
2522         out2str(s);
2523 }
2524 #endif
2525
2526 /* expandstr() needs parsing machinery, so it is far away ahead... */
2527 static const char *expandstr(const char *ps, int syntax_type);
2528 /* Values for syntax param */
2529 #define BASESYNTAX 0    /* not in quotes */
2530 #define DQSYNTAX   1    /* in double quotes */
2531 #define SQSYNTAX   2    /* in single quotes */
2532 #define ARISYNTAX  3    /* in arithmetic */
2533 #if ENABLE_ASH_EXPAND_PRMT
2534 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2535 #endif
2536 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2537
2538 /*
2539  * called by editline -- any expansions to the prompt should be added here.
2540  */
2541 static void
2542 setprompt_if(smallint do_set, int whichprompt)
2543 {
2544         const char *prompt;
2545         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2546
2547         if (!do_set)
2548                 return;
2549
2550         needprompt = 0;
2551
2552         switch (whichprompt) {
2553         case 1:
2554                 prompt = ps1val();
2555                 break;
2556         case 2:
2557                 prompt = ps2val();
2558                 break;
2559         default:                        /* 0 */
2560                 prompt = nullstr;
2561         }
2562 #if ENABLE_ASH_EXPAND_PRMT
2563         pushstackmark(&smark, stackblocksize());
2564         putprompt(expandstr(prompt, PSSYNTAX));
2565         popstackmark(&smark);
2566 #else
2567         putprompt(prompt);
2568 #endif
2569 }
2570
2571
2572 /* ============ The cd and pwd commands */
2573
2574 #define CD_PHYSICAL 1
2575 #define CD_PRINT 2
2576
2577 static int
2578 cdopt(void)
2579 {
2580         int flags = 0;
2581         int i, j;
2582
2583         j = 'L';
2584         while ((i = nextopt("LP")) != '\0') {
2585                 if (i != j) {
2586                         flags ^= CD_PHYSICAL;
2587                         j = i;
2588                 }
2589         }
2590
2591         return flags;
2592 }
2593
2594 /*
2595  * Update curdir (the name of the current directory) in response to a
2596  * cd command.
2597  */
2598 static const char *
2599 updatepwd(const char *dir)
2600 {
2601         char *new;
2602         char *p;
2603         char *cdcomppath;
2604         const char *lim;
2605
2606         cdcomppath = sstrdup(dir);
2607         STARTSTACKSTR(new);
2608         if (*dir != '/') {
2609                 if (curdir == nullstr)
2610                         return 0;
2611                 new = stack_putstr(curdir, new);
2612         }
2613         new = makestrspace(strlen(dir) + 2, new);
2614         lim = (char *)stackblock() + 1;
2615         if (*dir != '/') {
2616                 if (new[-1] != '/')
2617                         USTPUTC('/', new);
2618                 if (new > lim && *lim == '/')
2619                         lim++;
2620         } else {
2621                 USTPUTC('/', new);
2622                 cdcomppath++;
2623                 if (dir[1] == '/' && dir[2] != '/') {
2624                         USTPUTC('/', new);
2625                         cdcomppath++;
2626                         lim++;
2627                 }
2628         }
2629         p = strtok(cdcomppath, "/");
2630         while (p) {
2631                 switch (*p) {
2632                 case '.':
2633                         if (p[1] == '.' && p[2] == '\0') {
2634                                 while (new > lim) {
2635                                         STUNPUTC(new);
2636                                         if (new[-1] == '/')
2637                                                 break;
2638                                 }
2639                                 break;
2640                         }
2641                         if (p[1] == '\0')
2642                                 break;
2643                         /* fall through */
2644                 default:
2645                         new = stack_putstr(p, new);
2646                         USTPUTC('/', new);
2647                 }
2648                 p = strtok(NULL, "/");
2649         }
2650         if (new > lim)
2651                 STUNPUTC(new);
2652         *new = 0;
2653         return stackblock();
2654 }
2655
2656 /*
2657  * Find out what the current directory is. If we already know the current
2658  * directory, this routine returns immediately.
2659  */
2660 static char *
2661 getpwd(void)
2662 {
2663         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2664         return dir ? dir : nullstr;
2665 }
2666
2667 static void
2668 setpwd(const char *val, int setold)
2669 {
2670         char *oldcur, *dir;
2671
2672         oldcur = dir = curdir;
2673
2674         if (setold) {
2675                 setvar("OLDPWD", oldcur, VEXPORT);
2676         }
2677         INT_OFF;
2678         if (physdir != nullstr) {
2679                 if (physdir != oldcur)
2680                         free(physdir);
2681                 physdir = nullstr;
2682         }
2683         if (oldcur == val || !val) {
2684                 char *s = getpwd();
2685                 physdir = s;
2686                 if (!val)
2687                         dir = s;
2688         } else
2689                 dir = ckstrdup(val);
2690         if (oldcur != dir && oldcur != nullstr) {
2691                 free(oldcur);
2692         }
2693         curdir = dir;
2694         INT_ON;
2695         setvar("PWD", dir, VEXPORT);
2696 }
2697
2698 static void hashcd(void);
2699
2700 /*
2701  * Actually do the chdir.  We also call hashcd to let other routines
2702  * know that the current directory has changed.
2703  */
2704 static int
2705 docd(const char *dest, int flags)
2706 {
2707         const char *dir = NULL;
2708         int err;
2709
2710         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2711
2712         INT_OFF;
2713         if (!(flags & CD_PHYSICAL)) {
2714                 dir = updatepwd(dest);
2715                 if (dir)
2716                         dest = dir;
2717         }
2718         err = chdir(dest);
2719         if (err)
2720                 goto out;
2721         setpwd(dir, 1);
2722         hashcd();
2723  out:
2724         INT_ON;
2725         return err;
2726 }
2727
2728 static int FAST_FUNC
2729 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2730 {
2731         const char *dest;
2732         const char *path;
2733         const char *p;
2734         char c;
2735         struct stat statb;
2736         int flags;
2737
2738         flags = cdopt();
2739         dest = *argptr;
2740         if (!dest)
2741                 dest = bltinlookup("HOME");
2742         else if (LONE_DASH(dest)) {
2743                 dest = bltinlookup("OLDPWD");
2744                 flags |= CD_PRINT;
2745         }
2746         if (!dest)
2747                 dest = nullstr;
2748         if (*dest == '/')
2749                 goto step6;
2750         if (*dest == '.') {
2751                 c = dest[1];
2752  dotdot:
2753                 switch (c) {
2754                 case '\0':
2755                 case '/':
2756                         goto step6;
2757                 case '.':
2758                         c = dest[2];
2759                         if (c != '.')
2760                                 goto dotdot;
2761                 }
2762         }
2763         if (!*dest)
2764                 dest = ".";
2765         path = bltinlookup("CDPATH");
2766         while (path) {
2767                 c = *path;
2768                 p = path_advance(&path, dest);
2769                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2770                         if (c && c != ':')
2771                                 flags |= CD_PRINT;
2772  docd:
2773                         if (!docd(p, flags))
2774                                 goto out;
2775                         goto err;
2776                 }
2777         }
2778
2779  step6:
2780         p = dest;
2781         goto docd;
2782
2783  err:
2784         ash_msg_and_raise_perror("can't cd to %s", dest);
2785         /* NOTREACHED */
2786  out:
2787         if (flags & CD_PRINT)
2788                 out1fmt("%s\n", curdir);
2789         return 0;
2790 }
2791
2792 static int FAST_FUNC
2793 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2794 {
2795         int flags;
2796         const char *dir = curdir;
2797
2798         flags = cdopt();
2799         if (flags) {
2800                 if (physdir == nullstr)
2801                         setpwd(dir, 0);
2802                 dir = physdir;
2803         }
2804         out1fmt("%s\n", dir);
2805         return 0;
2806 }
2807
2808
2809 /* ============ ... */
2810
2811
2812 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2813
2814 /* Syntax classes */
2815 #define CWORD     0             /* character is nothing special */
2816 #define CNL       1             /* newline character */
2817 #define CBACK     2             /* a backslash character */
2818 #define CSQUOTE   3             /* single quote */
2819 #define CDQUOTE   4             /* double quote */
2820 #define CENDQUOTE 5             /* a terminating quote */
2821 #define CBQUOTE   6             /* backwards single quote */
2822 #define CVAR      7             /* a dollar sign */
2823 #define CENDVAR   8             /* a '}' character */
2824 #define CLP       9             /* a left paren in arithmetic */
2825 #define CRP      10             /* a right paren in arithmetic */
2826 #define CENDFILE 11             /* end of file */
2827 #define CCTL     12             /* like CWORD, except it must be escaped */
2828 #define CSPCL    13             /* these terminate a word */
2829 #define CIGN     14             /* character should be ignored */
2830
2831 #define PEOF     256
2832 #if ENABLE_ASH_ALIAS
2833 # define PEOA    257
2834 #endif
2835
2836 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2837
2838 #if ENABLE_FEATURE_SH_MATH
2839 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2840 #else
2841 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2842 #endif
2843 static const uint16_t S_I_T[] ALIGN2 = {
2844 #if ENABLE_ASH_ALIAS
2845         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2846 #endif
2847         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2848         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2849         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2850         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2851         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2852         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2853         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2854         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2855         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2856         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2857         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2858 #if !USE_SIT_FUNCTION
2859         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2860         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2861         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2862 #endif
2863 #undef SIT_ITEM
2864 };
2865 /* Constants below must match table above */
2866 enum {
2867 #if ENABLE_ASH_ALIAS
2868         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2869 #endif
2870         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2871         CNL_CNL_CNL_CNL                    , /*  2 */
2872         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2873         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2874         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2875         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2876         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2877         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2878         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2879         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2880         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2881         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2882         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2883         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2884 };
2885
2886 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2887  * caller must ensure proper cast on it if c is *char_ptr!
2888  */
2889 #if USE_SIT_FUNCTION
2890
2891 static int
2892 SIT(int c, int syntax)
2893 {
2894         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2895         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2896         /*
2897          * This causes '/' to be prepended with CTLESC in dquoted string,
2898          * making "./file"* treated incorrectly because we feed
2899          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2900          * The "homegrown" glob implementation is okay with that,
2901          * but glibc one isn't. With '/' always treated as CWORD,
2902          * both work fine.
2903          */
2904 # if ENABLE_ASH_ALIAS
2905         static const uint8_t syntax_index_table[] ALIGN1 = {
2906                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2907                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2908                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2909                 11, 3                           /* "}~" */
2910         };
2911 # else
2912         static const uint8_t syntax_index_table[] ALIGN1 = {
2913                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2914                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2915                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2916                 10, 2                           /* "}~" */
2917         };
2918 # endif
2919         const char *s;
2920         int indx;
2921
2922         if (c == PEOF)
2923                 return CENDFILE;
2924 # if ENABLE_ASH_ALIAS
2925         if (c == PEOA)
2926                 indx = 0;
2927         else
2928 # endif
2929         {
2930                 /* Cast is purely for paranoia here,
2931                  * just in case someone passed signed char to us */
2932                 if ((unsigned char)c >= CTL_FIRST
2933                  && (unsigned char)c <= CTL_LAST
2934                 ) {
2935                         return CCTL;
2936                 }
2937                 s = strchrnul(spec_symbls, c);
2938                 if (*s == '\0')
2939                         return CWORD;
2940                 indx = syntax_index_table[s - spec_symbls];
2941         }
2942         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2943 }
2944
2945 #else   /* !USE_SIT_FUNCTION */
2946
2947 static const uint8_t syntax_index_table[] ALIGN1 = {
2948         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2949         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2950         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2951         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2952         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2953         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2954         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2955         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2956         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2957         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2958         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2959         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2960         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2961         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2962         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2963         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2964         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2965         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2966         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2967         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2968         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2969         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2970         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2971         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2972         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2973         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2974         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2975         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2976         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2977         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2978         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2979         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2980         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2981         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2982         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2983         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2984         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2986         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2988         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2989         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2990         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2991         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2992         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2994         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2995         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2996 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2997         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3006         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3009         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3010         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3011         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3012         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3013         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3014         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3015         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3016         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3017         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3018         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3019         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3020         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3021         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3022         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3023         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3024         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3025         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3026         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3027         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3028         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3029         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3030         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3031         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3032         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3033         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3034         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3035         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3036         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3037         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3038         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3039         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3040         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3041         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3042         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3043         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3044         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3045         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3046         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3047         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3048         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3049         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3050         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3051         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3052         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3053         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3054         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3055         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3056         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3057         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3058         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3059         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3060         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3061         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3062         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3063         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3064         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3065         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3066         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3067         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3068         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3069         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3070         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3071         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3072         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3073         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3074         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3075         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3076         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3077         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3078         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3079         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3080         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3081         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3082         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3083         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3084         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3085         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3086         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3087         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3206         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3207 # if ENABLE_ASH_ALIAS
3208         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3209 # endif
3210 };
3211
3212 #if 1
3213 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3214 #else /* debug version, caught one signed char bug */
3215 # define SIT(c, syntax) \
3216         ({ \
3217                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3218                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3219                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3220                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3221                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3222         })
3223 #endif
3224
3225 #endif  /* !USE_SIT_FUNCTION */
3226
3227
3228 /* ============ Alias handling */
3229
3230 #if ENABLE_ASH_ALIAS
3231
3232 #define ALIASINUSE 1
3233 #define ALIASDEAD  2
3234
3235 struct alias {
3236         struct alias *next;
3237         char *name;
3238         char *val;
3239         int flag;
3240 };
3241
3242
3243 static struct alias **atab; // [ATABSIZE];
3244 #define INIT_G_alias() do { \
3245         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3246 } while (0)
3247
3248
3249 static struct alias **
3250 __lookupalias(const char *name)
3251 {
3252         unsigned int hashval;
3253         struct alias **app;
3254         const char *p;
3255         unsigned int ch;
3256
3257         p = name;
3258
3259         ch = (unsigned char)*p;
3260         hashval = ch << 4;
3261         while (ch) {
3262                 hashval += ch;
3263                 ch = (unsigned char)*++p;
3264         }
3265         app = &atab[hashval % ATABSIZE];
3266
3267         for (; *app; app = &(*app)->next) {
3268                 if (strcmp(name, (*app)->name) == 0) {
3269                         break;
3270                 }
3271         }
3272
3273         return app;
3274 }
3275
3276 static struct alias *
3277 lookupalias(const char *name, int check)
3278 {
3279         struct alias *ap = *__lookupalias(name);
3280
3281         if (check && ap && (ap->flag & ALIASINUSE))
3282                 return NULL;
3283         return ap;
3284 }
3285
3286 static struct alias *
3287 freealias(struct alias *ap)
3288 {
3289         struct alias *next;
3290
3291         if (ap->flag & ALIASINUSE) {
3292                 ap->flag |= ALIASDEAD;
3293                 return ap;
3294         }
3295
3296         next = ap->next;
3297         free(ap->name);
3298         free(ap->val);
3299         free(ap);
3300         return next;
3301 }
3302
3303 static void
3304 setalias(const char *name, const char *val)
3305 {
3306         struct alias *ap, **app;
3307
3308         app = __lookupalias(name);
3309         ap = *app;
3310         INT_OFF;
3311         if (ap) {
3312                 if (!(ap->flag & ALIASINUSE)) {
3313                         free(ap->val);
3314                 }
3315                 ap->val = ckstrdup(val);
3316                 ap->flag &= ~ALIASDEAD;
3317         } else {
3318                 /* not found */
3319                 ap = ckzalloc(sizeof(struct alias));
3320                 ap->name = ckstrdup(name);
3321                 ap->val = ckstrdup(val);
3322                 /*ap->flag = 0; - ckzalloc did it */
3323                 /*ap->next = NULL;*/
3324                 *app = ap;
3325         }
3326         INT_ON;
3327 }
3328
3329 static int
3330 unalias(const char *name)
3331 {
3332         struct alias **app;
3333
3334         app = __lookupalias(name);
3335
3336         if (*app) {
3337                 INT_OFF;
3338                 *app = freealias(*app);
3339                 INT_ON;
3340                 return 0;
3341         }
3342
3343         return 1;
3344 }
3345
3346 static void
3347 rmaliases(void)
3348 {
3349         struct alias *ap, **app;
3350         int i;
3351
3352         INT_OFF;
3353         for (i = 0; i < ATABSIZE; i++) {
3354                 app = &atab[i];
3355                 for (ap = *app; ap; ap = *app) {
3356                         *app = freealias(*app);
3357                         if (ap == *app) {
3358                                 app = &ap->next;
3359                         }
3360                 }
3361         }
3362         INT_ON;
3363 }
3364
3365 static void
3366 printalias(const struct alias *ap)
3367 {
3368         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3369 }
3370
3371 /*
3372  * TODO - sort output
3373  */
3374 static int FAST_FUNC
3375 aliascmd(int argc UNUSED_PARAM, char **argv)
3376 {
3377         char *n, *v;
3378         int ret = 0;
3379         struct alias *ap;
3380
3381         if (!argv[1]) {
3382                 int i;
3383
3384                 for (i = 0; i < ATABSIZE; i++) {
3385                         for (ap = atab[i]; ap; ap = ap->next) {
3386                                 printalias(ap);
3387                         }
3388                 }
3389                 return 0;
3390         }
3391         while ((n = *++argv) != NULL) {
3392                 v = strchr(n+1, '=');
3393                 if (v == NULL) { /* n+1: funny ksh stuff */
3394                         ap = *__lookupalias(n);
3395                         if (ap == NULL) {
3396                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3397                                 ret = 1;
3398                         } else
3399                                 printalias(ap);
3400                 } else {
3401                         *v++ = '\0';
3402                         setalias(n, v);
3403                 }
3404         }
3405
3406         return ret;
3407 }
3408
3409 static int FAST_FUNC
3410 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3411 {
3412         int i;
3413
3414         while (nextopt("a") != '\0') {
3415                 rmaliases();
3416                 return 0;
3417         }
3418         for (i = 0; *argptr; argptr++) {
3419                 if (unalias(*argptr)) {
3420                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3421                         i = 1;
3422                 }
3423         }
3424
3425         return i;
3426 }
3427
3428 #endif /* ASH_ALIAS */
3429
3430
3431 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3432 #define FORK_FG    0
3433 #define FORK_BG    1
3434 #define FORK_NOJOB 2
3435
3436 /* mode flags for showjob(s) */
3437 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3438 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3439 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3440 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3441
3442 /*
3443  * A job structure contains information about a job.  A job is either a
3444  * single process or a set of processes contained in a pipeline.  In the
3445  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3446  * array of pids.
3447  */
3448 struct procstat {
3449         pid_t   ps_pid;         /* process id */
3450         int     ps_status;      /* last process status from wait() */
3451         char    *ps_cmd;        /* text of command being run */
3452 };
3453
3454 struct job {
3455         struct procstat ps0;    /* status of process */
3456         struct procstat *ps;    /* status or processes when more than one */
3457 #if JOBS
3458         int stopstatus;         /* status of a stopped job */
3459 #endif
3460         unsigned nprocs;        /* number of processes */
3461
3462 #define JOBRUNNING      0       /* at least one proc running */
3463 #define JOBSTOPPED      1       /* all procs are stopped */
3464 #define JOBDONE         2       /* all procs are completed */
3465         unsigned
3466                 state: 8,
3467 #if JOBS
3468                 sigint: 1,      /* job was killed by SIGINT */
3469                 jobctl: 1,      /* job running under job control */
3470 #endif
3471                 waited: 1,      /* true if this entry has been waited for */
3472                 used: 1,        /* true if this entry is in used */
3473                 changed: 1;     /* true if status has changed */
3474         struct job *prev_job;   /* previous job */
3475 };
3476
3477 static struct job *makejob(/*union node *,*/ int);
3478 static int forkshell(struct job *, union node *, int);
3479 static int waitforjob(struct job *);
3480
3481 #if !JOBS
3482 enum { doing_jobctl = 0 };
3483 #define setjobctl(on) do {} while (0)
3484 #else
3485 static smallint doing_jobctl; //references:8
3486 static void setjobctl(int);
3487 #endif
3488
3489 /*
3490  * Ignore a signal.
3491  */
3492 static void
3493 ignoresig(int signo)
3494 {
3495         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3496         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3497                 /* No, need to do it */
3498                 signal(signo, SIG_IGN);
3499         }
3500         sigmode[signo - 1] = S_HARD_IGN;
3501 }
3502
3503 /*
3504  * Only one usage site - in setsignal()
3505  */
3506 static void
3507 signal_handler(int signo)
3508 {
3509         if (signo == SIGCHLD) {
3510                 got_sigchld = 1;
3511                 if (!trap[SIGCHLD])
3512                         return;
3513         }
3514
3515         gotsig[signo - 1] = 1;
3516         pending_sig = signo;
3517
3518         if (signo == SIGINT && !trap[SIGINT]) {
3519                 if (!suppress_int) {
3520                         pending_sig = 0;
3521                         raise_interrupt(); /* does not return */
3522                 }
3523                 pending_int = 1;
3524         }
3525 }
3526
3527 /*
3528  * Set the signal handler for the specified signal.  The routine figures
3529  * out what it should be set to.
3530  */
3531 static void
3532 setsignal(int signo)
3533 {
3534         char *t;
3535         char cur_act, new_act;
3536         struct sigaction act;
3537
3538         t = trap[signo];
3539         new_act = S_DFL;
3540         if (t != NULL) { /* trap for this sig is set */
3541                 new_act = S_CATCH;
3542                 if (t[0] == '\0') /* trap is "": ignore this sig */
3543                         new_act = S_IGN;
3544         }
3545
3546         if (rootshell && new_act == S_DFL) {
3547                 switch (signo) {
3548                 case SIGINT:
3549                         if (iflag || minusc || sflag == 0)
3550                                 new_act = S_CATCH;
3551                         break;
3552                 case SIGQUIT:
3553 #if DEBUG
3554                         if (debug)
3555                                 break;
3556 #endif
3557                         /* man bash:
3558                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3559                          * commands run by bash have signal handlers
3560                          * set to the values inherited by the shell
3561                          * from its parent". */
3562                         new_act = S_IGN;
3563                         break;
3564                 case SIGTERM:
3565                         if (iflag)
3566                                 new_act = S_IGN;
3567                         break;
3568 #if JOBS
3569                 case SIGTSTP:
3570                 case SIGTTOU:
3571                         if (mflag)
3572                                 new_act = S_IGN;
3573                         break;
3574 #endif
3575                 }
3576         }
3577         /* if !rootshell, we reset SIGQUIT to DFL,
3578          * whereas we have to restore it to what shell got on entry.
3579          * This is handled by the fact that if signal was IGNored on entry,
3580          * then cur_act is S_HARD_IGN and we never change its sigaction
3581          * (see code below).
3582          */
3583
3584         if (signo == SIGCHLD)
3585                 new_act = S_CATCH;
3586
3587         t = &sigmode[signo - 1];
3588         cur_act = *t;
3589         if (cur_act == 0) {
3590                 /* current setting is not yet known */
3591                 if (sigaction(signo, NULL, &act)) {
3592                         /* pretend it worked; maybe we should give a warning,
3593                          * but other shells don't. We don't alter sigmode,
3594                          * so we retry every time.
3595                          * btw, in Linux it never fails. --vda */
3596                         return;
3597                 }
3598                 if (act.sa_handler == SIG_IGN) {
3599                         cur_act = S_HARD_IGN;
3600                         if (mflag
3601                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3602                         ) {
3603                                 cur_act = S_IGN;   /* don't hard ignore these */
3604                         }
3605                 }
3606                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3607                         /* installing SIG_DFL over SIG_DFL is a no-op */
3608                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3609                         *t = S_DFL;
3610                         return;
3611                 }
3612         }
3613         if (cur_act == S_HARD_IGN || cur_act == new_act)
3614                 return;
3615
3616         *t = new_act;
3617
3618         act.sa_handler = SIG_DFL;
3619         switch (new_act) {
3620         case S_CATCH:
3621                 act.sa_handler = signal_handler;
3622                 break;
3623         case S_IGN:
3624                 act.sa_handler = SIG_IGN;
3625                 break;
3626         }
3627         /* flags and mask matter only if !DFL and !IGN, but we do it
3628          * for all cases for more deterministic behavior:
3629          */
3630         act.sa_flags = 0; //TODO: why not SA_RESTART?
3631         sigfillset(&act.sa_mask);
3632
3633         sigaction_set(signo, &act);
3634 }
3635
3636 /* mode flags for set_curjob */
3637 #define CUR_DELETE 2
3638 #define CUR_RUNNING 1
3639 #define CUR_STOPPED 0
3640
3641 #if JOBS
3642 /* pgrp of shell on invocation */
3643 static int initialpgrp; //references:2
3644 static int ttyfd = -1; //5
3645 #endif
3646 /* array of jobs */
3647 static struct job *jobtab; //5
3648 /* size of array */
3649 static unsigned njobs; //4
3650 /* current job */
3651 static struct job *curjob; //lots
3652 /* number of presumed living untracked jobs */
3653 static int jobless; //4
3654
3655 #if 0
3656 /* Bash has a feature: it restores termios after a successful wait for
3657  * a foreground job which had at least one stopped or sigkilled member.
3658  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3659  * properly restoring tty state. Should we do this too?
3660  * A reproducer: ^Z an interactive python:
3661  *
3662  * # python
3663  * Python 2.7.12 (...)
3664  * >>> ^Z
3665  *      { python leaves tty in -icanon -echo state. We do survive that... }
3666  *  [1]+  Stopped                    python
3667  *      { ...however, next program (python #2) does not survive it well: }
3668  * # python
3669  * Python 2.7.12 (...)
3670  * >>> Traceback (most recent call last):
3671  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3672  *   File "<stdin>", line 1, in <module>
3673  * NameError: name 'qwerty' is not defined
3674  *
3675  * The implementation below is modeled on bash code and seems to work.
3676  * However, I'm not sure we should do this. For one: what if I'd fg
3677  * the stopped python instead? It'll be confused by "restored" tty state.
3678  */
3679 static struct termios shell_tty_info;
3680 static void
3681 get_tty_state(void)
3682 {
3683         if (rootshell && ttyfd >= 0)
3684                 tcgetattr(ttyfd, &shell_tty_info);
3685 }
3686 static void
3687 set_tty_state(void)
3688 {
3689         /* if (rootshell) - caller ensures this */
3690         if (ttyfd >= 0)
3691                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3692 }
3693 static int
3694 job_signal_status(struct job *jp)
3695 {
3696         int status;
3697         unsigned i;
3698         struct procstat *ps = jp->ps;
3699         for (i = 0; i < jp->nprocs; i++) {
3700                 status = ps[i].ps_status;
3701                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3702                         return status;
3703         }
3704         return 0;
3705 }
3706 static void
3707 restore_tty_if_stopped_or_signaled(struct job *jp)
3708 {
3709 //TODO: check what happens if we come from waitforjob() in expbackq()
3710         if (rootshell) {
3711                 int s = job_signal_status(jp);
3712                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3713                         set_tty_state();
3714         }
3715 }
3716 #else
3717 # define get_tty_state() ((void)0)
3718 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3719 #endif
3720
3721 static void
3722 set_curjob(struct job *jp, unsigned mode)
3723 {
3724         struct job *jp1;
3725         struct job **jpp, **curp;
3726
3727         /* first remove from list */
3728         jpp = curp = &curjob;
3729         while (1) {
3730                 jp1 = *jpp;
3731                 if (jp1 == jp)
3732                         break;
3733                 jpp = &jp1->prev_job;
3734         }
3735         *jpp = jp1->prev_job;
3736
3737         /* Then re-insert in correct position */
3738         jpp = curp;
3739         switch (mode) {
3740         default:
3741 #if DEBUG
3742                 abort();
3743 #endif
3744         case CUR_DELETE:
3745                 /* job being deleted */
3746                 break;
3747         case CUR_RUNNING:
3748                 /* newly created job or backgrounded job,
3749                  * put after all stopped jobs.
3750                  */
3751                 while (1) {
3752                         jp1 = *jpp;
3753 #if JOBS
3754                         if (!jp1 || jp1->state != JOBSTOPPED)
3755 #endif
3756                                 break;
3757                         jpp = &jp1->prev_job;
3758                 }
3759                 /* FALLTHROUGH */
3760 #if JOBS
3761         case CUR_STOPPED:
3762 #endif
3763                 /* newly stopped job - becomes curjob */
3764                 jp->prev_job = *jpp;
3765                 *jpp = jp;
3766                 break;
3767         }
3768 }
3769
3770 #if JOBS || DEBUG
3771 static int
3772 jobno(const struct job *jp)
3773 {
3774         return jp - jobtab + 1;
3775 }
3776 #endif
3777
3778 /*
3779  * Convert a job name to a job structure.
3780  */
3781 #if !JOBS
3782 #define getjob(name, getctl) getjob(name)
3783 #endif
3784 static struct job *
3785 getjob(const char *name, int getctl)
3786 {
3787         struct job *jp;
3788         struct job *found;
3789         const char *err_msg = "%s: no such job";
3790         unsigned num;
3791         int c;
3792         const char *p;
3793         char *(*match)(const char *, const char *);
3794
3795         jp = curjob;
3796         p = name;
3797         if (!p)
3798                 goto currentjob;
3799
3800         if (*p != '%')
3801                 goto err;
3802
3803         c = *++p;
3804         if (!c)
3805                 goto currentjob;
3806
3807         if (!p[1]) {
3808                 if (c == '+' || c == '%') {
3809  currentjob:
3810                         err_msg = "No current job";
3811                         goto check;
3812                 }
3813                 if (c == '-') {
3814                         if (jp)
3815                                 jp = jp->prev_job;
3816                         err_msg = "No previous job";
3817  check:
3818                         if (!jp)
3819                                 goto err;
3820                         goto gotit;
3821                 }
3822         }
3823
3824         if (is_number(p)) {
3825                 num = atoi(p);
3826                 if (num > 0 && num <= njobs) {
3827                         jp = jobtab + num - 1;
3828                         if (jp->used)
3829                                 goto gotit;
3830                         goto err;
3831                 }
3832         }
3833
3834         match = prefix;
3835         if (*p == '?') {
3836                 match = strstr;
3837                 p++;
3838         }
3839
3840         found = NULL;
3841         while (jp) {
3842                 if (match(jp->ps[0].ps_cmd, p)) {
3843                         if (found)
3844                                 goto err;
3845                         found = jp;
3846                         err_msg = "%s: ambiguous";
3847                 }
3848                 jp = jp->prev_job;
3849         }
3850         if (!found)
3851                 goto err;
3852         jp = found;
3853
3854  gotit:
3855 #if JOBS
3856         err_msg = "job %s not created under job control";
3857         if (getctl && jp->jobctl == 0)
3858                 goto err;
3859 #endif
3860         return jp;
3861  err:
3862         ash_msg_and_raise_error(err_msg, name);
3863 }
3864
3865 /*
3866  * Mark a job structure as unused.
3867  */
3868 static void
3869 freejob(struct job *jp)
3870 {
3871         struct procstat *ps;
3872         int i;
3873
3874         INT_OFF;
3875         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3876                 if (ps->ps_cmd != nullstr)
3877                         free(ps->ps_cmd);
3878         }
3879         if (jp->ps != &jp->ps0)
3880                 free(jp->ps);
3881         jp->used = 0;
3882         set_curjob(jp, CUR_DELETE);
3883         INT_ON;
3884 }
3885
3886 #if JOBS
3887 static void
3888 xtcsetpgrp(int fd, pid_t pgrp)
3889 {
3890         if (tcsetpgrp(fd, pgrp))
3891                 ash_msg_and_raise_perror("can't set tty process group");
3892 }
3893
3894 /*
3895  * Turn job control on and off.
3896  *
3897  * Note:  This code assumes that the third arg to ioctl is a character
3898  * pointer, which is true on Berkeley systems but not System V.  Since
3899  * System V doesn't have job control yet, this isn't a problem now.
3900  *
3901  * Called with interrupts off.
3902  */
3903 static void
3904 setjobctl(int on)
3905 {
3906         int fd;
3907         int pgrp;
3908
3909         if (on == doing_jobctl || rootshell == 0)
3910                 return;
3911         if (on) {
3912                 int ofd;
3913                 ofd = fd = open(_PATH_TTY, O_RDWR);
3914                 if (fd < 0) {
3915         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3916          * That sometimes helps to acquire controlling tty.
3917          * Obviously, a workaround for bugs when someone
3918          * failed to provide a controlling tty to bash! :) */
3919                         fd = 2;
3920                         while (!isatty(fd))
3921                                 if (--fd < 0)
3922                                         goto out;
3923                 }
3924                 /* fd is a tty at this point */
3925                 fd = fcntl(fd, F_DUPFD, 10);
3926                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3927                         close(ofd);
3928                 if (fd < 0)
3929                         goto out; /* F_DUPFD failed */
3930                 close_on_exec_on(fd);
3931                 while (1) { /* while we are in the background */
3932                         pgrp = tcgetpgrp(fd);
3933                         if (pgrp < 0) {
3934  out:
3935                                 ash_msg("can't access tty; job control turned off");
3936                                 mflag = on = 0;
3937                                 goto close;
3938                         }
3939                         if (pgrp == getpgrp())
3940                                 break;
3941                         killpg(0, SIGTTIN);
3942                 }
3943                 initialpgrp = pgrp;
3944
3945                 setsignal(SIGTSTP);
3946                 setsignal(SIGTTOU);
3947                 setsignal(SIGTTIN);
3948                 pgrp = rootpid;
3949                 setpgid(0, pgrp);
3950                 xtcsetpgrp(fd, pgrp);
3951         } else {
3952                 /* turning job control off */
3953                 fd = ttyfd;
3954                 pgrp = initialpgrp;
3955                 /* was xtcsetpgrp, but this can make exiting ash
3956                  * loop forever if pty is already deleted */
3957                 tcsetpgrp(fd, pgrp);
3958                 setpgid(0, pgrp);
3959                 setsignal(SIGTSTP);
3960                 setsignal(SIGTTOU);
3961                 setsignal(SIGTTIN);
3962  close:
3963                 if (fd >= 0)
3964                         close(fd);
3965                 fd = -1;
3966         }
3967         ttyfd = fd;
3968         doing_jobctl = on;
3969 }
3970
3971 static int FAST_FUNC
3972 killcmd(int argc, char **argv)
3973 {
3974         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3975                 int i = 1;
3976                 do {
3977                         if (argv[i][0] == '%') {
3978                                 /*
3979                                  * "kill %N" - job kill
3980                                  * Converting to pgrp / pid kill
3981                                  */
3982                                 struct job *jp;
3983                                 char *dst;
3984                                 int j, n;
3985
3986                                 jp = getjob(argv[i], 0);
3987                                 /*
3988                                  * In jobs started under job control, we signal
3989                                  * entire process group by kill -PGRP_ID.
3990                                  * This happens, f.e., in interactive shell.
3991                                  *
3992                                  * Otherwise, we signal each child via
3993                                  * kill PID1 PID2 PID3.
3994                                  * Testcases:
3995                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3996                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3997                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3998                                  */
3999                                 n = jp->nprocs; /* can't be 0 (I hope) */
4000                                 if (jp->jobctl)
4001                                         n = 1;
4002                                 dst = alloca(n * sizeof(int)*4);
4003                                 argv[i] = dst;
4004                                 for (j = 0; j < n; j++) {
4005                                         struct procstat *ps = &jp->ps[j];
4006                                         /* Skip non-running and not-stopped members
4007                                          * (i.e. dead members) of the job
4008                                          */
4009                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4010                                                 continue;
4011                                         /*
4012                                          * kill_main has matching code to expect
4013                                          * leading space. Needed to not confuse
4014                                          * negative pids with "kill -SIGNAL_NO" syntax
4015                                          */
4016                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4017                                 }
4018                                 *dst = '\0';
4019                         }
4020                 } while (argv[++i]);
4021         }
4022         return kill_main(argc, argv);
4023 }
4024
4025 static void
4026 showpipe(struct job *jp /*, FILE *out*/)
4027 {
4028         struct procstat *ps;
4029         struct procstat *psend;
4030
4031         psend = jp->ps + jp->nprocs;
4032         for (ps = jp->ps + 1; ps < psend; ps++)
4033                 printf(" | %s", ps->ps_cmd);
4034         newline_and_flush(stdout);
4035         flush_stdout_stderr();
4036 }
4037
4038
4039 static int
4040 restartjob(struct job *jp, int mode)
4041 {
4042         struct procstat *ps;
4043         int i;
4044         int status;
4045         pid_t pgid;
4046
4047         INT_OFF;
4048         if (jp->state == JOBDONE)
4049                 goto out;
4050         jp->state = JOBRUNNING;
4051         pgid = jp->ps[0].ps_pid;
4052         if (mode == FORK_FG) {
4053                 get_tty_state();
4054                 xtcsetpgrp(ttyfd, pgid);
4055         }
4056         killpg(pgid, SIGCONT);
4057         ps = jp->ps;
4058         i = jp->nprocs;
4059         do {
4060                 if (WIFSTOPPED(ps->ps_status)) {
4061                         ps->ps_status = -1;
4062                 }
4063                 ps++;
4064         } while (--i);
4065  out:
4066         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4067         INT_ON;
4068         return status;
4069 }
4070
4071 static int FAST_FUNC
4072 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4073 {
4074         struct job *jp;
4075         int mode;
4076         int retval;
4077
4078         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4079         nextopt(nullstr);
4080         argv = argptr;
4081         do {
4082                 jp = getjob(*argv, 1);
4083                 if (mode == FORK_BG) {
4084                         set_curjob(jp, CUR_RUNNING);
4085                         printf("[%d] ", jobno(jp));
4086                 }
4087                 out1str(jp->ps[0].ps_cmd);
4088                 showpipe(jp /*, stdout*/);
4089                 retval = restartjob(jp, mode);
4090         } while (*argv && *++argv);
4091         return retval;
4092 }
4093 #endif
4094
4095 static int
4096 sprint_status48(char *s, int status, int sigonly)
4097 {
4098         int col;
4099         int st;
4100
4101         col = 0;
4102         if (!WIFEXITED(status)) {
4103 #if JOBS
4104                 if (WIFSTOPPED(status))
4105                         st = WSTOPSIG(status);
4106                 else
4107 #endif
4108                         st = WTERMSIG(status);
4109                 if (sigonly) {
4110                         if (st == SIGINT || st == SIGPIPE)
4111                                 goto out;
4112 #if JOBS
4113                         if (WIFSTOPPED(status))
4114                                 goto out;
4115 #endif
4116                 }
4117                 st &= 0x7f;
4118 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4119                 col = fmtstr(s, 32, strsignal(st));
4120                 if (WCOREDUMP(status)) {
4121                         strcpy(s + col, " (core dumped)");
4122                         col += sizeof(" (core dumped)")-1;
4123                 }
4124         } else if (!sigonly) {
4125                 st = WEXITSTATUS(status);
4126                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4127         }
4128  out:
4129         return col;
4130 }
4131
4132 static int
4133 wait_block_or_sig(int *status)
4134 {
4135         int pid;
4136
4137         do {
4138                 sigset_t mask;
4139
4140                 /* Poll all children for changes in their state */
4141                 got_sigchld = 0;
4142                 /* if job control is active, accept stopped processes too */
4143                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4144                 if (pid != 0)
4145                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4146
4147                 /* Children exist, but none are ready. Sleep until interesting signal */
4148 #if 1
4149                 sigfillset(&mask);
4150                 sigprocmask(SIG_SETMASK, &mask, &mask);
4151                 while (!got_sigchld && !pending_sig)
4152                         sigsuspend(&mask);
4153                 sigprocmask(SIG_SETMASK, &mask, NULL);
4154 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4155                 while (!got_sigchld && !pending_sig)
4156                         pause();
4157 #endif
4158
4159                 /* If it was SIGCHLD, poll children again */
4160         } while (got_sigchld);
4161
4162         return pid;
4163 }
4164
4165 #define DOWAIT_NONBLOCK 0
4166 #define DOWAIT_BLOCK    1
4167 #define DOWAIT_BLOCK_OR_SIG 2
4168
4169 static int
4170 dowait(int block, struct job *job)
4171 {
4172         int pid;
4173         int status;
4174         struct job *jp;
4175         struct job *thisjob = NULL;
4176
4177         TRACE(("dowait(0x%x) called\n", block));
4178
4179         /* It's wrong to call waitpid() outside of INT_OFF region:
4180          * signal can arrive just after syscall return and handler can
4181          * longjmp away, losing stop/exit notification processing.
4182          * Thus, for "jobs" builtin, and for waiting for a fg job,
4183          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4184          *
4185          * However, for "wait" builtin it is wrong to simply call waitpid()
4186          * in INT_OFF region: "wait" needs to wait for any running job
4187          * to change state, but should exit on any trap too.
4188          * In INT_OFF region, a signal just before syscall entry can set
4189          * pending_sig variables, but we can't check them, and we would
4190          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4191          *
4192          * Because of this, we run inside INT_OFF, but use a special routine
4193          * which combines waitpid() and sigsuspend().
4194          * This is the reason why we need to have a handler for SIGCHLD:
4195          * SIG_DFL handler does not wake sigsuspend().
4196          */
4197         INT_OFF;
4198         if (block == DOWAIT_BLOCK_OR_SIG) {
4199                 pid = wait_block_or_sig(&status);
4200         } else {
4201                 int wait_flags = 0;
4202                 if (block == DOWAIT_NONBLOCK)
4203                         wait_flags = WNOHANG;
4204                 /* if job control is active, accept stopped processes too */
4205                 if (doing_jobctl)
4206                         wait_flags |= WUNTRACED;
4207                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4208                 pid = waitpid(-1, &status, wait_flags);
4209         }
4210         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4211                                 pid, status, errno, strerror(errno)));
4212         if (pid <= 0)
4213                 goto out;
4214
4215         thisjob = NULL;
4216         for (jp = curjob; jp; jp = jp->prev_job) {
4217                 int jobstate;
4218                 struct procstat *ps;
4219                 struct procstat *psend;
4220                 if (jp->state == JOBDONE)
4221                         continue;
4222                 jobstate = JOBDONE;
4223                 ps = jp->ps;
4224                 psend = ps + jp->nprocs;
4225                 do {
4226                         if (ps->ps_pid == pid) {
4227                                 TRACE(("Job %d: changing status of proc %d "
4228                                         "from 0x%x to 0x%x\n",
4229                                         jobno(jp), pid, ps->ps_status, status));
4230                                 ps->ps_status = status;
4231                                 thisjob = jp;
4232                         }
4233                         if (ps->ps_status == -1)
4234                                 jobstate = JOBRUNNING;
4235 #if JOBS
4236                         if (jobstate == JOBRUNNING)
4237                                 continue;
4238                         if (WIFSTOPPED(ps->ps_status)) {
4239                                 jp->stopstatus = ps->ps_status;
4240                                 jobstate = JOBSTOPPED;
4241                         }
4242 #endif
4243                 } while (++ps < psend);
4244                 if (!thisjob)
4245                         continue;
4246
4247                 /* Found the job where one of its processes changed its state.
4248                  * Is there at least one live and running process in this job? */
4249                 if (jobstate != JOBRUNNING) {
4250                         /* No. All live processes in the job are stopped
4251                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4252                          */
4253                         thisjob->changed = 1;
4254                         if (thisjob->state != jobstate) {
4255                                 TRACE(("Job %d: changing state from %d to %d\n",
4256                                         jobno(thisjob), thisjob->state, jobstate));
4257                                 thisjob->state = jobstate;
4258 #if JOBS
4259                                 if (jobstate == JOBSTOPPED)
4260                                         set_curjob(thisjob, CUR_STOPPED);
4261 #endif
4262                         }
4263                 }
4264                 goto out;
4265         }
4266         /* The process wasn't found in job list */
4267 #if JOBS
4268         if (!WIFSTOPPED(status))
4269                 jobless--;
4270 #endif
4271  out:
4272         INT_ON;
4273
4274         if (thisjob && thisjob == job) {
4275                 char s[48 + 1];
4276                 int len;
4277
4278                 len = sprint_status48(s, status, 1);
4279                 if (len) {
4280                         s[len] = '\n';
4281                         s[len + 1] = '\0';
4282                         out2str(s);
4283                 }
4284         }
4285         return pid;
4286 }
4287
4288 #if JOBS
4289 static void
4290 showjob(struct job *jp, int mode)
4291 {
4292         struct procstat *ps;
4293         struct procstat *psend;
4294         int col;
4295         int indent_col;
4296         char s[16 + 16 + 48];
4297         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4298
4299         ps = jp->ps;
4300
4301         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4302                 /* just output process (group) id of pipeline */
4303                 fprintf(out, "%d\n", ps->ps_pid);
4304                 return;
4305         }
4306
4307         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4308         indent_col = col;
4309
4310         if (jp == curjob)
4311                 s[col - 3] = '+';
4312         else if (curjob && jp == curjob->prev_job)
4313                 s[col - 3] = '-';
4314
4315         if (mode & SHOW_PIDS)
4316                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4317
4318         psend = ps + jp->nprocs;
4319
4320         if (jp->state == JOBRUNNING) {
4321                 strcpy(s + col, "Running");
4322                 col += sizeof("Running") - 1;
4323         } else {
4324                 int status = psend[-1].ps_status;
4325                 if (jp->state == JOBSTOPPED)
4326                         status = jp->stopstatus;
4327                 col += sprint_status48(s + col, status, 0);
4328         }
4329         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4330
4331         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4332          * or prints several "PID             | <cmdN>" lines,
4333          * depending on SHOW_PIDS bit.
4334          * We do not print status of individual processes
4335          * between PID and <cmdN>. bash does it, but not very well:
4336          * first line shows overall job status, not process status,
4337          * making it impossible to know 1st process status.
4338          */
4339         goto start;
4340         do {
4341                 /* for each process */
4342                 s[0] = '\0';
4343                 col = 33;
4344                 if (mode & SHOW_PIDS)
4345                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4346  start:
4347                 fprintf(out, "%s%*c%s%s",
4348                                 s,
4349                                 33 - col >= 0 ? 33 - col : 0, ' ',
4350                                 ps == jp->ps ? "" : "| ",
4351                                 ps->ps_cmd
4352                 );
4353         } while (++ps != psend);
4354         newline_and_flush(out);
4355
4356         jp->changed = 0;
4357
4358         if (jp->state == JOBDONE) {
4359                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4360                 freejob(jp);
4361         }
4362 }
4363
4364 /*
4365  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4366  * statuses have changed since the last call to showjobs.
4367  */
4368 static void
4369 showjobs(int mode)
4370 {
4371         struct job *jp;
4372
4373         TRACE(("showjobs(0x%x) called\n", mode));
4374
4375         /* Handle all finished jobs */
4376         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4377                 continue;
4378
4379         for (jp = curjob; jp; jp = jp->prev_job) {
4380                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4381                         showjob(jp, mode);
4382                 }
4383         }
4384 }
4385
4386 static int FAST_FUNC
4387 jobscmd(int argc UNUSED_PARAM, char **argv)
4388 {
4389         int mode, m;
4390
4391         mode = 0;
4392         while ((m = nextopt("lp")) != '\0') {
4393                 if (m == 'l')
4394                         mode |= SHOW_PIDS;
4395                 else
4396                         mode |= SHOW_ONLY_PGID;
4397         }
4398
4399         argv = argptr;
4400         if (*argv) {
4401                 do
4402                         showjob(getjob(*argv, 0), mode);
4403                 while (*++argv);
4404         } else {
4405                 showjobs(mode);
4406         }
4407
4408         return 0;
4409 }
4410 #endif /* JOBS */
4411
4412 /* Called only on finished or stopped jobs (no members are running) */
4413 static int
4414 getstatus(struct job *job)
4415 {
4416         int status;
4417         int retval;
4418         struct procstat *ps;
4419
4420         /* Fetch last member's status */
4421         ps = job->ps + job->nprocs - 1;
4422         status = ps->ps_status;
4423         if (pipefail) {
4424                 /* "set -o pipefail" mode: use last _nonzero_ status */
4425                 while (status == 0 && --ps >= job->ps)
4426                         status = ps->ps_status;
4427         }
4428
4429         retval = WEXITSTATUS(status);
4430         if (!WIFEXITED(status)) {
4431 #if JOBS
4432                 retval = WSTOPSIG(status);
4433                 if (!WIFSTOPPED(status))
4434 #endif
4435                 {
4436                         /* XXX: limits number of signals */
4437                         retval = WTERMSIG(status);
4438 #if JOBS
4439                         if (retval == SIGINT)
4440                                 job->sigint = 1;
4441 #endif
4442                 }
4443                 retval += 128;
4444         }
4445         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4446                 jobno(job), job->nprocs, status, retval));
4447         return retval;
4448 }
4449
4450 static int FAST_FUNC
4451 waitcmd(int argc UNUSED_PARAM, char **argv)
4452 {
4453         struct job *job;
4454         int retval;
4455         struct job *jp;
4456
4457         nextopt(nullstr);
4458         retval = 0;
4459
4460         argv = argptr;
4461         if (!*argv) {
4462                 /* wait for all jobs */
4463                 for (;;) {
4464                         jp = curjob;
4465                         while (1) {
4466                                 if (!jp) /* no running procs */
4467                                         goto ret;
4468                                 if (jp->state == JOBRUNNING)
4469                                         break;
4470                                 jp->waited = 1;
4471                                 jp = jp->prev_job;
4472                         }
4473         /* man bash:
4474          * "When bash is waiting for an asynchronous command via
4475          * the wait builtin, the reception of a signal for which a trap
4476          * has been set will cause the wait builtin to return immediately
4477          * with an exit status greater than 128, immediately after which
4478          * the trap is executed."
4479          */
4480                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4481         /* if child sends us a signal *and immediately exits*,
4482          * dowait() returns pid > 0. Check this case,
4483          * not "if (dowait() < 0)"!
4484          */
4485                         if (pending_sig)
4486                                 goto sigout;
4487                 }
4488         }
4489
4490         retval = 127;
4491         do {
4492                 if (**argv != '%') {
4493                         pid_t pid = number(*argv);
4494                         job = curjob;
4495                         while (1) {
4496                                 if (!job)
4497                                         goto repeat;
4498                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4499                                         break;
4500                                 job = job->prev_job;
4501                         }
4502                 } else {
4503                         job = getjob(*argv, 0);
4504                 }
4505                 /* loop until process terminated or stopped */
4506                 while (job->state == JOBRUNNING) {
4507                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4508                         if (pending_sig)
4509                                 goto sigout;
4510                 }
4511                 job->waited = 1;
4512                 retval = getstatus(job);
4513  repeat: ;
4514         } while (*++argv);
4515
4516  ret:
4517         return retval;
4518  sigout:
4519         retval = 128 + pending_sig;
4520         return retval;
4521 }
4522
4523 static struct job *
4524 growjobtab(void)
4525 {
4526         size_t len;
4527         ptrdiff_t offset;
4528         struct job *jp, *jq;
4529
4530         len = njobs * sizeof(*jp);
4531         jq = jobtab;
4532         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4533
4534         offset = (char *)jp - (char *)jq;
4535         if (offset) {
4536                 /* Relocate pointers */
4537                 size_t l = len;
4538
4539                 jq = (struct job *)((char *)jq + l);
4540                 while (l) {
4541                         l -= sizeof(*jp);
4542                         jq--;
4543 #define joff(p) ((struct job *)((char *)(p) + l))
4544 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4545                         if (joff(jp)->ps == &jq->ps0)
4546                                 jmove(joff(jp)->ps);
4547                         if (joff(jp)->prev_job)
4548                                 jmove(joff(jp)->prev_job);
4549                 }
4550                 if (curjob)
4551                         jmove(curjob);
4552 #undef joff
4553 #undef jmove
4554         }
4555
4556         njobs += 4;
4557         jobtab = jp;
4558         jp = (struct job *)((char *)jp + len);
4559         jq = jp + 3;
4560         do {
4561                 jq->used = 0;
4562         } while (--jq >= jp);
4563         return jp;
4564 }
4565
4566 /*
4567  * Return a new job structure.
4568  * Called with interrupts off.
4569  */
4570 static struct job *
4571 makejob(/*union node *node,*/ int nprocs)
4572 {
4573         int i;
4574         struct job *jp;
4575
4576         for (i = njobs, jp = jobtab; ; jp++) {
4577                 if (--i < 0) {
4578                         jp = growjobtab();
4579                         break;
4580                 }
4581                 if (jp->used == 0)
4582                         break;
4583                 if (jp->state != JOBDONE || !jp->waited)
4584                         continue;
4585 #if JOBS
4586                 if (doing_jobctl)
4587                         continue;
4588 #endif
4589                 freejob(jp);
4590                 break;
4591         }
4592         memset(jp, 0, sizeof(*jp));
4593 #if JOBS
4594         /* jp->jobctl is a bitfield.
4595          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4596         if (doing_jobctl)
4597                 jp->jobctl = 1;
4598 #endif
4599         jp->prev_job = curjob;
4600         curjob = jp;
4601         jp->used = 1;
4602         jp->ps = &jp->ps0;
4603         if (nprocs > 1) {
4604                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4605         }
4606         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4607                                 jobno(jp)));
4608         return jp;
4609 }
4610
4611 #if JOBS
4612 /*
4613  * Return a string identifying a command (to be printed by the
4614  * jobs command).
4615  */
4616 static char *cmdnextc;
4617
4618 static void
4619 cmdputs(const char *s)
4620 {
4621         static const char vstype[VSTYPE + 1][3] = {
4622                 "", "}", "-", "+", "?", "=",
4623                 "%", "%%", "#", "##"
4624                 IF_BASH_SUBSTR(, ":")
4625                 IF_BASH_PATTERN_SUBST(, "/", "//")
4626         };
4627
4628         const char *p, *str;
4629         char cc[2];
4630         char *nextc;
4631         unsigned char c;
4632         unsigned char subtype = 0;
4633         int quoted = 0;
4634
4635         cc[1] = '\0';
4636         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4637         p = s;
4638         while ((c = *p++) != '\0') {
4639                 str = NULL;
4640                 switch (c) {
4641                 case CTLESC:
4642                         c = *p++;
4643                         break;
4644                 case CTLVAR:
4645                         subtype = *p++;
4646                         if ((subtype & VSTYPE) == VSLENGTH)
4647                                 str = "${#";
4648                         else
4649                                 str = "${";
4650                         goto dostr;
4651                 case CTLENDVAR:
4652                         str = "\"}" + !(quoted & 1);
4653                         quoted >>= 1;
4654                         subtype = 0;
4655                         goto dostr;
4656                 case CTLBACKQ:
4657                         str = "$(...)";
4658                         goto dostr;
4659 #if ENABLE_FEATURE_SH_MATH
4660                 case CTLARI:
4661                         str = "$((";
4662                         goto dostr;
4663                 case CTLENDARI:
4664                         str = "))";
4665                         goto dostr;
4666 #endif
4667                 case CTLQUOTEMARK:
4668                         quoted ^= 1;
4669                         c = '"';
4670                         break;
4671                 case '=':
4672                         if (subtype == 0)
4673                                 break;
4674                         if ((subtype & VSTYPE) != VSNORMAL)
4675                                 quoted <<= 1;
4676                         str = vstype[subtype & VSTYPE];
4677                         if (subtype & VSNUL)
4678                                 c = ':';
4679                         else
4680                                 goto checkstr;
4681                         break;
4682                 case '\'':
4683                 case '\\':
4684                 case '"':
4685                 case '$':
4686                         /* These can only happen inside quotes */
4687                         cc[0] = c;
4688                         str = cc;
4689 //FIXME:
4690 // $ true $$ &
4691 // $ <cr>
4692 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4693                         c = '\\';
4694                         break;
4695                 default:
4696                         break;
4697                 }
4698                 USTPUTC(c, nextc);
4699  checkstr:
4700                 if (!str)
4701                         continue;
4702  dostr:
4703                 while ((c = *str++) != '\0') {
4704                         USTPUTC(c, nextc);
4705                 }
4706         } /* while *p++ not NUL */
4707
4708         if (quoted & 1) {
4709                 USTPUTC('"', nextc);
4710         }
4711         *nextc = 0;
4712         cmdnextc = nextc;
4713 }
4714
4715 /* cmdtxt() and cmdlist() call each other */
4716 static void cmdtxt(union node *n);
4717
4718 static void
4719 cmdlist(union node *np, int sep)
4720 {
4721         for (; np; np = np->narg.next) {
4722                 if (!sep)
4723                         cmdputs(" ");
4724                 cmdtxt(np);
4725                 if (sep && np->narg.next)
4726                         cmdputs(" ");
4727         }
4728 }
4729
4730 static void
4731 cmdtxt(union node *n)
4732 {
4733         union node *np;
4734         struct nodelist *lp;
4735         const char *p;
4736
4737         if (!n)
4738                 return;
4739         switch (n->type) {
4740         default:
4741 #if DEBUG
4742                 abort();
4743 #endif
4744         case NPIPE:
4745                 lp = n->npipe.cmdlist;
4746                 for (;;) {
4747                         cmdtxt(lp->n);
4748                         lp = lp->next;
4749                         if (!lp)
4750                                 break;
4751                         cmdputs(" | ");
4752                 }
4753                 break;
4754         case NSEMI:
4755                 p = "; ";
4756                 goto binop;
4757         case NAND:
4758                 p = " && ";
4759                 goto binop;
4760         case NOR:
4761                 p = " || ";
4762  binop:
4763                 cmdtxt(n->nbinary.ch1);
4764                 cmdputs(p);
4765                 n = n->nbinary.ch2;
4766                 goto donode;
4767         case NREDIR:
4768         case NBACKGND:
4769                 n = n->nredir.n;
4770                 goto donode;
4771         case NNOT:
4772                 cmdputs("!");
4773                 n = n->nnot.com;
4774  donode:
4775                 cmdtxt(n);
4776                 break;
4777         case NIF:
4778                 cmdputs("if ");
4779                 cmdtxt(n->nif.test);
4780                 cmdputs("; then ");
4781                 if (n->nif.elsepart) {
4782                         cmdtxt(n->nif.ifpart);
4783                         cmdputs("; else ");
4784                         n = n->nif.elsepart;
4785                 } else {
4786                         n = n->nif.ifpart;
4787                 }
4788                 p = "; fi";
4789                 goto dotail;
4790         case NSUBSHELL:
4791                 cmdputs("(");
4792                 n = n->nredir.n;
4793                 p = ")";
4794                 goto dotail;
4795         case NWHILE:
4796                 p = "while ";
4797                 goto until;
4798         case NUNTIL:
4799                 p = "until ";
4800  until:
4801                 cmdputs(p);
4802                 cmdtxt(n->nbinary.ch1);
4803                 n = n->nbinary.ch2;
4804                 p = "; done";
4805  dodo:
4806                 cmdputs("; do ");
4807  dotail:
4808                 cmdtxt(n);
4809                 goto dotail2;
4810         case NFOR:
4811                 cmdputs("for ");
4812                 cmdputs(n->nfor.var);
4813                 cmdputs(" in ");
4814                 cmdlist(n->nfor.args, 1);
4815                 n = n->nfor.body;
4816                 p = "; done";
4817                 goto dodo;
4818         case NDEFUN:
4819                 cmdputs(n->narg.text);
4820                 p = "() { ... }";
4821                 goto dotail2;
4822         case NCMD:
4823                 cmdlist(n->ncmd.args, 1);
4824                 cmdlist(n->ncmd.redirect, 0);
4825                 break;
4826         case NARG:
4827                 p = n->narg.text;
4828  dotail2:
4829                 cmdputs(p);
4830                 break;
4831         case NHERE:
4832         case NXHERE:
4833                 p = "<<...";
4834                 goto dotail2;
4835         case NCASE:
4836                 cmdputs("case ");
4837                 cmdputs(n->ncase.expr->narg.text);
4838                 cmdputs(" in ");
4839                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4840                         cmdtxt(np->nclist.pattern);
4841                         cmdputs(") ");
4842                         cmdtxt(np->nclist.body);
4843                         cmdputs(";; ");
4844                 }
4845                 p = "esac";
4846                 goto dotail2;
4847         case NTO:
4848                 p = ">";
4849                 goto redir;
4850         case NCLOBBER:
4851                 p = ">|";
4852                 goto redir;
4853         case NAPPEND:
4854                 p = ">>";
4855                 goto redir;
4856 #if BASH_REDIR_OUTPUT
4857         case NTO2:
4858 #endif
4859         case NTOFD:
4860                 p = ">&";
4861                 goto redir;
4862         case NFROM:
4863                 p = "<";
4864                 goto redir;
4865         case NFROMFD:
4866                 p = "<&";
4867                 goto redir;
4868         case NFROMTO:
4869                 p = "<>";
4870  redir:
4871                 cmdputs(utoa(n->nfile.fd));
4872                 cmdputs(p);
4873                 if (n->type == NTOFD || n->type == NFROMFD) {
4874                         if (n->ndup.dupfd >= 0)
4875                                 cmdputs(utoa(n->ndup.dupfd));
4876                         else
4877                                 cmdputs("-");
4878                         break;
4879                 }
4880                 n = n->nfile.fname;
4881                 goto donode;
4882         }
4883 }
4884
4885 static char *
4886 commandtext(union node *n)
4887 {
4888         char *name;
4889
4890         STARTSTACKSTR(cmdnextc);
4891         cmdtxt(n);
4892         name = stackblock();
4893         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4894         return ckstrdup(name);
4895 }
4896 #endif /* JOBS */
4897
4898 /*
4899  * Fork off a subshell.  If we are doing job control, give the subshell its
4900  * own process group.  Jp is a job structure that the job is to be added to.
4901  * N is the command that will be evaluated by the child.  Both jp and n may
4902  * be NULL.  The mode parameter can be one of the following:
4903  *      FORK_FG - Fork off a foreground process.
4904  *      FORK_BG - Fork off a background process.
4905  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4906  *                   process group even if job control is on.
4907  *
4908  * When job control is turned off, background processes have their standard
4909  * input redirected to /dev/null (except for the second and later processes
4910  * in a pipeline).
4911  *
4912  * Called with interrupts off.
4913  */
4914 /*
4915  * Clear traps on a fork.
4916  */
4917 static void
4918 clear_traps(void)
4919 {
4920         char **tp;
4921
4922         INT_OFF;
4923         for (tp = trap; tp < &trap[NSIG]; tp++) {
4924                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4925                         if (trap_ptr == trap)
4926                                 free(*tp);
4927                         /* else: it "belongs" to trap_ptr vector, don't free */
4928                         *tp = NULL;
4929                         if ((tp - trap) != 0)
4930                                 setsignal(tp - trap);
4931                 }
4932         }
4933         may_have_traps = 0;
4934         INT_ON;
4935 }
4936
4937 /* Lives far away from here, needed for forkchild */
4938 static void closescript(void);
4939
4940 /* Called after fork(), in child */
4941 /* jp and n are NULL when called by openhere() for heredoc support */
4942 static NOINLINE void
4943 forkchild(struct job *jp, union node *n, int mode)
4944 {
4945         int oldlvl;
4946
4947         TRACE(("Child shell %d\n", getpid()));
4948         oldlvl = shlvl;
4949         shlvl++;
4950
4951         /* man bash: "Non-builtin commands run by bash have signal handlers
4952          * set to the values inherited by the shell from its parent".
4953          * Do we do it correctly? */
4954
4955         closescript();
4956
4957         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4958          && n && n->type == NCMD        /* is it single cmd? */
4959         /* && n->ncmd.args->type == NARG - always true? */
4960          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4961          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4962         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4963         ) {
4964                 TRACE(("Trap hack\n"));
4965                 /* Awful hack for `trap` or $(trap).
4966                  *
4967                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4968                  * contains an example where "trap" is executed in a subshell:
4969                  *
4970                  * save_traps=$(trap)
4971                  * ...
4972                  * eval "$save_traps"
4973                  *
4974                  * Standard does not say that "trap" in subshell shall print
4975                  * parent shell's traps. It only says that its output
4976                  * must have suitable form, but then, in the above example
4977                  * (which is not supposed to be normative), it implies that.
4978                  *
4979                  * bash (and probably other shell) does implement it
4980                  * (traps are reset to defaults, but "trap" still shows them),
4981                  * but as a result, "trap" logic is hopelessly messed up:
4982                  *
4983                  * # trap
4984                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4985                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4986                  * # true | trap   <--- trap is in subshell - no output (ditto)
4987                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4988                  * trap -- 'echo Ho' SIGWINCH
4989                  * # echo `(trap)`         <--- in subshell in subshell - output
4990                  * trap -- 'echo Ho' SIGWINCH
4991                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4992                  * trap -- 'echo Ho' SIGWINCH
4993                  *
4994                  * The rules when to forget and when to not forget traps
4995                  * get really complex and nonsensical.
4996                  *
4997                  * Our solution: ONLY bare $(trap) or `trap` is special.
4998                  */
4999                 /* Save trap handler strings for trap builtin to print */
5000                 trap_ptr = xmemdup(trap, sizeof(trap));
5001                 /* Fall through into clearing traps */
5002         }
5003         clear_traps();
5004 #if JOBS
5005         /* do job control only in root shell */
5006         doing_jobctl = 0;
5007         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5008                 pid_t pgrp;
5009
5010                 if (jp->nprocs == 0)
5011                         pgrp = getpid();
5012                 else
5013                         pgrp = jp->ps[0].ps_pid;
5014                 /* this can fail because we are doing it in the parent also */
5015                 setpgid(0, pgrp);
5016                 if (mode == FORK_FG)
5017                         xtcsetpgrp(ttyfd, pgrp);
5018                 setsignal(SIGTSTP);
5019                 setsignal(SIGTTOU);
5020         } else
5021 #endif
5022         if (mode == FORK_BG) {
5023                 /* man bash: "When job control is not in effect,
5024                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5025                 ignoresig(SIGINT);
5026                 ignoresig(SIGQUIT);
5027                 if (jp->nprocs == 0) {
5028                         close(0);
5029                         if (open(bb_dev_null, O_RDONLY) != 0)
5030                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5031                 }
5032         }
5033         if (oldlvl == 0) {
5034                 if (iflag) { /* why if iflag only? */
5035                         setsignal(SIGINT);
5036                         setsignal(SIGTERM);
5037                 }
5038                 /* man bash:
5039                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5040                  * commands run by bash have signal handlers
5041                  * set to the values inherited by the shell
5042                  * from its parent".
5043                  * Take care of the second rule: */
5044                 setsignal(SIGQUIT);
5045         }
5046 #if JOBS
5047         if (n && n->type == NCMD
5048          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5049         ) {
5050                 TRACE(("Job hack\n"));
5051                 /* "jobs": we do not want to clear job list for it,
5052                  * instead we remove only _its_ own_ job from job list.
5053                  * This makes "jobs .... | cat" more useful.
5054                  */
5055                 freejob(curjob);
5056                 return;
5057         }
5058 #endif
5059         for (jp = curjob; jp; jp = jp->prev_job)
5060                 freejob(jp);
5061         jobless = 0;
5062 }
5063
5064 /* Called after fork(), in parent */
5065 #if !JOBS
5066 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5067 #endif
5068 static void
5069 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5070 {
5071         TRACE(("In parent shell: child = %d\n", pid));
5072         if (!jp) {
5073                 /* jp is NULL when called by openhere() for heredoc support */
5074                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5075                         continue;
5076                 jobless++;
5077                 return;
5078         }
5079 #if JOBS
5080         if (mode != FORK_NOJOB && jp->jobctl) {
5081                 int pgrp;
5082
5083                 if (jp->nprocs == 0)
5084                         pgrp = pid;
5085                 else
5086                         pgrp = jp->ps[0].ps_pid;
5087                 /* This can fail because we are doing it in the child also */
5088                 setpgid(pid, pgrp);
5089         }
5090 #endif
5091         if (mode == FORK_BG) {
5092                 backgndpid = pid;               /* set $! */
5093                 set_curjob(jp, CUR_RUNNING);
5094         }
5095         if (jp) {
5096                 struct procstat *ps = &jp->ps[jp->nprocs++];
5097                 ps->ps_pid = pid;
5098                 ps->ps_status = -1;
5099                 ps->ps_cmd = nullstr;
5100 #if JOBS
5101                 if (doing_jobctl && n)
5102                         ps->ps_cmd = commandtext(n);
5103 #endif
5104         }
5105 }
5106
5107 /* jp and n are NULL when called by openhere() for heredoc support */
5108 static int
5109 forkshell(struct job *jp, union node *n, int mode)
5110 {
5111         int pid;
5112
5113         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5114         pid = fork();
5115         if (pid < 0) {
5116                 TRACE(("Fork failed, errno=%d", errno));
5117                 if (jp)
5118                         freejob(jp);
5119                 ash_msg_and_raise_perror("can't fork");
5120         }
5121         if (pid == 0) {
5122                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5123                 forkchild(jp, n, mode);
5124         } else {
5125                 forkparent(jp, n, mode, pid);
5126         }
5127         return pid;
5128 }
5129
5130 /*
5131  * Wait for job to finish.
5132  *
5133  * Under job control we have the problem that while a child process
5134  * is running interrupts generated by the user are sent to the child
5135  * but not to the shell.  This means that an infinite loop started by
5136  * an interactive user may be hard to kill.  With job control turned off,
5137  * an interactive user may place an interactive program inside a loop.
5138  * If the interactive program catches interrupts, the user doesn't want
5139  * these interrupts to also abort the loop.  The approach we take here
5140  * is to have the shell ignore interrupt signals while waiting for a
5141  * foreground process to terminate, and then send itself an interrupt
5142  * signal if the child process was terminated by an interrupt signal.
5143  * Unfortunately, some programs want to do a bit of cleanup and then
5144  * exit on interrupt; unless these processes terminate themselves by
5145  * sending a signal to themselves (instead of calling exit) they will
5146  * confuse this approach.
5147  *
5148  * Called with interrupts off.
5149  */
5150 static int
5151 waitforjob(struct job *jp)
5152 {
5153         int st;
5154
5155         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5156
5157         INT_OFF;
5158         while (jp->state == JOBRUNNING) {
5159                 /* In non-interactive shells, we _can_ get
5160                  * a keyboard signal here and be EINTRed,
5161                  * but we just loop back, waiting for command to complete.
5162                  *
5163                  * man bash:
5164                  * "If bash is waiting for a command to complete and receives
5165                  * a signal for which a trap has been set, the trap
5166                  * will not be executed until the command completes."
5167                  *
5168                  * Reality is that even if trap is not set, bash
5169                  * will not act on the signal until command completes.
5170                  * Try this. sleep5intoff.c:
5171                  * #include <signal.h>
5172                  * #include <unistd.h>
5173                  * int main() {
5174                  *         sigset_t set;
5175                  *         sigemptyset(&set);
5176                  *         sigaddset(&set, SIGINT);
5177                  *         sigaddset(&set, SIGQUIT);
5178                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5179                  *         sleep(5);
5180                  *         return 0;
5181                  * }
5182                  * $ bash -c './sleep5intoff; echo hi'
5183                  * ^C^C^C^C <--- pressing ^C once a second
5184                  * $ _
5185                  * $ bash -c './sleep5intoff; echo hi'
5186                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5187                  * $ _
5188                  */
5189                 dowait(DOWAIT_BLOCK, jp);
5190         }
5191         INT_ON;
5192
5193         st = getstatus(jp);
5194 #if JOBS
5195         if (jp->jobctl) {
5196                 xtcsetpgrp(ttyfd, rootpid);
5197                 restore_tty_if_stopped_or_signaled(jp);
5198
5199                 /*
5200                  * This is truly gross.
5201                  * If we're doing job control, then we did a TIOCSPGRP which
5202                  * caused us (the shell) to no longer be in the controlling
5203                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5204                  * intuit from the subprocess exit status whether a SIGINT
5205                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5206                  */
5207                 if (jp->sigint) /* TODO: do the same with all signals */
5208                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5209         }
5210         if (jp->state == JOBDONE)
5211 #endif
5212                 freejob(jp);
5213         return st;
5214 }
5215
5216 /*
5217  * return 1 if there are stopped jobs, otherwise 0
5218  */
5219 static int
5220 stoppedjobs(void)
5221 {
5222         struct job *jp;
5223         int retval;
5224
5225         retval = 0;
5226         if (job_warning)
5227                 goto out;
5228         jp = curjob;
5229         if (jp && jp->state == JOBSTOPPED) {
5230                 out2str("You have stopped jobs.\n");
5231                 job_warning = 2;
5232                 retval++;
5233         }
5234  out:
5235         return retval;
5236 }
5237
5238
5239 /*
5240  * Code for dealing with input/output redirection.
5241  */
5242
5243 #undef EMPTY
5244 #undef CLOSED
5245 #define EMPTY -2                /* marks an unused slot in redirtab */
5246 #define CLOSED -1               /* marks a slot of previously-closed fd */
5247
5248 /*
5249  * Handle here documents.  Normally we fork off a process to write the
5250  * data to a pipe.  If the document is short, we can stuff the data in
5251  * the pipe without forking.
5252  */
5253 /* openhere needs this forward reference */
5254 static void expandhere(union node *arg, int fd);
5255 static int
5256 openhere(union node *redir)
5257 {
5258         int pip[2];
5259         size_t len = 0;
5260
5261         if (pipe(pip) < 0)
5262                 ash_msg_and_raise_perror("can't create pipe");
5263         if (redir->type == NHERE) {
5264                 len = strlen(redir->nhere.doc->narg.text);
5265                 if (len <= PIPE_BUF) {
5266                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5267                         goto out;
5268                 }
5269         }
5270         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5271                 /* child */
5272                 close(pip[0]);
5273                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5274                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5275                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5276                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5277                 signal(SIGPIPE, SIG_DFL);
5278                 if (redir->type == NHERE)
5279                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5280                 else /* NXHERE */
5281                         expandhere(redir->nhere.doc, pip[1]);
5282                 _exit(EXIT_SUCCESS);
5283         }
5284  out:
5285         close(pip[1]);
5286         return pip[0];
5287 }
5288
5289 static int
5290 openredirect(union node *redir)
5291 {
5292         struct stat sb;
5293         char *fname;
5294         int f;
5295
5296         switch (redir->nfile.type) {
5297 /* Can't happen, our single caller does this itself */
5298 //      case NTOFD:
5299 //      case NFROMFD:
5300 //              return -1;
5301         case NHERE:
5302         case NXHERE:
5303                 return openhere(redir);
5304         }
5305
5306         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5307          * allocated space. Do it only when we know it is safe.
5308          */
5309         fname = redir->nfile.expfname;
5310
5311         switch (redir->nfile.type) {
5312         default:
5313 #if DEBUG
5314                 abort();
5315 #endif
5316         case NFROM:
5317                 f = open(fname, O_RDONLY);
5318                 if (f < 0)
5319                         goto eopen;
5320                 break;
5321         case NFROMTO:
5322                 f = open(fname, O_RDWR|O_CREAT, 0666);
5323                 if (f < 0)
5324                         goto ecreate;
5325                 break;
5326         case NTO:
5327 #if BASH_REDIR_OUTPUT
5328         case NTO2:
5329 #endif
5330                 /* Take care of noclobber mode. */
5331                 if (Cflag) {
5332                         if (stat(fname, &sb) < 0) {
5333                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5334                                 if (f < 0)
5335                                         goto ecreate;
5336                         } else if (!S_ISREG(sb.st_mode)) {
5337                                 f = open(fname, O_WRONLY, 0666);
5338                                 if (f < 0)
5339                                         goto ecreate;
5340                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5341                                         close(f);
5342                                         errno = EEXIST;
5343                                         goto ecreate;
5344                                 }
5345                         } else {
5346                                 errno = EEXIST;
5347                                 goto ecreate;
5348                         }
5349                         break;
5350                 }
5351                 /* FALLTHROUGH */
5352         case NCLOBBER:
5353                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5354                 if (f < 0)
5355                         goto ecreate;
5356                 break;
5357         case NAPPEND:
5358                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5359                 if (f < 0)
5360                         goto ecreate;
5361                 break;
5362         }
5363
5364         return f;
5365  ecreate:
5366         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5367  eopen:
5368         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5369 }
5370
5371 /*
5372  * Copy a file descriptor to be >= 10. Throws exception on error.
5373  */
5374 static int
5375 savefd(int from)
5376 {
5377         int newfd;
5378         int err;
5379
5380         newfd = fcntl(from, F_DUPFD, 10);
5381         err = newfd < 0 ? errno : 0;
5382         if (err != EBADF) {
5383                 if (err)
5384                         ash_msg_and_raise_perror("%d", from);
5385                 close(from);
5386                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5387         }
5388
5389         return newfd;
5390 }
5391 static int
5392 dup2_or_raise(int from, int to)
5393 {
5394         int newfd;
5395
5396         newfd = (from != to) ? dup2(from, to) : to;
5397         if (newfd < 0) {
5398                 /* Happens when source fd is not open: try "echo >&99" */
5399                 ash_msg_and_raise_perror("%d", from);
5400         }
5401         return newfd;
5402 }
5403 static int
5404 fcntl_F_DUPFD(int fd, int avoid_fd)
5405 {
5406         int newfd;
5407  repeat:
5408         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5409         if (newfd < 0) {
5410                 if (errno == EBUSY)
5411                         goto repeat;
5412                 if (errno == EINTR)
5413                         goto repeat;
5414         }
5415         return newfd;
5416 }
5417 static int
5418 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5419 {
5420         int newfd;
5421  repeat:
5422         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5423         if (newfd < 0) {
5424                 if (errno == EBUSY)
5425                         goto repeat;
5426                 if (errno == EINTR)
5427                         goto repeat;
5428                 /* fd was not open? */
5429                 if (errno == EBADF)
5430                         return fd;
5431                 ash_msg_and_raise_perror("%d", newfd);
5432         }
5433         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5434         close(fd);
5435         return newfd;
5436 }
5437
5438 /* Struct def and variable are moved down to the first usage site */
5439 struct squirrel {
5440         int orig_fd;
5441         int moved_to;
5442 };
5443 struct redirtab {
5444         struct redirtab *next;
5445         int pair_count;
5446         struct squirrel two_fd[];
5447 };
5448 #define redirlist (G_var.redirlist)
5449
5450 static void
5451 add_squirrel_closed(struct redirtab *sq, int fd)
5452 {
5453         int i;
5454
5455         if (!sq)
5456                 return;
5457
5458         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5459                 /* If we collide with an already moved fd... */
5460                 if (fd == sq->two_fd[i].orig_fd) {
5461                         /* Examples:
5462                          * "echo 3>FILE 3>&- 3>FILE"
5463                          * "echo 3>&- 3>FILE"
5464                          * No need for last redirect to insert
5465                          * another "need to close 3" indicator.
5466                          */
5467                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5468                         return;
5469                 }
5470         }
5471         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5472         sq->two_fd[i].orig_fd = fd;
5473         sq->two_fd[i].moved_to = CLOSED;
5474 }
5475
5476 static int
5477 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5478 {
5479         int i, new_fd;
5480
5481         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5482                 avoid_fd = 9;
5483
5484 #if JOBS
5485         if (fd == ttyfd) {
5486                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5487                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5488                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5489                 return 1; /* "we closed fd" */
5490         }
5491 #endif
5492         /* Are we called from redirect(0)? E.g. redirect
5493          * in a forked child. No need to save fds,
5494          * we aren't going to use them anymore, ok to trash.
5495          */
5496         if (!sq)
5497                 return 0;
5498
5499         /* If this one of script's fds? */
5500         if (fd != 0) {
5501                 struct parsefile *pf = g_parsefile;
5502                 while (pf) {
5503                         /* We skip fd == 0 case because of the following:
5504                          * $ ash  # running ash interactively
5505                          * $ . ./script.sh
5506                          * and in script.sh: "exec 9>&0".
5507                          * Even though top-level pf_fd _is_ 0,
5508                          * it's still ok to use it: "read" builtin uses it,
5509                          * why should we cripple "exec" builtin?
5510                          */
5511                         if (fd == pf->pf_fd) {
5512                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5513                                 return 1; /* "we closed fd" */
5514                         }
5515                         pf = pf->prev;
5516                 }
5517         }
5518
5519         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5520
5521         /* First: do we collide with some already moved fds? */
5522         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5523                 /* If we collide with an already moved fd... */
5524                 if (fd == sq->two_fd[i].moved_to) {
5525                         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5526                         sq->two_fd[i].moved_to = new_fd;
5527                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5528                         if (new_fd < 0) /* what? */
5529                                 xfunc_die();
5530                         return 0; /* "we did not close fd" */
5531                 }
5532                 if (fd == sq->two_fd[i].orig_fd) {
5533                         /* Example: echo Hello >/dev/null 1>&2 */
5534                         TRACE(("redirect_fd %d: already moved\n", fd));
5535                         return 0; /* "we did not close fd" */
5536                 }
5537         }
5538
5539         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5540         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5541         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5542         if (new_fd < 0) {
5543                 if (errno != EBADF)
5544                         xfunc_die();
5545                 /* new_fd = CLOSED; - already is -1 */
5546         }
5547         sq->two_fd[i].moved_to = new_fd;
5548         sq->two_fd[i].orig_fd = fd;
5549
5550         /* if we move stderr, let "set -x" code know */
5551         if (fd == preverrout_fd)
5552                 preverrout_fd = new_fd;
5553
5554         return 0; /* "we did not close fd" */
5555 }
5556
5557 static int
5558 internally_opened_fd(int fd, struct redirtab *sq)
5559 {
5560         int i;
5561 #if JOBS
5562         if (fd == ttyfd)
5563                 return 1;
5564 #endif
5565         /* If this one of script's fds? */
5566         if (fd != 0) {
5567                 struct parsefile *pf = g_parsefile;
5568                 while (pf) {
5569                         if (fd == pf->pf_fd)
5570                                 return 1;
5571                         pf = pf->prev;
5572                 }
5573         }
5574
5575         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5576                 if (fd == sq->two_fd[i].moved_to)
5577                         return 1;
5578         }
5579         return 0;
5580 }
5581
5582 /*
5583  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5584  * old file descriptors are stashed away so that the redirection can be
5585  * undone by calling popredir.
5586  */
5587 /* flags passed to redirect */
5588 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5589 static void
5590 redirect(union node *redir, int flags)
5591 {
5592         struct redirtab *sv;
5593
5594         if (!redir)
5595                 return;
5596
5597         sv = NULL;
5598         INT_OFF;
5599         if (flags & REDIR_PUSH)
5600                 sv = redirlist;
5601         do {
5602                 int fd;
5603                 int newfd;
5604                 int close_fd;
5605                 int closed;
5606
5607                 fd = redir->nfile.fd;
5608                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5609                         //bb_error_msg("doing %d > %d", fd, newfd);
5610                         newfd = redir->ndup.dupfd;
5611                         close_fd = -1;
5612                 } else {
5613                         newfd = openredirect(redir); /* always >= 0 */
5614                         if (fd == newfd) {
5615                                 /* open() gave us precisely the fd we wanted.
5616                                  * This means that this fd was not busy
5617                                  * (not opened to anywhere).
5618                                  * Remember to close it on restore:
5619                                  */
5620                                 add_squirrel_closed(sv, fd);
5621                                 continue;
5622                         }
5623                         close_fd = newfd;
5624                 }
5625
5626                 if (fd == newfd)
5627                         continue;
5628
5629                 /* if "N>FILE": move newfd to fd */
5630                 /* if "N>&M": dup newfd to fd */
5631                 /* if "N>&-": close fd (newfd is -1) */
5632
5633  IF_BASH_REDIR_OUTPUT(redirect_more:)
5634
5635                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5636                 if (newfd == -1) {
5637                         /* "N>&-" means "close me" */
5638                         if (!closed) {
5639                                 /* ^^^ optimization: saving may already
5640                                  * have closed it. If not... */
5641                                 close(fd);
5642                         }
5643                 } else {
5644                         /* if newfd is a script fd or saved fd, simulate EBADF */
5645                         if (internally_opened_fd(newfd, sv)) {
5646                                 errno = EBADF;
5647                                 ash_msg_and_raise_perror("%d", newfd);
5648                         }
5649                         dup2_or_raise(newfd, fd);
5650                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5651                                 close(close_fd);
5652 #if BASH_REDIR_OUTPUT
5653                         if (redir->nfile.type == NTO2 && fd == 1) {
5654                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5655                                 fd = 2;
5656                                 newfd = 1;
5657                                 close_fd = -1;
5658                                 goto redirect_more;
5659                         }
5660 #endif
5661                 }
5662         } while ((redir = redir->nfile.next) != NULL);
5663         INT_ON;
5664
5665 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5666 #define REDIR_SAVEFD2 0
5667         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5668         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5669         // not only for calls with flags containing REDIR_SAVEFD2.
5670         // We do this unconditionally (see save_fd_on_redirect()).
5671         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5672         //      preverrout_fd = copied_fd2;
5673 }
5674
5675 static int
5676 redirectsafe(union node *redir, int flags)
5677 {
5678         int err;
5679         volatile int saveint;
5680         struct jmploc *volatile savehandler = exception_handler;
5681         struct jmploc jmploc;
5682
5683         SAVE_INT(saveint);
5684         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5685         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5686         if (!err) {
5687                 exception_handler = &jmploc;
5688                 redirect(redir, flags);
5689         }
5690         exception_handler = savehandler;
5691         if (err && exception_type != EXERROR)
5692                 longjmp(exception_handler->loc, 1);
5693         RESTORE_INT(saveint);
5694         return err;
5695 }
5696
5697 static struct redirtab*
5698 pushredir(union node *redir)
5699 {
5700         struct redirtab *sv;
5701         int i;
5702
5703         if (!redir)
5704                 return redirlist;
5705
5706         i = 0;
5707         do {
5708                 i++;
5709 #if BASH_REDIR_OUTPUT
5710                 if (redir->nfile.type == NTO2)
5711                         i++;
5712 #endif
5713                 redir = redir->nfile.next;
5714         } while (redir);
5715
5716         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5717         sv->pair_count = i;
5718         while (--i >= 0)
5719                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5720         sv->next = redirlist;
5721         redirlist = sv;
5722         return sv->next;
5723 }
5724
5725 /*
5726  * Undo the effects of the last redirection.
5727  */
5728 static void
5729 popredir(int drop)
5730 {
5731         struct redirtab *rp;
5732         int i;
5733
5734         if (redirlist == NULL)
5735                 return;
5736         INT_OFF;
5737         rp = redirlist;
5738         for (i = 0; i < rp->pair_count; i++) {
5739                 int fd = rp->two_fd[i].orig_fd;
5740                 int copy = rp->two_fd[i].moved_to;
5741                 if (copy == CLOSED) {
5742                         if (!drop)
5743                                 close(fd);
5744                         continue;
5745                 }
5746                 if (copy != EMPTY) {
5747                         if (!drop) {
5748                                 /*close(fd);*/
5749                                 dup2_or_raise(copy, fd);
5750                         }
5751                         close(copy);
5752                 }
5753         }
5754         redirlist = rp->next;
5755         free(rp);
5756         INT_ON;
5757 }
5758
5759 static void
5760 unwindredir(struct redirtab *stop)
5761 {
5762         while (redirlist != stop)
5763                 popredir(/*drop:*/ 0);
5764 }
5765
5766
5767 /* ============ Routines to expand arguments to commands
5768  *
5769  * We have to deal with backquotes, shell variables, and file metacharacters.
5770  */
5771
5772 #if ENABLE_FEATURE_SH_MATH
5773 static arith_t
5774 ash_arith(const char *s)
5775 {
5776         arith_state_t math_state;
5777         arith_t result;
5778
5779         math_state.lookupvar = lookupvar;
5780         math_state.setvar    = setvar0;
5781         //math_state.endofname = endofname;
5782
5783         INT_OFF;
5784         result = arith(&math_state, s);
5785         if (math_state.errmsg)
5786                 ash_msg_and_raise_error(math_state.errmsg);
5787         INT_ON;
5788
5789         return result;
5790 }
5791 #endif
5792 #if BASH_SUBSTR
5793 # if ENABLE_FEATURE_SH_MATH
5794 static int substr_atoi(const char *s)
5795 {
5796         arith_t t = ash_arith(s);
5797         if (sizeof(t) > sizeof(int)) {
5798                 /* clamp very large or very large negative nums for ${v:N:M}:
5799                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5800                  */
5801                 if (t > INT_MAX)
5802                         t = INT_MAX;
5803                 if (t < INT_MIN)
5804                         t = INT_MIN;
5805         }
5806         return t;
5807 }
5808 # else
5809 #  define substr_atoi(s) number(s)
5810 # endif
5811 #endif
5812
5813 /*
5814  * expandarg flags
5815  */
5816 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5817 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5818 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5819 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5820 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5821  * POSIX says for this case:
5822  *  Pathname expansion shall not be performed on the word by a
5823  *  non-interactive shell; an interactive shell may perform it, but shall
5824  *  do so only when the expansion would result in one word.
5825  * Currently, our code complies to the above rule by never globbing
5826  * redirection filenames.
5827  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5828  * (this means that on a typical Linux distro, bash almost always
5829  * performs globbing, and thus diverges from what we do).
5830  */
5831 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5832 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5833 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5834 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5835 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5836 /*
5837  * rmescape() flags
5838  */
5839 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5840 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5841 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5842 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5843
5844 /* Add CTLESC when necessary. */
5845 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5846 /* Do not skip NUL characters. */
5847 #define QUOTES_KEEPNUL EXP_TILDE
5848
5849 /*
5850  * Structure specifying which parts of the string should be searched
5851  * for IFS characters.
5852  */
5853 struct ifsregion {
5854         struct ifsregion *next; /* next region in list */
5855         int begoff;             /* offset of start of region */
5856         int endoff;             /* offset of end of region */
5857         int nulonly;            /* search for nul bytes only */
5858 };
5859
5860 struct arglist {
5861         struct strlist *list;
5862         struct strlist **lastp;
5863 };
5864
5865 /* output of current string */
5866 static char *expdest;
5867 /* list of back quote expressions */
5868 static struct nodelist *argbackq;
5869 /* first struct in list of ifs regions */
5870 static struct ifsregion ifsfirst;
5871 /* last struct in list */
5872 static struct ifsregion *ifslastp;
5873 /* holds expanded arg list */
5874 static struct arglist exparg;
5875
5876 /*
5877  * Our own itoa().
5878  * cvtnum() is used even if math support is off (to prepare $? values and such).
5879  */
5880 static int
5881 cvtnum(arith_t num)
5882 {
5883         int len;
5884
5885         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5886         len = sizeof(arith_t) * 3;
5887         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5888         if (sizeof(arith_t) < 4) len += 2;
5889
5890         expdest = makestrspace(len, expdest);
5891         len = fmtstr(expdest, len, ARITH_FMT, num);
5892         STADJUST(len, expdest);
5893         return len;
5894 }
5895
5896 /*
5897  * Break the argument string into pieces based upon IFS and add the
5898  * strings to the argument list.  The regions of the string to be
5899  * searched for IFS characters have been stored by recordregion.
5900  */
5901 static void
5902 ifsbreakup(char *string, struct arglist *arglist)
5903 {
5904         struct ifsregion *ifsp;
5905         struct strlist *sp;
5906         char *start;
5907         char *p;
5908         char *q;
5909         const char *ifs, *realifs;
5910         int ifsspc;
5911         int nulonly;
5912
5913         start = string;
5914         if (ifslastp != NULL) {
5915                 ifsspc = 0;
5916                 nulonly = 0;
5917                 realifs = ifsset() ? ifsval() : defifs;
5918                 ifsp = &ifsfirst;
5919                 do {
5920                         p = string + ifsp->begoff;
5921                         nulonly = ifsp->nulonly;
5922                         ifs = nulonly ? nullstr : realifs;
5923                         ifsspc = 0;
5924                         while (p < string + ifsp->endoff) {
5925                                 q = p;
5926                                 if ((unsigned char)*p == CTLESC)
5927                                         p++;
5928                                 if (!strchr(ifs, *p)) {
5929                                         p++;
5930                                         continue;
5931                                 }
5932                                 if (!nulonly)
5933                                         ifsspc = (strchr(defifs, *p) != NULL);
5934                                 /* Ignore IFS whitespace at start */
5935                                 if (q == start && ifsspc) {
5936                                         p++;
5937                                         start = p;
5938                                         continue;
5939                                 }
5940                                 *q = '\0';
5941                                 sp = stzalloc(sizeof(*sp));
5942                                 sp->text = start;
5943                                 *arglist->lastp = sp;
5944                                 arglist->lastp = &sp->next;
5945                                 p++;
5946                                 if (!nulonly) {
5947                                         for (;;) {
5948                                                 if (p >= string + ifsp->endoff) {
5949                                                         break;
5950                                                 }
5951                                                 q = p;
5952                                                 if ((unsigned char)*p == CTLESC)
5953                                                         p++;
5954                                                 if (strchr(ifs, *p) == NULL) {
5955                                                         p = q;
5956                                                         break;
5957                                                 }
5958                                                 if (strchr(defifs, *p) == NULL) {
5959                                                         if (ifsspc) {
5960                                                                 p++;
5961                                                                 ifsspc = 0;
5962                                                         } else {
5963                                                                 p = q;
5964                                                                 break;
5965                                                         }
5966                                                 } else
5967                                                         p++;
5968                                         }
5969                                 }
5970                                 start = p;
5971                         } /* while */
5972                         ifsp = ifsp->next;
5973                 } while (ifsp != NULL);
5974                 if (nulonly)
5975                         goto add;
5976         }
5977
5978         if (!*start)
5979                 return;
5980
5981  add:
5982         sp = stzalloc(sizeof(*sp));
5983         sp->text = start;
5984         *arglist->lastp = sp;
5985         arglist->lastp = &sp->next;
5986 }
5987
5988 static void
5989 ifsfree(void)
5990 {
5991         struct ifsregion *p = ifsfirst.next;
5992
5993         if (!p)
5994                 goto out;
5995
5996         INT_OFF;
5997         do {
5998                 struct ifsregion *ifsp;
5999                 ifsp = p->next;
6000                 free(p);
6001                 p = ifsp;
6002         } while (p);
6003         ifsfirst.next = NULL;
6004         INT_ON;
6005  out:
6006         ifslastp = NULL;
6007 }
6008
6009 static size_t
6010 esclen(const char *start, const char *p)
6011 {
6012         size_t esc = 0;
6013
6014         while (p > start && (unsigned char)*--p == CTLESC) {
6015                 esc++;
6016         }
6017         return esc;
6018 }
6019
6020 /*
6021  * Remove any CTLESC characters from a string.
6022  */
6023 #if !BASH_PATTERN_SUBST
6024 #define rmescapes(str, flag, slash_position) \
6025         rmescapes(str, flag)
6026 #endif
6027 static char *
6028 rmescapes(char *str, int flag, int *slash_position)
6029 {
6030         static const char qchars[] ALIGN1 = {
6031                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6032
6033         char *p, *q, *r;
6034         unsigned inquotes;
6035         unsigned protect_against_glob;
6036         unsigned globbing;
6037
6038         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6039         if (!p)
6040                 return str;
6041
6042         q = p;
6043         r = str;
6044         if (flag & RMESCAPE_ALLOC) {
6045                 size_t len = p - str;
6046                 size_t fulllen = len + strlen(p) + 1;
6047
6048                 if (flag & RMESCAPE_GROW) {
6049                         int strloc = str - (char *)stackblock();
6050                         r = makestrspace(fulllen, expdest);
6051                         /* p and str may be invalidated by makestrspace */
6052                         str = (char *)stackblock() + strloc;
6053                         p = str + len;
6054                 } else if (flag & RMESCAPE_HEAP) {
6055                         r = ckmalloc(fulllen);
6056                 } else {
6057                         r = stalloc(fulllen);
6058                 }
6059                 q = r;
6060                 if (len > 0) {
6061                         q = (char *)mempcpy(q, str, len);
6062                 }
6063         }
6064
6065         inquotes = 0;
6066         globbing = flag & RMESCAPE_GLOB;
6067         protect_against_glob = globbing;
6068         while (*p) {
6069                 if ((unsigned char)*p == CTLQUOTEMARK) {
6070 // Note: both inquotes and protect_against_glob only affect whether
6071 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6072                         inquotes = ~inquotes;
6073                         p++;
6074                         protect_against_glob = globbing;
6075                         continue;
6076                 }
6077                 if ((unsigned char)*p == CTLESC) {
6078                         p++;
6079 #if DEBUG
6080                         if (*p == '\0')
6081                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6082 #endif
6083                         if (protect_against_glob) {
6084                                 /*
6085                                  * We used to trust glob() and fnmatch() to eat
6086                                  * superfluous escapes (\z where z has no
6087                                  * special meaning anyway). But this causes
6088                                  * bugs such as string of one greek letter rho
6089                                  * (unicode-encoded as two bytes "cf,81")
6090                                  * getting encoded as "cf,CTLESC,81"
6091                                  * and here, converted to "cf,\,81" -
6092                                  * which does not go well with some flavors
6093                                  * of fnmatch() in unicode locales
6094                                  * (for example, glibc <= 2.22).
6095                                  *
6096                                  * Lets add "\" only on the chars which need it.
6097                                  * Testcases for less obvious chars are shown.
6098                                  */
6099                                 if (*p == '*'
6100                                  || *p == '?'
6101                                  || *p == '['
6102                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6103                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6104                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6105                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6106                                 /* Some libc support [^negate], that's why "^" also needs love */
6107                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6108                                 ) {
6109                                         *q++ = '\\';
6110                                 }
6111                         }
6112                 } else if (*p == '\\' && !inquotes) {
6113                         /* naked back slash */
6114                         protect_against_glob = 0;
6115                         goto copy;
6116                 }
6117 #if BASH_PATTERN_SUBST
6118                 else if (slash_position && p == str + *slash_position) {
6119                         /* stop handling globbing */
6120                         globbing = 0;
6121                         *slash_position = q - r;
6122                         slash_position = NULL;
6123                 }
6124 #endif
6125                 protect_against_glob = globbing;
6126  copy:
6127                 *q++ = *p++;
6128         }
6129         *q = '\0';
6130         if (flag & RMESCAPE_GROW) {
6131                 expdest = r;
6132                 STADJUST(q - r + 1, expdest);
6133         }
6134         return r;
6135 }
6136 #define pmatch(a, b) !fnmatch((a), (b), 0)
6137
6138 /*
6139  * Prepare a pattern for a expmeta (internal glob(3)) call.
6140  *
6141  * Returns an stalloced string.
6142  */
6143 static char *
6144 preglob(const char *pattern, int flag)
6145 {
6146         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6147 }
6148
6149 /*
6150  * Put a string on the stack.
6151  */
6152 static void
6153 memtodest(const char *p, size_t len, int syntax, int quotes)
6154 {
6155         char *q;
6156
6157         if (!len)
6158                 return;
6159
6160         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6161
6162         do {
6163                 unsigned char c = *p++;
6164                 if (c) {
6165                         if (quotes & QUOTES_ESC) {
6166                                 int n = SIT(c, syntax);
6167                                 if (n == CCTL
6168                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6169                                      && n == CBACK
6170                                     )
6171                                 ) {
6172                                         USTPUTC(CTLESC, q);
6173                                 }
6174                         }
6175                 } else if (!(quotes & QUOTES_KEEPNUL))
6176                         continue;
6177                 USTPUTC(c, q);
6178         } while (--len);
6179
6180         expdest = q;
6181 }
6182
6183 static size_t
6184 strtodest(const char *p, int syntax, int quotes)
6185 {
6186         size_t len = strlen(p);
6187         memtodest(p, len, syntax, quotes);
6188         return len;
6189 }
6190
6191 /*
6192  * Record the fact that we have to scan this region of the
6193  * string for IFS characters.
6194  */
6195 static void
6196 recordregion(int start, int end, int nulonly)
6197 {
6198         struct ifsregion *ifsp;
6199
6200         if (ifslastp == NULL) {
6201                 ifsp = &ifsfirst;
6202         } else {
6203                 INT_OFF;
6204                 ifsp = ckzalloc(sizeof(*ifsp));
6205                 /*ifsp->next = NULL; - ckzalloc did it */
6206                 ifslastp->next = ifsp;
6207                 INT_ON;
6208         }
6209         ifslastp = ifsp;
6210         ifslastp->begoff = start;
6211         ifslastp->endoff = end;
6212         ifslastp->nulonly = nulonly;
6213 }
6214
6215 static void
6216 removerecordregions(int endoff)
6217 {
6218         if (ifslastp == NULL)
6219                 return;
6220
6221         if (ifsfirst.endoff > endoff) {
6222                 while (ifsfirst.next) {
6223                         struct ifsregion *ifsp;
6224                         INT_OFF;
6225                         ifsp = ifsfirst.next->next;
6226                         free(ifsfirst.next);
6227                         ifsfirst.next = ifsp;
6228                         INT_ON;
6229                 }
6230                 if (ifsfirst.begoff > endoff) {
6231                         ifslastp = NULL;
6232                 } else {
6233                         ifslastp = &ifsfirst;
6234                         ifsfirst.endoff = endoff;
6235                 }
6236                 return;
6237         }
6238
6239         ifslastp = &ifsfirst;
6240         while (ifslastp->next && ifslastp->next->begoff < endoff)
6241                 ifslastp = ifslastp->next;
6242         while (ifslastp->next) {
6243                 struct ifsregion *ifsp;
6244                 INT_OFF;
6245                 ifsp = ifslastp->next->next;
6246                 free(ifslastp->next);
6247                 ifslastp->next = ifsp;
6248                 INT_ON;
6249         }
6250         if (ifslastp->endoff > endoff)
6251                 ifslastp->endoff = endoff;
6252 }
6253
6254 static char *
6255 exptilde(char *startp, char *p, int flags)
6256 {
6257         unsigned char c;
6258         char *name;
6259         struct passwd *pw;
6260         const char *home;
6261         int quotes = flags & QUOTES_ESC;
6262
6263         name = p + 1;
6264
6265         while ((c = *++p) != '\0') {
6266                 switch (c) {
6267                 case CTLESC:
6268                         return startp;
6269                 case CTLQUOTEMARK:
6270                         return startp;
6271                 case ':':
6272                         if (flags & EXP_VARTILDE)
6273                                 goto done;
6274                         break;
6275                 case '/':
6276                 case CTLENDVAR:
6277                         goto done;
6278                 }
6279         }
6280  done:
6281         *p = '\0';
6282         if (*name == '\0') {
6283                 home = lookupvar("HOME");
6284         } else {
6285                 pw = getpwnam(name);
6286                 if (pw == NULL)
6287                         goto lose;
6288                 home = pw->pw_dir;
6289         }
6290         if (!home || !*home)
6291                 goto lose;
6292         *p = c;
6293         strtodest(home, SQSYNTAX, quotes);
6294         return p;
6295  lose:
6296         *p = c;
6297         return startp;
6298 }
6299
6300 /*
6301  * Execute a command inside back quotes.  If it's a builtin command, we
6302  * want to save its output in a block obtained from malloc.  Otherwise
6303  * we fork off a subprocess and get the output of the command via a pipe.
6304  * Should be called with interrupts off.
6305  */
6306 struct backcmd {                /* result of evalbackcmd */
6307         int fd;                 /* file descriptor to read from */
6308         int nleft;              /* number of chars in buffer */
6309         char *buf;              /* buffer */
6310         struct job *jp;         /* job structure for command */
6311 };
6312
6313 /* These forward decls are needed to use "eval" code for backticks handling: */
6314 /* flags in argument to evaltree */
6315 #define EV_EXIT    01           /* exit after evaluating tree */
6316 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6317 static int evaltree(union node *, int);
6318
6319 /* An evaltree() which is known to never return.
6320  * Used to use an alias:
6321  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6322  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6323  */
6324 static ALWAYS_INLINE NORETURN void
6325 evaltreenr(union node *n, int flags)
6326 {
6327         evaltree(n, flags);
6328         bb_unreachable(abort());
6329         /* NOTREACHED */
6330 }
6331
6332 static void FAST_FUNC
6333 evalbackcmd(union node *n, struct backcmd *result)
6334 {
6335         int pip[2];
6336         struct job *jp;
6337
6338         result->fd = -1;
6339         result->buf = NULL;
6340         result->nleft = 0;
6341         result->jp = NULL;
6342         if (n == NULL) {
6343                 goto out;
6344         }
6345
6346         if (pipe(pip) < 0)
6347                 ash_msg_and_raise_perror("can't create pipe");
6348         jp = makejob(/*n,*/ 1);
6349         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6350                 /* child */
6351                 FORCE_INT_ON;
6352                 close(pip[0]);
6353                 if (pip[1] != 1) {
6354                         /*close(1);*/
6355                         dup2_or_raise(pip[1], 1);
6356                         close(pip[1]);
6357                 }
6358 /* TODO: eflag clearing makes the following not abort:
6359  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6360  * which is what bash does (unless it is in POSIX mode).
6361  * dash deleted "eflag = 0" line in the commit
6362  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6363  *  [EVAL] Don't clear eflag in evalbackcmd
6364  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6365  */
6366                 eflag = 0;
6367                 ifsfree();
6368                 evaltreenr(n, EV_EXIT);
6369                 /* NOTREACHED */
6370         }
6371         /* parent */
6372         close(pip[1]);
6373         result->fd = pip[0];
6374         result->jp = jp;
6375
6376  out:
6377         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6378                 result->fd, result->buf, result->nleft, result->jp));
6379 }
6380
6381 /*
6382  * Expand stuff in backwards quotes.
6383  */
6384 static void
6385 expbackq(union node *cmd, int flag)
6386 {
6387         struct backcmd in;
6388         int i;
6389         char buf[128];
6390         char *p;
6391         char *dest;
6392         int startloc;
6393         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6394         struct stackmark smark;
6395
6396         INT_OFF;
6397         startloc = expdest - (char *)stackblock();
6398         pushstackmark(&smark, startloc);
6399         evalbackcmd(cmd, &in);
6400         popstackmark(&smark);
6401
6402         p = in.buf;
6403         i = in.nleft;
6404         if (i == 0)
6405                 goto read;
6406         for (;;) {
6407                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6408  read:
6409                 if (in.fd < 0)
6410                         break;
6411                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6412                 TRACE(("expbackq: read returns %d\n", i));
6413                 if (i <= 0)
6414                         break;
6415                 p = buf;
6416         }
6417
6418         free(in.buf);
6419         if (in.fd >= 0) {
6420                 close(in.fd);
6421                 back_exitstatus = waitforjob(in.jp);
6422         }
6423         INT_ON;
6424
6425         /* Eat all trailing newlines */
6426         dest = expdest;
6427         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6428                 STUNPUTC(dest);
6429         expdest = dest;
6430
6431         if (!(flag & EXP_QUOTED))
6432                 recordregion(startloc, dest - (char *)stackblock(), 0);
6433         TRACE(("evalbackq: size:%d:'%.*s'\n",
6434                 (int)((dest - (char *)stackblock()) - startloc),
6435                 (int)((dest - (char *)stackblock()) - startloc),
6436                 stackblock() + startloc));
6437 }
6438
6439 #if ENABLE_FEATURE_SH_MATH
6440 /*
6441  * Expand arithmetic expression.  Backup to start of expression,
6442  * evaluate, place result in (backed up) result, adjust string position.
6443  */
6444 static void
6445 expari(int flag)
6446 {
6447         char *p, *start;
6448         int begoff;
6449         int len;
6450
6451         /* ifsfree(); */
6452
6453         /*
6454          * This routine is slightly over-complicated for
6455          * efficiency.  Next we scan backwards looking for the
6456          * start of arithmetic.
6457          */
6458         start = stackblock();
6459         p = expdest - 1;
6460         *p = '\0';
6461         p--;
6462         while (1) {
6463                 int esc;
6464
6465                 while ((unsigned char)*p != CTLARI) {
6466                         p--;
6467 #if DEBUG
6468                         if (p < start) {
6469                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6470                         }
6471 #endif
6472                 }
6473
6474                 esc = esclen(start, p);
6475                 if (!(esc % 2)) {
6476                         break;
6477                 }
6478
6479                 p -= esc + 1;
6480         }
6481
6482         begoff = p - start;
6483
6484         removerecordregions(begoff);
6485
6486         expdest = p;
6487
6488         if (flag & QUOTES_ESC)
6489                 rmescapes(p + 1, 0, NULL);
6490
6491         len = cvtnum(ash_arith(p + 1));
6492
6493         if (!(flag & EXP_QUOTED))
6494                 recordregion(begoff, begoff + len, 0);
6495 }
6496 #endif
6497
6498 /* argstr needs it */
6499 static char *evalvar(char *p, int flags);
6500
6501 /*
6502  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6503  * characters to allow for further processing.  Otherwise treat
6504  * $@ like $* since no splitting will be performed.
6505  */
6506 static void
6507 argstr(char *p, int flags)
6508 {
6509         static const char spclchars[] ALIGN1 = {
6510                 '=',
6511                 ':',
6512                 CTLQUOTEMARK,
6513                 CTLENDVAR,
6514                 CTLESC,
6515                 CTLVAR,
6516                 CTLBACKQ,
6517 #if ENABLE_FEATURE_SH_MATH
6518                 CTLENDARI,
6519 #endif
6520                 '\0'
6521         };
6522         const char *reject = spclchars;
6523         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6524         int inquotes;
6525         size_t length;
6526         int startloc;
6527
6528         if (!(flags & EXP_VARTILDE)) {
6529                 reject += 2;
6530         } else if (flags & EXP_VARTILDE2) {
6531                 reject++;
6532         }
6533         inquotes = 0;
6534         length = 0;
6535         if (flags & EXP_TILDE) {
6536                 char *q;
6537
6538                 flags &= ~EXP_TILDE;
6539  tilde:
6540                 q = p;
6541                 if (*q == '~')
6542                         p = exptilde(p, q, flags);
6543         }
6544  start:
6545         startloc = expdest - (char *)stackblock();
6546         for (;;) {
6547                 unsigned char c;
6548
6549                 length += strcspn(p + length, reject);
6550                 c = p[length];
6551                 if (c) {
6552                         if (!(c & 0x80)
6553                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6554                         ) {
6555                                 /* c == '=' || c == ':' || c == CTLENDARI */
6556                                 length++;
6557                         }
6558                 }
6559                 if (length > 0) {
6560                         int newloc;
6561                         expdest = stack_nputstr(p, length, expdest);
6562                         newloc = expdest - (char *)stackblock();
6563                         if (breakall && !inquotes && newloc > startloc) {
6564                                 recordregion(startloc, newloc, 0);
6565                         }
6566                         startloc = newloc;
6567                 }
6568                 p += length + 1;
6569                 length = 0;
6570
6571                 switch (c) {
6572                 case '\0':
6573                         goto breakloop;
6574                 case '=':
6575                         if (flags & EXP_VARTILDE2) {
6576                                 p--;
6577                                 continue;
6578                         }
6579                         flags |= EXP_VARTILDE2;
6580                         reject++;
6581                         /* fall through */
6582                 case ':':
6583                         /*
6584                          * sort of a hack - expand tildes in variable
6585                          * assignments (after the first '=' and after ':'s).
6586                          */
6587                         if (*--p == '~') {
6588                                 goto tilde;
6589                         }
6590                         continue;
6591                 }
6592
6593                 switch (c) {
6594                 case CTLENDVAR: /* ??? */
6595                         goto breakloop;
6596                 case CTLQUOTEMARK:
6597                         inquotes ^= EXP_QUOTED;
6598                         /* "$@" syntax adherence hack */
6599                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6600                                 p = evalvar(p + 1, flags | inquotes) + 1;
6601                                 goto start;
6602                         }
6603  addquote:
6604                         if (flags & QUOTES_ESC) {
6605                                 p--;
6606                                 length++;
6607                                 startloc++;
6608                         }
6609                         break;
6610                 case CTLESC:
6611                         startloc++;
6612                         length++;
6613
6614                         /*
6615                          * Quoted parameter expansion pattern: remove quote
6616                          * unless inside inner quotes or we have a literal
6617                          * backslash.
6618                          */
6619                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6620                             EXP_QPAT && *p != '\\')
6621                                 break;
6622
6623                         goto addquote;
6624                 case CTLVAR:
6625                         TRACE(("argstr: evalvar('%s')\n", p));
6626                         p = evalvar(p, flags | inquotes);
6627                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6628                         goto start;
6629                 case CTLBACKQ:
6630                         expbackq(argbackq->n, flags | inquotes);
6631                         argbackq = argbackq->next;
6632                         goto start;
6633 #if ENABLE_FEATURE_SH_MATH
6634                 case CTLENDARI:
6635                         p--;
6636                         expari(flags | inquotes);
6637                         goto start;
6638 #endif
6639                 }
6640         }
6641  breakloop: ;
6642 }
6643
6644 static char *
6645 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6646                 char *pattern, int quotes, int zero)
6647 {
6648         char *loc, *loc2;
6649         char c;
6650
6651         loc = startp;
6652         loc2 = rmesc;
6653         do {
6654                 int match;
6655                 const char *s = loc2;
6656
6657                 c = *loc2;
6658                 if (zero) {
6659                         *loc2 = '\0';
6660                         s = rmesc;
6661                 }
6662                 match = pmatch(pattern, s);
6663
6664                 *loc2 = c;
6665                 if (match)
6666                         return loc;
6667                 if (quotes && (unsigned char)*loc == CTLESC)
6668                         loc++;
6669                 loc++;
6670                 loc2++;
6671         } while (c);
6672         return NULL;
6673 }
6674
6675 static char *
6676 scanright(char *startp, char *rmesc, char *rmescend,
6677                 char *pattern, int quotes, int match_at_start)
6678 {
6679 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6680         int try2optimize = match_at_start;
6681 #endif
6682         int esc = 0;
6683         char *loc;
6684         char *loc2;
6685
6686         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6687          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6688          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6689          * Logic:
6690          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6691          * and on each iteration they go back two/one char until they reach the beginning.
6692          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6693          */
6694         /* TODO: document in what other circumstances we are called. */
6695
6696         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6697                 int match;
6698                 char c = *loc2;
6699                 const char *s = loc2;
6700                 if (match_at_start) {
6701                         *loc2 = '\0';
6702                         s = rmesc;
6703                 }
6704                 match = pmatch(pattern, s);
6705                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6706                 *loc2 = c;
6707                 if (match)
6708                         return loc;
6709 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6710                 if (try2optimize) {
6711                         /* Maybe we can optimize this:
6712                          * if pattern ends with unescaped *, we can avoid checking
6713                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6714                          * it won't match truncated "raw_value_of_" strings too.
6715                          */
6716                         unsigned plen = strlen(pattern);
6717                         /* Does it end with "*"? */
6718                         if (plen != 0 && pattern[--plen] == '*') {
6719                                 /* "xxxx*" is not escaped */
6720                                 /* "xxx\*" is escaped */
6721                                 /* "xx\\*" is not escaped */
6722                                 /* "x\\\*" is escaped */
6723                                 int slashes = 0;
6724                                 while (plen != 0 && pattern[--plen] == '\\')
6725                                         slashes++;
6726                                 if (!(slashes & 1))
6727                                         break; /* ends with unescaped "*" */
6728                         }
6729                         try2optimize = 0;
6730                 }
6731 #endif
6732                 loc--;
6733                 if (quotes) {
6734                         if (--esc < 0) {
6735                                 esc = esclen(startp, loc);
6736                         }
6737                         if (esc % 2) {
6738                                 esc--;
6739                                 loc--;
6740                         }
6741                 }
6742         }
6743         return NULL;
6744 }
6745
6746 static void varunset(const char *, const char *, const char *, int) NORETURN;
6747 static void
6748 varunset(const char *end, const char *var, const char *umsg, int varflags)
6749 {
6750         const char *msg;
6751         const char *tail;
6752
6753         tail = nullstr;
6754         msg = "parameter not set";
6755         if (umsg) {
6756                 if ((unsigned char)*end == CTLENDVAR) {
6757                         if (varflags & VSNUL)
6758                                 tail = " or null";
6759                 } else {
6760                         msg = umsg;
6761                 }
6762         }
6763         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6764 }
6765
6766 static const char *
6767 subevalvar(char *p, char *varname, int strloc, int subtype,
6768                 int startloc, int varflags, int flag)
6769 {
6770         struct nodelist *saveargbackq = argbackq;
6771         int quotes = flag & QUOTES_ESC;
6772         char *startp;
6773         char *loc;
6774         char *rmesc, *rmescend;
6775         char *str;
6776         int amount, resetloc;
6777         int argstr_flags;
6778         IF_BASH_PATTERN_SUBST(int workloc;)
6779         IF_BASH_PATTERN_SUBST(int slash_pos;)
6780         IF_BASH_PATTERN_SUBST(char *repl;)
6781         int zero;
6782         char *(*scan)(char*, char*, char*, char*, int, int);
6783
6784         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6785         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6786
6787 #if BASH_PATTERN_SUBST
6788         /* For "${v/pattern/repl}", we must find the delimiter _before_
6789          * argstr() call expands possible variable references in pattern:
6790          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6791          */
6792         repl = NULL;
6793         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6794                 /* Find '/' and replace with NUL */
6795                 repl = p;
6796                 for (;;) {
6797                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6798                         if (*repl == '\0') {
6799                                 repl = NULL;
6800                                 break;
6801                         }
6802                         if (*repl == '/') {
6803                                 *repl = '\0';
6804                                 break;
6805                         }
6806                         if ((unsigned char)*repl == CTLESC && repl[1])
6807                                 repl++;
6808                         repl++;
6809                 }
6810         }
6811 #endif
6812         argstr_flags = EXP_TILDE;
6813         if (subtype != VSASSIGN && subtype != VSQUESTION)
6814                 argstr_flags |= (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE);
6815         argstr(p, argstr_flags);
6816 #if BASH_PATTERN_SUBST
6817         slash_pos = -1;
6818         if (repl) {
6819                 slash_pos = expdest - ((char *)stackblock() + strloc);
6820                 STPUTC('/', expdest);
6821                 argstr(repl + 1, argstr_flags);
6822                 *repl = '/';
6823         }
6824 #endif
6825         STPUTC('\0', expdest);
6826         argbackq = saveargbackq;
6827         startp = (char *)stackblock() + startloc;
6828         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6829
6830         switch (subtype) {
6831         case VSASSIGN:
6832                 setvar0(varname, startp);
6833                 amount = startp - expdest;
6834                 STADJUST(amount, expdest);
6835                 return startp;
6836
6837         case VSQUESTION:
6838                 varunset(p, varname, startp, varflags);
6839                 /* NOTREACHED */
6840
6841 #if BASH_SUBSTR
6842         case VSSUBSTR: {
6843                 int pos, len, orig_len;
6844                 char *colon;
6845
6846                 loc = str = stackblock() + strloc;
6847
6848                 /* Read POS in ${var:POS:LEN} */
6849                 colon = strchr(loc, ':');
6850                 if (colon) *colon = '\0';
6851                 pos = substr_atoi(loc);
6852                 if (colon) *colon = ':';
6853
6854                 /* Read LEN in ${var:POS:LEN} */
6855                 len = str - startp - 1;
6856                 /* *loc != '\0', guaranteed by parser */
6857                 if (quotes) {
6858                         char *ptr;
6859                         /* Adjust the length by the number of escapes */
6860                         for (ptr = startp; ptr < (str - 1); ptr++) {
6861                                 if ((unsigned char)*ptr == CTLESC) {
6862                                         len--;
6863                                         ptr++;
6864                                 }
6865                         }
6866                 }
6867                 orig_len = len;
6868                 if (*loc++ == ':') {
6869                         /* ${var::LEN} */
6870                         len = substr_atoi(loc);
6871                 } else {
6872                         /* Skip POS in ${var:POS:LEN} */
6873                         len = orig_len;
6874                         while (*loc && *loc != ':')
6875                                 loc++;
6876                         if (*loc++ == ':')
6877                                 len = substr_atoi(loc);
6878                 }
6879                 if (pos < 0) {
6880                         /* ${VAR:$((-n)):l} starts n chars from the end */
6881                         pos = orig_len + pos;
6882                 }
6883                 if ((unsigned)pos >= orig_len) {
6884                         /* apart from obvious ${VAR:999999:l},
6885                          * covers ${VAR:$((-9999999)):l} - result is ""
6886                          * (bash compat)
6887                          */
6888                         pos = 0;
6889                         len = 0;
6890                 }
6891                 if (len < 0) {
6892                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6893                         len = (orig_len - pos) + len;
6894                 }
6895                 if ((unsigned)len > (orig_len - pos))
6896                         len = orig_len - pos;
6897
6898                 for (str = startp; pos; str++, pos--) {
6899                         if (quotes && (unsigned char)*str == CTLESC)
6900                                 str++;
6901                 }
6902                 for (loc = startp; len; len--) {
6903                         if (quotes && (unsigned char)*str == CTLESC)
6904                                 *loc++ = *str++;
6905                         *loc++ = *str++;
6906                 }
6907                 *loc = '\0';
6908                 amount = loc - expdest;
6909                 STADJUST(amount, expdest);
6910                 return loc;
6911         }
6912 #endif /* BASH_SUBSTR */
6913         }
6914
6915         resetloc = expdest - (char *)stackblock();
6916
6917 #if BASH_PATTERN_SUBST
6918         repl = NULL;
6919
6920         /* We'll comeback here if we grow the stack while handling
6921          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6922          * stack will need rebasing, and we'll need to remove our work
6923          * areas each time
6924          */
6925  restart:
6926 #endif
6927
6928         amount = expdest - ((char *)stackblock() + resetloc);
6929         STADJUST(-amount, expdest);
6930         startp = (char *)stackblock() + startloc;
6931
6932         rmesc = startp;
6933         rmescend = (char *)stackblock() + strloc;
6934         //bb_error_msg("str7:'%s'", rmescend);
6935         if (quotes) {
6936 //TODO: how to handle slash_pos here if string changes (shortens?)
6937                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
6938                 if (rmesc != startp) {
6939                         rmescend = expdest;
6940                         startp = (char *)stackblock() + startloc;
6941                 }
6942         }
6943         rmescend--;
6944         str = (char *)stackblock() + strloc;
6945         /*
6946          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6947          * The result is a_\_z_c (not a\_\_z_c)!
6948          *
6949          * The search pattern and replace string treat backslashes differently!
6950          * "&slash_pos" causes rmescapes() to work differently on the pattern
6951          * and string.  It's only used on the first call.
6952          */
6953         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
6954         rmescapes(str, RMESCAPE_GLOB,
6955                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
6956         );
6957
6958 #if BASH_PATTERN_SUBST
6959         workloc = expdest - (char *)stackblock();
6960         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6961                 int len;
6962                 char *idx, *end;
6963
6964                 if (!repl) {
6965                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
6966                         repl = nullstr;
6967                         if (slash_pos >= 0) {
6968                                 repl = str + slash_pos;
6969                                 *repl++ = '\0';
6970                         }
6971                 }
6972                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6973
6974                 /* If there's no pattern to match, return the expansion unmolested */
6975                 if (str[0] == '\0')
6976                         return NULL;
6977
6978                 len = 0;
6979                 idx = startp;
6980                 end = str - 1;
6981                 while (idx < end) {
6982  try_to_match:
6983                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6984                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6985                         if (!loc) {
6986                                 /* No match, advance */
6987                                 char *restart_detect = stackblock();
6988  skip_matching:
6989                                 STPUTC(*idx, expdest);
6990                                 if (quotes && (unsigned char)*idx == CTLESC) {
6991                                         idx++;
6992                                         len++;
6993                                         STPUTC(*idx, expdest);
6994                                 }
6995                                 if (stackblock() != restart_detect)
6996                                         goto restart;
6997                                 idx++;
6998                                 len++;
6999                                 rmesc++;
7000                                 /* continue; - prone to quadratic behavior, smarter code: */
7001                                 if (idx >= end)
7002                                         break;
7003                                 if (str[0] == '*') {
7004                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7005                                          * it would never match "ong_string" etc, no point in trying.
7006                                          */
7007                                         goto skip_matching;
7008                                 }
7009                                 goto try_to_match;
7010                         }
7011
7012                         if (subtype == VSREPLACEALL) {
7013                                 while (idx < loc) {
7014                                         if (quotes && (unsigned char)*idx == CTLESC)
7015                                                 idx++;
7016                                         idx++;
7017                                         rmesc++;
7018                                 }
7019                         } else {
7020                                 idx = loc;
7021                         }
7022
7023                         //bb_error_msg("repl:'%s'", repl);
7024                         for (loc = (char*)repl; *loc; loc++) {
7025                                 char *restart_detect = stackblock();
7026                                 if (quotes && *loc == '\\') {
7027                                         STPUTC(CTLESC, expdest);
7028                                         len++;
7029                                 }
7030                                 STPUTC(*loc, expdest);
7031                                 if (stackblock() != restart_detect)
7032                                         goto restart;
7033                                 len++;
7034                         }
7035
7036                         if (subtype == VSREPLACE) {
7037                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7038                                 while (*idx) {
7039                                         char *restart_detect = stackblock();
7040                                         STPUTC(*idx, expdest);
7041                                         if (stackblock() != restart_detect)
7042                                                 goto restart;
7043                                         len++;
7044                                         idx++;
7045                                 }
7046                                 break;
7047                         }
7048                 }
7049
7050                 /* We've put the replaced text into a buffer at workloc, now
7051                  * move it to the right place and adjust the stack.
7052                  */
7053                 STPUTC('\0', expdest);
7054                 startp = (char *)stackblock() + startloc;
7055                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7056                 //bb_error_msg("startp:'%s'", startp);
7057                 amount = expdest - (startp + len);
7058                 STADJUST(-amount, expdest);
7059                 return startp;
7060         }
7061 #endif /* BASH_PATTERN_SUBST */
7062
7063         subtype -= VSTRIMRIGHT;
7064 #if DEBUG
7065         if (subtype < 0 || subtype > 7)
7066                 abort();
7067 #endif
7068         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7069         zero = subtype >> 1;
7070         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7071         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7072
7073         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7074         if (loc) {
7075                 if (zero) {
7076                         memmove(startp, loc, str - loc);
7077                         loc = startp + (str - loc) - 1;
7078                 }
7079                 *loc = '\0';
7080                 amount = loc - expdest;
7081                 STADJUST(amount, expdest);
7082         }
7083         return loc;
7084 }
7085
7086 /*
7087  * Add the value of a specialized variable to the stack string.
7088  * name parameter (examples):
7089  * ash -c 'echo $1'      name:'1='
7090  * ash -c 'echo $qwe'    name:'qwe='
7091  * ash -c 'echo $$'      name:'$='
7092  * ash -c 'echo ${$}'    name:'$='
7093  * ash -c 'echo ${$##q}' name:'$=q'
7094  * ash -c 'echo ${#$}'   name:'$='
7095  * note: examples with bad shell syntax:
7096  * ash -c 'echo ${#$1}'  name:'$=1'
7097  * ash -c 'echo ${#1#}'  name:'1=#'
7098  */
7099 static NOINLINE ssize_t
7100 varvalue(char *name, int varflags, int flags, int *quotedp)
7101 {
7102         const char *p;
7103         int num;
7104         int i;
7105         ssize_t len = 0;
7106         int sep;
7107         int quoted = *quotedp;
7108         int subtype = varflags & VSTYPE;
7109         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7110         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7111         int syntax;
7112
7113         sep = (flags & EXP_FULL) << CHAR_BIT;
7114         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7115
7116         switch (*name) {
7117         case '$':
7118                 num = rootpid;
7119                 goto numvar;
7120         case '?':
7121                 num = exitstatus;
7122                 goto numvar;
7123         case '#':
7124                 num = shellparam.nparam;
7125                 goto numvar;
7126         case '!':
7127                 num = backgndpid;
7128                 if (num == 0)
7129                         return -1;
7130  numvar:
7131                 len = cvtnum(num);
7132                 goto check_1char_name;
7133         case '-':
7134                 expdest = makestrspace(NOPTS, expdest);
7135                 for (i = NOPTS - 1; i >= 0; i--) {
7136                         if (optlist[i]) {
7137                                 USTPUTC(optletters(i), expdest);
7138                                 len++;
7139                         }
7140                 }
7141  check_1char_name:
7142 #if 0
7143                 /* handles cases similar to ${#$1} */
7144                 if (name[2] != '\0')
7145                         raise_error_syntax("bad substitution");
7146 #endif
7147                 break;
7148         case '@':
7149                 if (quoted && sep)
7150                         goto param;
7151                 /* fall through */
7152         case '*': {
7153                 char **ap;
7154                 char sepc;
7155
7156                 if (quoted)
7157                         sep = 0;
7158                 sep |= ifsset() ? ifsval()[0] : ' ';
7159  param:
7160                 sepc = sep;
7161                 *quotedp = !sepc;
7162                 ap = shellparam.p;
7163                 if (!ap)
7164                         return -1;
7165                 while ((p = *ap++) != NULL) {
7166                         len += strtodest(p, syntax, quotes);
7167
7168                         if (*ap && sep) {
7169                                 len++;
7170                                 memtodest(&sepc, 1, syntax, quotes);
7171                         }
7172                 }
7173                 break;
7174         } /* case '*' */
7175         case '0':
7176         case '1':
7177         case '2':
7178         case '3':
7179         case '4':
7180         case '5':
7181         case '6':
7182         case '7':
7183         case '8':
7184         case '9':
7185                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7186                 if (num < 0 || num > shellparam.nparam)
7187                         return -1;
7188                 p = num ? shellparam.p[num - 1] : arg0;
7189                 goto value;
7190         default:
7191                 /* NB: name has form "VAR=..." */
7192                 p = lookupvar(name);
7193  value:
7194                 if (!p)
7195                         return -1;
7196
7197                 len = strtodest(p, syntax, quotes);
7198 #if ENABLE_UNICODE_SUPPORT
7199                 if (subtype == VSLENGTH && len > 0) {
7200                         reinit_unicode_for_ash();
7201                         if (unicode_status == UNICODE_ON) {
7202                                 STADJUST(-len, expdest);
7203                                 discard = 0;
7204                                 len = unicode_strlen(p);
7205                         }
7206                 }
7207 #endif
7208                 break;
7209         }
7210
7211         if (discard)
7212                 STADJUST(-len, expdest);
7213         return len;
7214 }
7215
7216 /*
7217  * Expand a variable, and return a pointer to the next character in the
7218  * input string.
7219  */
7220 static char *
7221 evalvar(char *p, int flag)
7222 {
7223         char varflags;
7224         char subtype;
7225         int quoted;
7226         char easy;
7227         char *var;
7228         int patloc;
7229         int startloc;
7230         ssize_t varlen;
7231
7232         varflags = (unsigned char) *p++;
7233         subtype = varflags & VSTYPE;
7234
7235         if (!subtype)
7236                 raise_error_syntax("bad substitution");
7237
7238         quoted = flag & EXP_QUOTED;
7239         var = p;
7240         easy = (!quoted || (*var == '@' && shellparam.nparam));
7241         startloc = expdest - (char *)stackblock();
7242         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7243
7244  again:
7245         varlen = varvalue(var, varflags, flag, &quoted);
7246         if (varflags & VSNUL)
7247                 varlen--;
7248
7249         if (subtype == VSPLUS) {
7250                 varlen = -1 - varlen;
7251                 goto vsplus;
7252         }
7253
7254         if (subtype == VSMINUS) {
7255  vsplus:
7256                 if (varlen < 0) {
7257                         argstr(
7258                                 p,
7259                                 flag | EXP_TILDE | EXP_WORD
7260                         );
7261                         goto end;
7262                 }
7263                 goto record;
7264         }
7265
7266         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7267                 if (varlen >= 0)
7268                         goto record;
7269
7270                 subevalvar(p, var, 0, subtype, startloc, varflags,
7271                            flag & ~QUOTES_ESC);
7272                 varflags &= ~VSNUL;
7273                 /*
7274                  * Remove any recorded regions beyond
7275                  * start of variable
7276                  */
7277                 removerecordregions(startloc);
7278                 goto again;
7279         }
7280
7281         if (varlen < 0 && uflag)
7282                 varunset(p, var, 0, 0);
7283
7284         if (subtype == VSLENGTH) {
7285                 cvtnum(varlen > 0 ? varlen : 0);
7286                 goto record;
7287         }
7288
7289         if (subtype == VSNORMAL) {
7290  record:
7291                 if (!easy)
7292                         goto end;
7293                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7294                 goto end;
7295         }
7296
7297 #if DEBUG
7298         switch (subtype) {
7299         case VSTRIMLEFT:
7300         case VSTRIMLEFTMAX:
7301         case VSTRIMRIGHT:
7302         case VSTRIMRIGHTMAX:
7303 #if BASH_SUBSTR
7304         case VSSUBSTR:
7305 #endif
7306 #if BASH_PATTERN_SUBST
7307         case VSREPLACE:
7308         case VSREPLACEALL:
7309 #endif
7310                 break;
7311         default:
7312                 abort();
7313         }
7314 #endif
7315
7316         if (varlen >= 0) {
7317                 /*
7318                  * Terminate the string and start recording the pattern
7319                  * right after it
7320                  */
7321                 STPUTC('\0', expdest);
7322                 patloc = expdest - (char *)stackblock();
7323                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7324                                 startloc, varflags, flag)) {
7325                         int amount = expdest - (
7326                                 (char *)stackblock() + patloc - 1
7327                         );
7328                         STADJUST(-amount, expdest);
7329                 }
7330                 /* Remove any recorded regions beyond start of variable */
7331                 removerecordregions(startloc);
7332                 goto record;
7333         }
7334
7335  end:
7336         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7337                 int nesting = 1;
7338                 for (;;) {
7339                         unsigned char c = *p++;
7340                         if (c == CTLESC)
7341                                 p++;
7342                         else if (c == CTLBACKQ) {
7343                                 if (varlen >= 0)
7344                                         argbackq = argbackq->next;
7345                         } else if (c == CTLVAR) {
7346                                 if ((*p++ & VSTYPE) != VSNORMAL)
7347                                         nesting++;
7348                         } else if (c == CTLENDVAR) {
7349                                 if (--nesting == 0)
7350                                         break;
7351                         }
7352                 }
7353         }
7354         return p;
7355 }
7356
7357 /*
7358  * Add a file name to the list.
7359  */
7360 static void
7361 addfname(const char *name)
7362 {
7363         struct strlist *sp;
7364
7365         sp = stzalloc(sizeof(*sp));
7366         sp->text = sstrdup(name);
7367         *exparg.lastp = sp;
7368         exparg.lastp = &sp->next;
7369 }
7370
7371 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7372 static int
7373 hasmeta(const char *p)
7374 {
7375         static const char chars[] ALIGN1 = {
7376                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7377         };
7378
7379         for (;;) {
7380                 p = strpbrk(p, chars);
7381                 if (!p)
7382                         break;
7383                 switch ((unsigned char) *p) {
7384                 case CTLQUOTEMARK:
7385                         for (;;) {
7386                                 p++;
7387                                 if (*p == CTLQUOTEMARK)
7388                                         break;
7389                                 if (*p == CTLESC)
7390                                         p++;
7391                                 if (*p == '\0') /* huh? */
7392                                         return 0;
7393                         }
7394                         break;
7395                 case '\\':
7396                 case CTLESC:
7397                         p++;
7398                         if (*p == '\0')
7399                                 return 0;
7400                         break;
7401                 case '[':
7402                         if (!strchr(p + 1, ']')) {
7403                                 /* It's not a properly closed [] pattern,
7404                                  * but other metas may follow. Continue checking.
7405                                  * my[file* _is_ globbed by bash
7406                                  * and matches filenames like "my[file1".
7407                                  */
7408                                 break;
7409                         }
7410                         /* fallthrough */
7411                 default:
7412                 /* case '*': */
7413                 /* case '?': */
7414                         return 1;
7415                 }
7416                 p++;
7417         }
7418
7419         return 0;
7420 }
7421
7422 /* If we want to use glob() from libc... */
7423 #if !ENABLE_ASH_INTERNAL_GLOB
7424
7425 /* Add the result of glob() to the list */
7426 static void
7427 addglob(const glob_t *pglob)
7428 {
7429         char **p = pglob->gl_pathv;
7430
7431         do {
7432                 addfname(*p);
7433         } while (*++p);
7434 }
7435 static void
7436 expandmeta(struct strlist *str /*, int flag*/)
7437 {
7438         /* TODO - EXP_REDIR */
7439
7440         while (str) {
7441                 char *p;
7442                 glob_t pglob;
7443                 int i;
7444
7445                 if (fflag)
7446                         goto nometa;
7447
7448                 if (!hasmeta(str->text))
7449                         goto nometa;
7450
7451                 INT_OFF;
7452                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7453 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7454 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7455 //
7456 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7457 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7458 // Which means you need to unescape the string, right? Not so fast:
7459 // if there _is_ a file named "file\?" (with backslash), it is returned
7460 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7461 // You DON'T KNOW by looking at the result whether you need to unescape it.
7462 //
7463 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7464 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7465 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7466 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7467 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7468 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7469                 i = glob(p, 0, NULL, &pglob);
7470                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7471                 if (p != str->text)
7472                         free(p);
7473                 switch (i) {
7474                 case 0:
7475 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7476                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7477                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7478                                 goto nometa2;
7479 #endif
7480                         addglob(&pglob);
7481                         globfree(&pglob);
7482                         INT_ON;
7483                         break;
7484                 case GLOB_NOMATCH:
7485  //nometa2:
7486                         globfree(&pglob);
7487                         INT_ON;
7488  nometa:
7489                         *exparg.lastp = str;
7490                         rmescapes(str->text, 0, NULL);
7491                         exparg.lastp = &str->next;
7492                         break;
7493                 default:        /* GLOB_NOSPACE */
7494                         globfree(&pglob);
7495                         INT_ON;
7496                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7497                 }
7498                 str = str->next;
7499         }
7500 }
7501
7502 #else
7503 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7504
7505 /*
7506  * Do metacharacter (i.e. *, ?, [...]) expansion.
7507  */
7508 static void
7509 expmeta(char *expdir, char *enddir, char *name)
7510 {
7511         char *p;
7512         const char *cp;
7513         char *start;
7514         char *endname;
7515         int metaflag;
7516         struct stat statb;
7517         DIR *dirp;
7518         struct dirent *dp;
7519         int atend;
7520         int matchdot;
7521         int esc;
7522
7523         metaflag = 0;
7524         start = name;
7525         for (p = name; esc = 0, *p; p += esc + 1) {
7526                 if (*p == '*' || *p == '?')
7527                         metaflag = 1;
7528                 else if (*p == '[') {
7529                         char *q = p + 1;
7530                         if (*q == '!')
7531                                 q++;
7532                         for (;;) {
7533                                 if (*q == '\\')
7534                                         q++;
7535                                 if (*q == '/' || *q == '\0')
7536                                         break;
7537                                 if (*++q == ']') {
7538                                         metaflag = 1;
7539                                         break;
7540                                 }
7541                         }
7542                 } else {
7543                         if (*p == '\\')
7544                                 esc++;
7545                         if (p[esc] == '/') {
7546                                 if (metaflag)
7547                                         break;
7548                                 start = p + esc + 1;
7549                         }
7550                 }
7551         }
7552         if (metaflag == 0) {    /* we've reached the end of the file name */
7553                 if (enddir != expdir)
7554                         metaflag++;
7555                 p = name;
7556                 do {
7557                         if (*p == '\\')
7558                                 p++;
7559                         *enddir++ = *p;
7560                 } while (*p++);
7561                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7562                         addfname(expdir);
7563                 return;
7564         }
7565         endname = p;
7566         if (name < start) {
7567                 p = name;
7568                 do {
7569                         if (*p == '\\')
7570                                 p++;
7571                         *enddir++ = *p++;
7572                 } while (p < start);
7573         }
7574         if (enddir == expdir) {
7575                 cp = ".";
7576         } else if (enddir == expdir + 1 && *expdir == '/') {
7577                 cp = "/";
7578         } else {
7579                 cp = expdir;
7580                 enddir[-1] = '\0';
7581         }
7582         dirp = opendir(cp);
7583         if (dirp == NULL)
7584                 return;
7585         if (enddir != expdir)
7586                 enddir[-1] = '/';
7587         if (*endname == 0) {
7588                 atend = 1;
7589         } else {
7590                 atend = 0;
7591                 *endname = '\0';
7592                 endname += esc + 1;
7593         }
7594         matchdot = 0;
7595         p = start;
7596         if (*p == '\\')
7597                 p++;
7598         if (*p == '.')
7599                 matchdot++;
7600         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7601                 if (dp->d_name[0] == '.' && !matchdot)
7602                         continue;
7603                 if (pmatch(start, dp->d_name)) {
7604                         if (atend) {
7605                                 strcpy(enddir, dp->d_name);
7606                                 addfname(expdir);
7607                         } else {
7608                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7609                                         continue;
7610                                 p[-1] = '/';
7611                                 expmeta(expdir, p, endname);
7612                         }
7613                 }
7614         }
7615         closedir(dirp);
7616         if (!atend)
7617                 endname[-esc - 1] = esc ? '\\' : '/';
7618 }
7619
7620 static struct strlist *
7621 msort(struct strlist *list, int len)
7622 {
7623         struct strlist *p, *q = NULL;
7624         struct strlist **lpp;
7625         int half;
7626         int n;
7627
7628         if (len <= 1)
7629                 return list;
7630         half = len >> 1;
7631         p = list;
7632         for (n = half; --n >= 0;) {
7633                 q = p;
7634                 p = p->next;
7635         }
7636         q->next = NULL;                 /* terminate first half of list */
7637         q = msort(list, half);          /* sort first half of list */
7638         p = msort(p, len - half);               /* sort second half */
7639         lpp = &list;
7640         for (;;) {
7641 #if ENABLE_LOCALE_SUPPORT
7642                 if (strcoll(p->text, q->text) < 0)
7643 #else
7644                 if (strcmp(p->text, q->text) < 0)
7645 #endif
7646                                                 {
7647                         *lpp = p;
7648                         lpp = &p->next;
7649                         p = *lpp;
7650                         if (p == NULL) {
7651                                 *lpp = q;
7652                                 break;
7653                         }
7654                 } else {
7655                         *lpp = q;
7656                         lpp = &q->next;
7657                         q = *lpp;
7658                         if (q == NULL) {
7659                                 *lpp = p;
7660                                 break;
7661                         }
7662                 }
7663         }
7664         return list;
7665 }
7666
7667 /*
7668  * Sort the results of file name expansion.  It calculates the number of
7669  * strings to sort and then calls msort (short for merge sort) to do the
7670  * work.
7671  */
7672 static struct strlist *
7673 expsort(struct strlist *str)
7674 {
7675         int len;
7676         struct strlist *sp;
7677
7678         len = 0;
7679         for (sp = str; sp; sp = sp->next)
7680                 len++;
7681         return msort(str, len);
7682 }
7683
7684 static void
7685 expandmeta(struct strlist *str /*, int flag*/)
7686 {
7687         /* TODO - EXP_REDIR */
7688
7689         while (str) {
7690                 char *expdir;
7691                 struct strlist **savelastp;
7692                 struct strlist *sp;
7693                 char *p;
7694
7695                 if (fflag)
7696                         goto nometa;
7697                 if (!hasmeta(str->text))
7698                         goto nometa;
7699                 savelastp = exparg.lastp;
7700
7701                 INT_OFF;
7702                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7703                 {
7704                         int i = strlen(str->text);
7705 //BUGGY estimation of how long expanded name can be
7706                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7707                 }
7708                 expmeta(expdir, expdir, p);
7709                 free(expdir);
7710                 if (p != str->text)
7711                         free(p);
7712                 INT_ON;
7713                 if (exparg.lastp == savelastp) {
7714                         /*
7715                          * no matches
7716                          */
7717  nometa:
7718                         *exparg.lastp = str;
7719                         rmescapes(str->text, 0, NULL);
7720                         exparg.lastp = &str->next;
7721                 } else {
7722                         *exparg.lastp = NULL;
7723                         *savelastp = sp = expsort(*savelastp);
7724                         while (sp->next != NULL)
7725                                 sp = sp->next;
7726                         exparg.lastp = &sp->next;
7727                 }
7728                 str = str->next;
7729         }
7730 }
7731 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7732
7733 /*
7734  * Perform variable substitution and command substitution on an argument,
7735  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7736  * perform splitting and file name expansion.  When arglist is NULL, perform
7737  * here document expansion.
7738  */
7739 static void
7740 expandarg(union node *arg, struct arglist *arglist, int flag)
7741 {
7742         struct strlist *sp;
7743         char *p;
7744
7745         argbackq = arg->narg.backquote;
7746         STARTSTACKSTR(expdest);
7747         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7748         argstr(arg->narg.text, flag);
7749         p = _STPUTC('\0', expdest);
7750         expdest = p - 1;
7751         if (arglist == NULL) {
7752                 /* here document expanded */
7753                 goto out;
7754         }
7755         p = grabstackstr(p);
7756         TRACE(("expandarg: p:'%s'\n", p));
7757         exparg.lastp = &exparg.list;
7758         /*
7759          * TODO - EXP_REDIR
7760          */
7761         if (flag & EXP_FULL) {
7762                 ifsbreakup(p, &exparg);
7763                 *exparg.lastp = NULL;
7764                 exparg.lastp = &exparg.list;
7765                 expandmeta(exparg.list /*, flag*/);
7766         } else {
7767                 sp = stzalloc(sizeof(*sp));
7768                 sp->text = p;
7769                 *exparg.lastp = sp;
7770                 exparg.lastp = &sp->next;
7771         }
7772         *exparg.lastp = NULL;
7773         if (exparg.list) {
7774                 *arglist->lastp = exparg.list;
7775                 arglist->lastp = exparg.lastp;
7776         }
7777
7778  out:
7779         ifsfree();
7780 }
7781
7782 /*
7783  * Expand shell variables and backquotes inside a here document.
7784  */
7785 static void
7786 expandhere(union node *arg, int fd)
7787 {
7788         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7789         full_write(fd, stackblock(), expdest - (char *)stackblock());
7790 }
7791
7792 /*
7793  * Returns true if the pattern matches the string.
7794  */
7795 static int
7796 patmatch(char *pattern, const char *string)
7797 {
7798         char *p = preglob(pattern, 0);
7799         int r = pmatch(p, string);
7800         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7801         return r;
7802 }
7803
7804 /*
7805  * See if a pattern matches in a case statement.
7806  */
7807 static int
7808 casematch(union node *pattern, char *val)
7809 {
7810         struct stackmark smark;
7811         int result;
7812
7813         setstackmark(&smark);
7814         argbackq = pattern->narg.backquote;
7815         STARTSTACKSTR(expdest);
7816         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7817         STACKSTRNUL(expdest);
7818         ifsfree();
7819         result = patmatch(stackblock(), val);
7820         popstackmark(&smark);
7821         return result;
7822 }
7823
7824
7825 /* ============ find_command */
7826
7827 struct builtincmd {
7828         const char *name;
7829         int (*builtin)(int, char **) FAST_FUNC;
7830         /* unsigned flags; */
7831 };
7832 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7833 /* "regular" builtins always take precedence over commands,
7834  * regardless of PATH=....%builtin... position */
7835 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7836 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7837
7838 struct cmdentry {
7839         smallint cmdtype;       /* CMDxxx */
7840         union param {
7841                 int index;
7842                 /* index >= 0 for commands without path (slashes) */
7843                 /* (TODO: what exactly does the value mean? PATH position?) */
7844                 /* index == -1 for commands with slashes */
7845                 /* index == (-2 - applet_no) for NOFORK applets */
7846                 const struct builtincmd *cmd;
7847                 struct funcnode *func;
7848         } u;
7849 };
7850 /* values of cmdtype */
7851 #define CMDUNKNOWN      -1      /* no entry in table for command */
7852 #define CMDNORMAL       0       /* command is an executable program */
7853 #define CMDFUNCTION     1       /* command is a shell function */
7854 #define CMDBUILTIN      2       /* command is a shell builtin */
7855
7856 /* action to find_command() */
7857 #define DO_ERR          0x01    /* prints errors */
7858 #define DO_ABS          0x02    /* checks absolute paths */
7859 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7860 #define DO_ALTPATH      0x08    /* using alternate path */
7861 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7862
7863 static void find_command(char *, struct cmdentry *, int, const char *);
7864
7865
7866 /* ============ Hashing commands */
7867
7868 /*
7869  * When commands are first encountered, they are entered in a hash table.
7870  * This ensures that a full path search will not have to be done for them
7871  * on each invocation.
7872  *
7873  * We should investigate converting to a linear search, even though that
7874  * would make the command name "hash" a misnomer.
7875  */
7876
7877 struct tblentry {
7878         struct tblentry *next;  /* next entry in hash chain */
7879         union param param;      /* definition of builtin function */
7880         smallint cmdtype;       /* CMDxxx */
7881         char rehash;            /* if set, cd done since entry created */
7882         char cmdname[1];        /* name of command */
7883 };
7884
7885 static struct tblentry **cmdtable;
7886 #define INIT_G_cmdtable() do { \
7887         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7888 } while (0)
7889
7890 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7891
7892
7893 static void
7894 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7895 {
7896 #if ENABLE_FEATURE_SH_STANDALONE
7897         if (applet_no >= 0) {
7898                 if (APPLET_IS_NOEXEC(applet_no)) {
7899                         clearenv();
7900                         while (*envp)
7901                                 putenv(*envp++);
7902                         popredir(/*drop:*/ 1);
7903                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7904                 }
7905                 /* re-exec ourselves with the new arguments */
7906                 execve(bb_busybox_exec_path, argv, envp);
7907                 /* If they called chroot or otherwise made the binary no longer
7908                  * executable, fall through */
7909         }
7910 #endif
7911
7912  repeat:
7913 #ifdef SYSV
7914         do {
7915                 execve(cmd, argv, envp);
7916         } while (errno == EINTR);
7917 #else
7918         execve(cmd, argv, envp);
7919 #endif
7920         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7921                 /* Run "cmd" as a shell script:
7922                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7923                  * "If the execve() function fails with ENOEXEC, the shell
7924                  * shall execute a command equivalent to having a shell invoked
7925                  * with the command name as its first operand,
7926                  * with any remaining arguments passed to the new shell"
7927                  *
7928                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7929                  * just call ourselves.
7930                  *
7931                  * Note that bash reads ~80 chars of the file, and if it sees
7932                  * a zero byte before it sees newline, it doesn't try to
7933                  * interpret it, but fails with "cannot execute binary file"
7934                  * message and exit code 126. For one, this prevents attempts
7935                  * to interpret foreign ELF binaries as shell scripts.
7936                  */
7937                 argv[0] = (char*) cmd;
7938                 cmd = bb_busybox_exec_path;
7939                 /* NB: this is only possible because all callers of shellexec()
7940                  * ensure that the argv[-1] slot exists!
7941                  */
7942                 argv--;
7943                 argv[0] = (char*) "ash";
7944                 goto repeat;
7945         }
7946 }
7947
7948 /*
7949  * Exec a program.  Never returns.  If you change this routine, you may
7950  * have to change the find_command routine as well.
7951  * argv[-1] must exist and be writable! See tryexec() for why.
7952  */
7953 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7954 static void shellexec(char *prog, char **argv, const char *path, int idx)
7955 {
7956         char *cmdname;
7957         int e;
7958         char **envp;
7959         int exerrno;
7960         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7961
7962         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
7963         if (strchr(prog, '/') != NULL
7964 #if ENABLE_FEATURE_SH_STANDALONE
7965          || (applet_no = find_applet_by_name(prog)) >= 0
7966 #endif
7967         ) {
7968                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7969                 if (applet_no >= 0) {
7970                         /* We tried execing ourself, but it didn't work.
7971                          * Maybe /proc/self/exe doesn't exist?
7972                          * Try $PATH search.
7973                          */
7974                         goto try_PATH;
7975                 }
7976                 e = errno;
7977         } else {
7978  try_PATH:
7979                 e = ENOENT;
7980                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7981                         if (--idx < 0 && pathopt == NULL) {
7982                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7983                                 if (errno != ENOENT && errno != ENOTDIR)
7984                                         e = errno;
7985                         }
7986                         stunalloc(cmdname);
7987                 }
7988         }
7989
7990         /* Map to POSIX errors */
7991         switch (e) {
7992         case EACCES:
7993                 exerrno = 126;
7994                 break;
7995         case ENOENT:
7996                 exerrno = 127;
7997                 break;
7998         default:
7999                 exerrno = 2;
8000                 break;
8001         }
8002         exitstatus = exerrno;
8003         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8004                 prog, e, suppress_int));
8005         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8006         /* NOTREACHED */
8007 }
8008
8009 static void
8010 printentry(struct tblentry *cmdp)
8011 {
8012         int idx;
8013         const char *path;
8014         char *name;
8015
8016         idx = cmdp->param.index;
8017         path = pathval();
8018         do {
8019                 name = path_advance(&path, cmdp->cmdname);
8020                 stunalloc(name);
8021         } while (--idx >= 0);
8022         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8023 }
8024
8025 /*
8026  * Clear out command entries.  The argument specifies the first entry in
8027  * PATH which has changed.
8028  */
8029 static void
8030 clearcmdentry(int firstchange)
8031 {
8032         struct tblentry **tblp;
8033         struct tblentry **pp;
8034         struct tblentry *cmdp;
8035
8036         INT_OFF;
8037         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8038                 pp = tblp;
8039                 while ((cmdp = *pp) != NULL) {
8040                         if ((cmdp->cmdtype == CMDNORMAL &&
8041                              cmdp->param.index >= firstchange)
8042                          || (cmdp->cmdtype == CMDBUILTIN &&
8043                              builtinloc >= firstchange)
8044                         ) {
8045                                 *pp = cmdp->next;
8046                                 free(cmdp);
8047                         } else {
8048                                 pp = &cmdp->next;
8049                         }
8050                 }
8051         }
8052         INT_ON;
8053 }
8054
8055 /*
8056  * Locate a command in the command hash table.  If "add" is nonzero,
8057  * add the command to the table if it is not already present.  The
8058  * variable "lastcmdentry" is set to point to the address of the link
8059  * pointing to the entry, so that delete_cmd_entry can delete the
8060  * entry.
8061  *
8062  * Interrupts must be off if called with add != 0.
8063  */
8064 static struct tblentry **lastcmdentry;
8065
8066 static struct tblentry *
8067 cmdlookup(const char *name, int add)
8068 {
8069         unsigned int hashval;
8070         const char *p;
8071         struct tblentry *cmdp;
8072         struct tblentry **pp;
8073
8074         p = name;
8075         hashval = (unsigned char)*p << 4;
8076         while (*p)
8077                 hashval += (unsigned char)*p++;
8078         hashval &= 0x7FFF;
8079         pp = &cmdtable[hashval % CMDTABLESIZE];
8080         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8081                 if (strcmp(cmdp->cmdname, name) == 0)
8082                         break;
8083                 pp = &cmdp->next;
8084         }
8085         if (add && cmdp == NULL) {
8086                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8087                                 + strlen(name)
8088                                 /* + 1 - already done because
8089                                  * tblentry::cmdname is char[1] */);
8090                 /*cmdp->next = NULL; - ckzalloc did it */
8091                 cmdp->cmdtype = CMDUNKNOWN;
8092                 strcpy(cmdp->cmdname, name);
8093         }
8094         lastcmdentry = pp;
8095         return cmdp;
8096 }
8097
8098 /*
8099  * Delete the command entry returned on the last lookup.
8100  */
8101 static void
8102 delete_cmd_entry(void)
8103 {
8104         struct tblentry *cmdp;
8105
8106         INT_OFF;
8107         cmdp = *lastcmdentry;
8108         *lastcmdentry = cmdp->next;
8109         if (cmdp->cmdtype == CMDFUNCTION)
8110                 freefunc(cmdp->param.func);
8111         free(cmdp);
8112         INT_ON;
8113 }
8114
8115 /*
8116  * Add a new command entry, replacing any existing command entry for
8117  * the same name - except special builtins.
8118  */
8119 static void
8120 addcmdentry(char *name, struct cmdentry *entry)
8121 {
8122         struct tblentry *cmdp;
8123
8124         cmdp = cmdlookup(name, 1);
8125         if (cmdp->cmdtype == CMDFUNCTION) {
8126                 freefunc(cmdp->param.func);
8127         }
8128         cmdp->cmdtype = entry->cmdtype;
8129         cmdp->param = entry->u;
8130         cmdp->rehash = 0;
8131 }
8132
8133 static int FAST_FUNC
8134 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8135 {
8136         struct tblentry **pp;
8137         struct tblentry *cmdp;
8138         int c;
8139         struct cmdentry entry;
8140         char *name;
8141
8142         if (nextopt("r") != '\0') {
8143                 clearcmdentry(0);
8144                 return 0;
8145         }
8146
8147         if (*argptr == NULL) {
8148                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8149                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8150                                 if (cmdp->cmdtype == CMDNORMAL)
8151                                         printentry(cmdp);
8152                         }
8153                 }
8154                 return 0;
8155         }
8156
8157         c = 0;
8158         while ((name = *argptr) != NULL) {
8159                 cmdp = cmdlookup(name, 0);
8160                 if (cmdp != NULL
8161                  && (cmdp->cmdtype == CMDNORMAL
8162                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8163                 ) {
8164                         delete_cmd_entry();
8165                 }
8166                 find_command(name, &entry, DO_ERR, pathval());
8167                 if (entry.cmdtype == CMDUNKNOWN)
8168                         c = 1;
8169                 argptr++;
8170         }
8171         return c;
8172 }
8173
8174 /*
8175  * Called when a cd is done.  Marks all commands so the next time they
8176  * are executed they will be rehashed.
8177  */
8178 static void
8179 hashcd(void)
8180 {
8181         struct tblentry **pp;
8182         struct tblentry *cmdp;
8183
8184         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8185                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8186                         if (cmdp->cmdtype == CMDNORMAL
8187                          || (cmdp->cmdtype == CMDBUILTIN
8188                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8189                              && builtinloc > 0)
8190                         ) {
8191                                 cmdp->rehash = 1;
8192                         }
8193                 }
8194         }
8195 }
8196
8197 /*
8198  * Fix command hash table when PATH changed.
8199  * Called before PATH is changed.  The argument is the new value of PATH;
8200  * pathval() still returns the old value at this point.
8201  * Called with interrupts off.
8202  */
8203 static void FAST_FUNC
8204 changepath(const char *new)
8205 {
8206         const char *old;
8207         int firstchange;
8208         int idx;
8209         int idx_bltin;
8210
8211         old = pathval();
8212         firstchange = 9999;     /* assume no change */
8213         idx = 0;
8214         idx_bltin = -1;
8215         for (;;) {
8216                 if (*old != *new) {
8217                         firstchange = idx;
8218                         if ((*old == '\0' && *new == ':')
8219                          || (*old == ':' && *new == '\0')
8220                         ) {
8221                                 firstchange++;
8222                         }
8223                         old = new;      /* ignore subsequent differences */
8224                 }
8225                 if (*new == '\0')
8226                         break;
8227                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8228                         idx_bltin = idx;
8229                 if (*new == ':')
8230                         idx++;
8231                 new++;
8232                 old++;
8233         }
8234         if (builtinloc < 0 && idx_bltin >= 0)
8235                 builtinloc = idx_bltin;             /* zap builtins */
8236         if (builtinloc >= 0 && idx_bltin < 0)
8237                 firstchange = 0;
8238         clearcmdentry(firstchange);
8239         builtinloc = idx_bltin;
8240 }
8241 enum {
8242         TEOF,
8243         TNL,
8244         TREDIR,
8245         TWORD,
8246         TSEMI,
8247         TBACKGND,
8248         TAND,
8249         TOR,
8250         TPIPE,
8251         TLP,
8252         TRP,
8253         TENDCASE,
8254         TENDBQUOTE,
8255         TNOT,
8256         TCASE,
8257         TDO,
8258         TDONE,
8259         TELIF,
8260         TELSE,
8261         TESAC,
8262         TFI,
8263         TFOR,
8264 #if BASH_FUNCTION
8265         TFUNCTION,
8266 #endif
8267         TIF,
8268         TIN,
8269         TTHEN,
8270         TUNTIL,
8271         TWHILE,
8272         TBEGIN,
8273         TEND
8274 };
8275 typedef smallint token_id_t;
8276
8277 /* Nth bit indicates if token marks the end of a list */
8278 enum {
8279         tokendlist = 0
8280         /*  0 */ | (1u << TEOF)
8281         /*  1 */ | (0u << TNL)
8282         /*  2 */ | (0u << TREDIR)
8283         /*  3 */ | (0u << TWORD)
8284         /*  4 */ | (0u << TSEMI)
8285         /*  5 */ | (0u << TBACKGND)
8286         /*  6 */ | (0u << TAND)
8287         /*  7 */ | (0u << TOR)
8288         /*  8 */ | (0u << TPIPE)
8289         /*  9 */ | (0u << TLP)
8290         /* 10 */ | (1u << TRP)
8291         /* 11 */ | (1u << TENDCASE)
8292         /* 12 */ | (1u << TENDBQUOTE)
8293         /* 13 */ | (0u << TNOT)
8294         /* 14 */ | (0u << TCASE)
8295         /* 15 */ | (1u << TDO)
8296         /* 16 */ | (1u << TDONE)
8297         /* 17 */ | (1u << TELIF)
8298         /* 18 */ | (1u << TELSE)
8299         /* 19 */ | (1u << TESAC)
8300         /* 20 */ | (1u << TFI)
8301         /* 21 */ | (0u << TFOR)
8302 #if BASH_FUNCTION
8303         /* 22 */ | (0u << TFUNCTION)
8304 #endif
8305         /* 23 */ | (0u << TIF)
8306         /* 24 */ | (0u << TIN)
8307         /* 25 */ | (1u << TTHEN)
8308         /* 26 */ | (0u << TUNTIL)
8309         /* 27 */ | (0u << TWHILE)
8310         /* 28 */ | (0u << TBEGIN)
8311         /* 29 */ | (1u << TEND)
8312         , /* thus far 29 bits used */
8313 };
8314
8315 static const char *const tokname_array[] = {
8316         "end of file",
8317         "newline",
8318         "redirection",
8319         "word",
8320         ";",
8321         "&",
8322         "&&",
8323         "||",
8324         "|",
8325         "(",
8326         ")",
8327         ";;",
8328         "`",
8329 #define KWDOFFSET 13
8330         /* the following are keywords */
8331         "!",
8332         "case",
8333         "do",
8334         "done",
8335         "elif",
8336         "else",
8337         "esac",
8338         "fi",
8339         "for",
8340 #if BASH_FUNCTION
8341         "function",
8342 #endif
8343         "if",
8344         "in",
8345         "then",
8346         "until",
8347         "while",
8348         "{",
8349         "}",
8350 };
8351
8352 /* Wrapper around strcmp for qsort/bsearch/... */
8353 static int
8354 pstrcmp(const void *a, const void *b)
8355 {
8356         return strcmp((char*)a, *(char**)b);
8357 }
8358
8359 static const char *const *
8360 findkwd(const char *s)
8361 {
8362         return bsearch(s, tokname_array + KWDOFFSET,
8363                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8364                         sizeof(tokname_array[0]), pstrcmp);
8365 }
8366
8367 /*
8368  * Locate and print what a word is...
8369  */
8370 static int
8371 describe_command(char *command, const char *path, int describe_command_verbose)
8372 {
8373         struct cmdentry entry;
8374 #if ENABLE_ASH_ALIAS
8375         const struct alias *ap;
8376 #endif
8377
8378         path = path ? path : pathval();
8379
8380         if (describe_command_verbose) {
8381                 out1str(command);
8382         }
8383
8384         /* First look at the keywords */
8385         if (findkwd(command)) {
8386                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8387                 goto out;
8388         }
8389
8390 #if ENABLE_ASH_ALIAS
8391         /* Then look at the aliases */
8392         ap = lookupalias(command, 0);
8393         if (ap != NULL) {
8394                 if (!describe_command_verbose) {
8395                         out1str("alias ");
8396                         printalias(ap);
8397                         return 0;
8398                 }
8399                 out1fmt(" is an alias for %s", ap->val);
8400                 goto out;
8401         }
8402 #endif
8403         /* Brute force */
8404         find_command(command, &entry, DO_ABS, path);
8405
8406         switch (entry.cmdtype) {
8407         case CMDNORMAL: {
8408                 int j = entry.u.index;
8409                 char *p;
8410                 if (j < 0) {
8411                         p = command;
8412                 } else {
8413                         do {
8414                                 p = path_advance(&path, command);
8415                                 stunalloc(p);
8416                         } while (--j >= 0);
8417                 }
8418                 if (describe_command_verbose) {
8419                         out1fmt(" is %s", p);
8420                 } else {
8421                         out1str(p);
8422                 }
8423                 break;
8424         }
8425
8426         case CMDFUNCTION:
8427                 if (describe_command_verbose) {
8428                         out1str(" is a shell function");
8429                 } else {
8430                         out1str(command);
8431                 }
8432                 break;
8433
8434         case CMDBUILTIN:
8435                 if (describe_command_verbose) {
8436                         out1fmt(" is a %sshell builtin",
8437                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8438                                         "special " : nullstr
8439                         );
8440                 } else {
8441                         out1str(command);
8442                 }
8443                 break;
8444
8445         default:
8446                 if (describe_command_verbose) {
8447                         out1str(": not found\n");
8448                 }
8449                 return 127;
8450         }
8451  out:
8452         out1str("\n");
8453         return 0;
8454 }
8455
8456 static int FAST_FUNC
8457 typecmd(int argc UNUSED_PARAM, char **argv)
8458 {
8459         int i = 1;
8460         int err = 0;
8461         int verbose = 1;
8462
8463         /* type -p ... ? (we don't bother checking for 'p') */
8464         if (argv[1] && argv[1][0] == '-') {
8465                 i++;
8466                 verbose = 0;
8467         }
8468         while (argv[i]) {
8469                 err |= describe_command(argv[i++], NULL, verbose);
8470         }
8471         return err;
8472 }
8473
8474 #if ENABLE_ASH_CMDCMD
8475 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8476 static char **
8477 parse_command_args(char **argv, const char **path)
8478 {
8479         char *cp, c;
8480
8481         for (;;) {
8482                 cp = *++argv;
8483                 if (!cp)
8484                         return NULL;
8485                 if (*cp++ != '-')
8486                         break;
8487                 c = *cp++;
8488                 if (!c)
8489                         break;
8490                 if (c == '-' && !*cp) {
8491                         if (!*++argv)
8492                                 return NULL;
8493                         break;
8494                 }
8495                 do {
8496                         switch (c) {
8497                         case 'p':
8498                                 *path = bb_default_path;
8499                                 break;
8500                         default:
8501                                 /* run 'typecmd' for other options */
8502                                 return NULL;
8503                         }
8504                         c = *cp++;
8505                 } while (c);
8506         }
8507         return argv;
8508 }
8509
8510 static int FAST_FUNC
8511 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8512 {
8513         char *cmd;
8514         int c;
8515         enum {
8516                 VERIFY_BRIEF = 1,
8517                 VERIFY_VERBOSE = 2,
8518         } verify = 0;
8519         const char *path = NULL;
8520
8521         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8522          * never reaches this function.
8523          */
8524
8525         while ((c = nextopt("pvV")) != '\0')
8526                 if (c == 'V')
8527                         verify |= VERIFY_VERBOSE;
8528                 else if (c == 'v')
8529                         /*verify |= VERIFY_BRIEF*/;
8530 #if DEBUG
8531                 else if (c != 'p')
8532                         abort();
8533 #endif
8534                 else
8535                         path = bb_default_path;
8536
8537         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8538         cmd = *argptr;
8539         if (/*verify && */ cmd)
8540                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8541
8542         return 0;
8543 }
8544 #endif
8545
8546
8547 /*static int funcblocksize;     // size of structures in function */
8548 /*static int funcstringsize;    // size of strings in node */
8549 static void *funcblock;         /* block to allocate function from */
8550 static char *funcstring_end;    /* end of block to allocate strings from */
8551
8552 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8553         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8554         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8555         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8556         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8557         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8558         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8559         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8560         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8561         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8562         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8563         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8564         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8565         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8566         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8567         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8568         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8569         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8570 #if BASH_REDIR_OUTPUT
8571         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8572 #endif
8573         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8574         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8575         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8576         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8577         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8578         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8579         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8580         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8581         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8582 };
8583
8584 static int calcsize(int funcblocksize, union node *n);
8585
8586 static int
8587 sizenodelist(int funcblocksize, struct nodelist *lp)
8588 {
8589         while (lp) {
8590                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8591                 funcblocksize = calcsize(funcblocksize, lp->n);
8592                 lp = lp->next;
8593         }
8594         return funcblocksize;
8595 }
8596
8597 static int
8598 calcsize(int funcblocksize, union node *n)
8599 {
8600         if (n == NULL)
8601                 return funcblocksize;
8602         funcblocksize += nodesize[n->type];
8603         switch (n->type) {
8604         case NCMD:
8605                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8606                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8607                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8608                 break;
8609         case NPIPE:
8610                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8611                 break;
8612         case NREDIR:
8613         case NBACKGND:
8614         case NSUBSHELL:
8615                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8616                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8617                 break;
8618         case NAND:
8619         case NOR:
8620         case NSEMI:
8621         case NWHILE:
8622         case NUNTIL:
8623                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8624                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8625                 break;
8626         case NIF:
8627                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8628                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8629                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8630                 break;
8631         case NFOR:
8632                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8633                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8634                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8635                 break;
8636         case NCASE:
8637                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8638                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8639                 break;
8640         case NCLIST:
8641                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8642                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8643                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8644                 break;
8645         case NDEFUN:
8646         case NARG:
8647                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8648                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8649                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8650                 break;
8651         case NTO:
8652 #if BASH_REDIR_OUTPUT
8653         case NTO2:
8654 #endif
8655         case NCLOBBER:
8656         case NFROM:
8657         case NFROMTO:
8658         case NAPPEND:
8659                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8660                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8661                 break;
8662         case NTOFD:
8663         case NFROMFD:
8664                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8665                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8666         break;
8667         case NHERE:
8668         case NXHERE:
8669                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8670                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8671                 break;
8672         case NNOT:
8673                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8674                 break;
8675         };
8676         return funcblocksize;
8677 }
8678
8679 static char *
8680 nodeckstrdup(char *s)
8681 {
8682         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8683         return strcpy(funcstring_end, s);
8684 }
8685
8686 static union node *copynode(union node *);
8687
8688 static struct nodelist *
8689 copynodelist(struct nodelist *lp)
8690 {
8691         struct nodelist *start;
8692         struct nodelist **lpp;
8693
8694         lpp = &start;
8695         while (lp) {
8696                 *lpp = funcblock;
8697                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8698                 (*lpp)->n = copynode(lp->n);
8699                 lp = lp->next;
8700                 lpp = &(*lpp)->next;
8701         }
8702         *lpp = NULL;
8703         return start;
8704 }
8705
8706 static union node *
8707 copynode(union node *n)
8708 {
8709         union node *new;
8710
8711         if (n == NULL)
8712                 return NULL;
8713         new = funcblock;
8714         funcblock = (char *) funcblock + nodesize[n->type];
8715
8716         switch (n->type) {
8717         case NCMD:
8718                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8719                 new->ncmd.args = copynode(n->ncmd.args);
8720                 new->ncmd.assign = copynode(n->ncmd.assign);
8721                 break;
8722         case NPIPE:
8723                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8724                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8725                 break;
8726         case NREDIR:
8727         case NBACKGND:
8728         case NSUBSHELL:
8729                 new->nredir.redirect = copynode(n->nredir.redirect);
8730                 new->nredir.n = copynode(n->nredir.n);
8731                 break;
8732         case NAND:
8733         case NOR:
8734         case NSEMI:
8735         case NWHILE:
8736         case NUNTIL:
8737                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8738                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8739                 break;
8740         case NIF:
8741                 new->nif.elsepart = copynode(n->nif.elsepart);
8742                 new->nif.ifpart = copynode(n->nif.ifpart);
8743                 new->nif.test = copynode(n->nif.test);
8744                 break;
8745         case NFOR:
8746                 new->nfor.var = nodeckstrdup(n->nfor.var);
8747                 new->nfor.body = copynode(n->nfor.body);
8748                 new->nfor.args = copynode(n->nfor.args);
8749                 break;
8750         case NCASE:
8751                 new->ncase.cases = copynode(n->ncase.cases);
8752                 new->ncase.expr = copynode(n->ncase.expr);
8753                 break;
8754         case NCLIST:
8755                 new->nclist.body = copynode(n->nclist.body);
8756                 new->nclist.pattern = copynode(n->nclist.pattern);
8757                 new->nclist.next = copynode(n->nclist.next);
8758                 break;
8759         case NDEFUN:
8760         case NARG:
8761                 new->narg.backquote = copynodelist(n->narg.backquote);
8762                 new->narg.text = nodeckstrdup(n->narg.text);
8763                 new->narg.next = copynode(n->narg.next);
8764                 break;
8765         case NTO:
8766 #if BASH_REDIR_OUTPUT
8767         case NTO2:
8768 #endif
8769         case NCLOBBER:
8770         case NFROM:
8771         case NFROMTO:
8772         case NAPPEND:
8773                 new->nfile.fname = copynode(n->nfile.fname);
8774                 new->nfile.fd = n->nfile.fd;
8775                 new->nfile.next = copynode(n->nfile.next);
8776                 break;
8777         case NTOFD:
8778         case NFROMFD:
8779                 new->ndup.vname = copynode(n->ndup.vname);
8780                 new->ndup.dupfd = n->ndup.dupfd;
8781                 new->ndup.fd = n->ndup.fd;
8782                 new->ndup.next = copynode(n->ndup.next);
8783                 break;
8784         case NHERE:
8785         case NXHERE:
8786                 new->nhere.doc = copynode(n->nhere.doc);
8787                 new->nhere.fd = n->nhere.fd;
8788                 new->nhere.next = copynode(n->nhere.next);
8789                 break;
8790         case NNOT:
8791                 new->nnot.com = copynode(n->nnot.com);
8792                 break;
8793         };
8794         new->type = n->type;
8795         return new;
8796 }
8797
8798 /*
8799  * Make a copy of a parse tree.
8800  */
8801 static struct funcnode *
8802 copyfunc(union node *n)
8803 {
8804         struct funcnode *f;
8805         size_t blocksize;
8806
8807         /*funcstringsize = 0;*/
8808         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8809         f = ckzalloc(blocksize /* + funcstringsize */);
8810         funcblock = (char *) f + offsetof(struct funcnode, n);
8811         funcstring_end = (char *) f + blocksize;
8812         copynode(n);
8813         /* f->count = 0; - ckzalloc did it */
8814         return f;
8815 }
8816
8817 /*
8818  * Define a shell function.
8819  */
8820 static void
8821 defun(union node *func)
8822 {
8823         struct cmdentry entry;
8824
8825         INT_OFF;
8826         entry.cmdtype = CMDFUNCTION;
8827         entry.u.func = copyfunc(func);
8828         addcmdentry(func->narg.text, &entry);
8829         INT_ON;
8830 }
8831
8832 /* Reasons for skipping commands (see comment on breakcmd routine) */
8833 #define SKIPBREAK      (1 << 0)
8834 #define SKIPCONT       (1 << 1)
8835 #define SKIPFUNC       (1 << 2)
8836 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8837 static int skipcount;           /* number of levels to skip */
8838 static int funcnest;            /* depth of function calls */
8839 static int loopnest;            /* current loop nesting level */
8840
8841 /* Forward decl way out to parsing code - dotrap needs it */
8842 static int evalstring(char *s, int flags);
8843
8844 /* Called to execute a trap.
8845  * Single callsite - at the end of evaltree().
8846  * If we return non-zero, evaltree raises EXEXIT exception.
8847  *
8848  * Perhaps we should avoid entering new trap handlers
8849  * while we are executing a trap handler. [is it a TODO?]
8850  */
8851 static void
8852 dotrap(void)
8853 {
8854         uint8_t *g;
8855         int sig;
8856         uint8_t last_status;
8857
8858         if (!pending_sig)
8859                 return;
8860
8861         last_status = exitstatus;
8862         pending_sig = 0;
8863         barrier();
8864
8865         TRACE(("dotrap entered\n"));
8866         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8867                 char *p;
8868
8869                 if (!*g)
8870                         continue;
8871
8872                 if (evalskip) {
8873                         pending_sig = sig;
8874                         break;
8875                 }
8876
8877                 p = trap[sig];
8878                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8879                  * don't upset it by resetting gotsig[SIGINT-1] */
8880                 if (sig == SIGINT && !p)
8881                         continue;
8882
8883                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8884                 *g = 0;
8885                 if (!p)
8886                         continue;
8887                 evalstring(p, 0);
8888         }
8889         exitstatus = last_status;
8890         TRACE(("dotrap returns\n"));
8891 }
8892
8893 /* forward declarations - evaluation is fairly recursive business... */
8894 static int evalloop(union node *, int);
8895 static int evalfor(union node *, int);
8896 static int evalcase(union node *, int);
8897 static int evalsubshell(union node *, int);
8898 static void expredir(union node *);
8899 static int evalpipe(union node *, int);
8900 static int evalcommand(union node *, int);
8901 static int evalbltin(const struct builtincmd *, int, char **, int);
8902 static void prehash(union node *);
8903
8904 /*
8905  * Evaluate a parse tree.  The value is left in the global variable
8906  * exitstatus.
8907  */
8908 static int
8909 evaltree(union node *n, int flags)
8910 {
8911         int checkexit = 0;
8912         int (*evalfn)(union node *, int);
8913         int status = 0;
8914
8915         if (n == NULL) {
8916                 TRACE(("evaltree(NULL) called\n"));
8917                 goto out;
8918         }
8919         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8920
8921         dotrap();
8922
8923         switch (n->type) {
8924         default:
8925 #if DEBUG
8926                 out1fmt("Node type = %d\n", n->type);
8927                 fflush_all();
8928                 break;
8929 #endif
8930         case NNOT:
8931                 status = !evaltree(n->nnot.com, EV_TESTED);
8932                 goto setstatus;
8933         case NREDIR:
8934                 expredir(n->nredir.redirect);
8935                 pushredir(n->nredir.redirect);
8936                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8937                 if (!status) {
8938                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8939                 }
8940                 if (n->nredir.redirect)
8941                         popredir(/*drop:*/ 0);
8942                 goto setstatus;
8943         case NCMD:
8944                 evalfn = evalcommand;
8945  checkexit:
8946                 if (eflag && !(flags & EV_TESTED))
8947                         checkexit = ~0;
8948                 goto calleval;
8949         case NFOR:
8950                 evalfn = evalfor;
8951                 goto calleval;
8952         case NWHILE:
8953         case NUNTIL:
8954                 evalfn = evalloop;
8955                 goto calleval;
8956         case NSUBSHELL:
8957         case NBACKGND:
8958                 evalfn = evalsubshell;
8959                 goto checkexit;
8960         case NPIPE:
8961                 evalfn = evalpipe;
8962                 goto checkexit;
8963         case NCASE:
8964                 evalfn = evalcase;
8965                 goto calleval;
8966         case NAND:
8967         case NOR:
8968         case NSEMI: {
8969
8970 #if NAND + 1 != NOR
8971 #error NAND + 1 != NOR
8972 #endif
8973 #if NOR + 1 != NSEMI
8974 #error NOR + 1 != NSEMI
8975 #endif
8976                 unsigned is_or = n->type - NAND;
8977                 status = evaltree(
8978                         n->nbinary.ch1,
8979                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8980                 );
8981                 if ((!status) == is_or || evalskip)
8982                         break;
8983                 n = n->nbinary.ch2;
8984  evaln:
8985                 evalfn = evaltree;
8986  calleval:
8987                 status = evalfn(n, flags);
8988                 goto setstatus;
8989         }
8990         case NIF:
8991                 status = evaltree(n->nif.test, EV_TESTED);
8992                 if (evalskip)
8993                         break;
8994                 if (!status) {
8995                         n = n->nif.ifpart;
8996                         goto evaln;
8997                 }
8998                 if (n->nif.elsepart) {
8999                         n = n->nif.elsepart;
9000                         goto evaln;
9001                 }
9002                 status = 0;
9003                 goto setstatus;
9004         case NDEFUN:
9005                 defun(n);
9006                 /* Not necessary. To test it:
9007                  * "false; f() { qwerty; }; echo $?" should print 0.
9008                  */
9009                 /* status = 0; */
9010  setstatus:
9011                 exitstatus = status;
9012                 break;
9013         }
9014  out:
9015         /* Order of checks below is important:
9016          * signal handlers trigger before exit caused by "set -e".
9017          */
9018         dotrap();
9019
9020         if (checkexit & status)
9021                 raise_exception(EXEXIT);
9022         if (flags & EV_EXIT)
9023                 raise_exception(EXEXIT);
9024
9025         TRACE(("leaving evaltree (no interrupts)\n"));
9026         return exitstatus;
9027 }
9028
9029 static int
9030 skiploop(void)
9031 {
9032         int skip = evalskip;
9033
9034         switch (skip) {
9035         case 0:
9036                 break;
9037         case SKIPBREAK:
9038         case SKIPCONT:
9039                 if (--skipcount <= 0) {
9040                         evalskip = 0;
9041                         break;
9042                 }
9043                 skip = SKIPBREAK;
9044                 break;
9045         }
9046         return skip;
9047 }
9048
9049 static int
9050 evalloop(union node *n, int flags)
9051 {
9052         int skip;
9053         int status;
9054
9055         loopnest++;
9056         status = 0;
9057         flags &= EV_TESTED;
9058         do {
9059                 int i;
9060
9061                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9062                 skip = skiploop();
9063                 if (skip == SKIPFUNC)
9064                         status = i;
9065                 if (skip)
9066                         continue;
9067                 if (n->type != NWHILE)
9068                         i = !i;
9069                 if (i != 0)
9070                         break;
9071                 status = evaltree(n->nbinary.ch2, flags);
9072                 skip = skiploop();
9073         } while (!(skip & ~SKIPCONT));
9074         loopnest--;
9075
9076         return status;
9077 }
9078
9079 static int
9080 evalfor(union node *n, int flags)
9081 {
9082         struct arglist arglist;
9083         union node *argp;
9084         struct strlist *sp;
9085         struct stackmark smark;
9086         int status = 0;
9087
9088         setstackmark(&smark);
9089         arglist.list = NULL;
9090         arglist.lastp = &arglist.list;
9091         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9092                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9093         }
9094         *arglist.lastp = NULL;
9095
9096         loopnest++;
9097         flags &= EV_TESTED;
9098         for (sp = arglist.list; sp; sp = sp->next) {
9099                 setvar0(n->nfor.var, sp->text);
9100                 status = evaltree(n->nfor.body, flags);
9101                 if (skiploop() & ~SKIPCONT)
9102                         break;
9103         }
9104         loopnest--;
9105         popstackmark(&smark);
9106
9107         return status;
9108 }
9109
9110 static int
9111 evalcase(union node *n, int flags)
9112 {
9113         union node *cp;
9114         union node *patp;
9115         struct arglist arglist;
9116         struct stackmark smark;
9117         int status = 0;
9118
9119         setstackmark(&smark);
9120         arglist.list = NULL;
9121         arglist.lastp = &arglist.list;
9122         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9123         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9124                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9125                         if (casematch(patp, arglist.list->text)) {
9126                                 /* Ensure body is non-empty as otherwise
9127                                  * EV_EXIT may prevent us from setting the
9128                                  * exit status.
9129                                  */
9130                                 if (evalskip == 0 && cp->nclist.body) {
9131                                         status = evaltree(cp->nclist.body, flags);
9132                                 }
9133                                 goto out;
9134                         }
9135                 }
9136         }
9137  out:
9138         popstackmark(&smark);
9139
9140         return status;
9141 }
9142
9143 /*
9144  * Kick off a subshell to evaluate a tree.
9145  */
9146 static int
9147 evalsubshell(union node *n, int flags)
9148 {
9149         struct job *jp;
9150         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9151         int status;
9152
9153         expredir(n->nredir.redirect);
9154         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9155                 goto nofork;
9156         INT_OFF;
9157         if (backgnd == FORK_FG)
9158                 get_tty_state();
9159         jp = makejob(/*n,*/ 1);
9160         if (forkshell(jp, n, backgnd) == 0) {
9161                 /* child */
9162                 INT_ON;
9163                 flags |= EV_EXIT;
9164                 if (backgnd)
9165                         flags &= ~EV_TESTED;
9166  nofork:
9167                 redirect(n->nredir.redirect, 0);
9168                 evaltreenr(n->nredir.n, flags);
9169                 /* never returns */
9170         }
9171         /* parent */
9172         status = 0;
9173         if (backgnd == FORK_FG)
9174                 status = waitforjob(jp);
9175         INT_ON;
9176         return status;
9177 }
9178
9179 /*
9180  * Compute the names of the files in a redirection list.
9181  */
9182 static void fixredir(union node *, const char *, int);
9183 static void
9184 expredir(union node *n)
9185 {
9186         union node *redir;
9187
9188         for (redir = n; redir; redir = redir->nfile.next) {
9189                 struct arglist fn;
9190
9191                 fn.list = NULL;
9192                 fn.lastp = &fn.list;
9193                 switch (redir->type) {
9194                 case NFROMTO:
9195                 case NFROM:
9196                 case NTO:
9197 #if BASH_REDIR_OUTPUT
9198                 case NTO2:
9199 #endif
9200                 case NCLOBBER:
9201                 case NAPPEND:
9202                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9203                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9204 #if BASH_REDIR_OUTPUT
9205  store_expfname:
9206 #endif
9207 #if 0
9208 // By the design of stack allocator, the loop of this kind:
9209 //      while true; do while true; do break; done </dev/null; done
9210 // will look like a memory leak: ash plans to free expfname's
9211 // of "/dev/null" as soon as it finishes running the loop
9212 // (in this case, never).
9213 // This "fix" is wrong:
9214                         if (redir->nfile.expfname)
9215                                 stunalloc(redir->nfile.expfname);
9216 // It results in corrupted state of stacked allocations.
9217 #endif
9218                         redir->nfile.expfname = fn.list->text;
9219                         break;
9220                 case NFROMFD:
9221                 case NTOFD: /* >& */
9222                         if (redir->ndup.vname) {
9223                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9224                                 if (fn.list == NULL)
9225                                         ash_msg_and_raise_error("redir error");
9226 #if BASH_REDIR_OUTPUT
9227 //FIXME: we used expandarg with different args!
9228                                 if (!isdigit_str9(fn.list->text)) {
9229                                         /* >&file, not >&fd */
9230                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9231                                                 ash_msg_and_raise_error("redir error");
9232                                         redir->type = NTO2;
9233                                         goto store_expfname;
9234                                 }
9235 #endif
9236                                 fixredir(redir, fn.list->text, 1);
9237                         }
9238                         break;
9239                 }
9240         }
9241 }
9242
9243 /*
9244  * Evaluate a pipeline.  All the processes in the pipeline are children
9245  * of the process creating the pipeline.  (This differs from some versions
9246  * of the shell, which make the last process in a pipeline the parent
9247  * of all the rest.)
9248  */
9249 static int
9250 evalpipe(union node *n, int flags)
9251 {
9252         struct job *jp;
9253         struct nodelist *lp;
9254         int pipelen;
9255         int prevfd;
9256         int pip[2];
9257         int status = 0;
9258
9259         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9260         pipelen = 0;
9261         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9262                 pipelen++;
9263         flags |= EV_EXIT;
9264         INT_OFF;
9265         if (n->npipe.pipe_backgnd == 0)
9266                 get_tty_state();
9267         jp = makejob(/*n,*/ pipelen);
9268         prevfd = -1;
9269         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9270                 prehash(lp->n);
9271                 pip[1] = -1;
9272                 if (lp->next) {
9273                         if (pipe(pip) < 0) {
9274                                 close(prevfd);
9275                                 ash_msg_and_raise_perror("can't create pipe");
9276                         }
9277                 }
9278                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9279                         /* child */
9280                         INT_ON;
9281                         if (pip[1] >= 0) {
9282                                 close(pip[0]);
9283                         }
9284                         if (prevfd > 0) {
9285                                 dup2(prevfd, 0);
9286                                 close(prevfd);
9287                         }
9288                         if (pip[1] > 1) {
9289                                 dup2(pip[1], 1);
9290                                 close(pip[1]);
9291                         }
9292                         evaltreenr(lp->n, flags);
9293                         /* never returns */
9294                 }
9295                 /* parent */
9296                 if (prevfd >= 0)
9297                         close(prevfd);
9298                 prevfd = pip[0];
9299                 /* Don't want to trigger debugging */
9300                 if (pip[1] != -1)
9301                         close(pip[1]);
9302         }
9303         if (n->npipe.pipe_backgnd == 0) {
9304                 status = waitforjob(jp);
9305                 TRACE(("evalpipe:  job done exit status %d\n", status));
9306         }
9307         INT_ON;
9308
9309         return status;
9310 }
9311
9312 /*
9313  * Controls whether the shell is interactive or not.
9314  */
9315 static void
9316 setinteractive(int on)
9317 {
9318         static smallint is_interactive;
9319
9320         if (++on == is_interactive)
9321                 return;
9322         is_interactive = on;
9323         setsignal(SIGINT);
9324         setsignal(SIGQUIT);
9325         setsignal(SIGTERM);
9326 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9327         if (is_interactive > 1) {
9328                 /* Looks like they want an interactive shell */
9329                 static smallint did_banner;
9330
9331                 if (!did_banner) {
9332                         /* note: ash and hush share this string */
9333                         out1fmt("\n\n%s %s\n"
9334                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9335                                 "\n",
9336                                 bb_banner,
9337                                 "built-in shell (ash)"
9338                         );
9339                         did_banner = 1;
9340                 }
9341         }
9342 #endif
9343 }
9344
9345 static void
9346 optschanged(void)
9347 {
9348 #if DEBUG
9349         opentrace();
9350 #endif
9351         setinteractive(iflag);
9352         setjobctl(mflag);
9353 #if ENABLE_FEATURE_EDITING_VI
9354         if (viflag)
9355                 line_input_state->flags |= VI_MODE;
9356         else
9357                 line_input_state->flags &= ~VI_MODE;
9358 #else
9359         viflag = 0; /* forcibly keep the option off */
9360 #endif
9361 }
9362
9363 struct localvar_list {
9364         struct localvar_list *next;
9365         struct localvar *lv;
9366 };
9367
9368 static struct localvar_list *localvar_stack;
9369
9370 /*
9371  * Called after a function returns.
9372  * Interrupts must be off.
9373  */
9374 static void
9375 poplocalvars(int keep)
9376 {
9377         struct localvar_list *ll;
9378         struct localvar *lvp, *next;
9379         struct var *vp;
9380
9381         INT_OFF;
9382         ll = localvar_stack;
9383         localvar_stack = ll->next;
9384
9385         next = ll->lv;
9386         free(ll);
9387
9388         while ((lvp = next) != NULL) {
9389                 next = lvp->next;
9390                 vp = lvp->vp;
9391                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9392                 if (keep) {
9393                         int bits = VSTRFIXED;
9394
9395                         if (lvp->flags != VUNSET) {
9396                                 if (vp->var_text == lvp->text)
9397                                         bits |= VTEXTFIXED;
9398                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9399                                         free((char*)lvp->text);
9400                         }
9401
9402                         vp->flags &= ~bits;
9403                         vp->flags |= (lvp->flags & bits);
9404
9405                         if ((vp->flags &
9406                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9407                                 unsetvar(vp->var_text);
9408                 } else if (vp == NULL) {        /* $- saved */
9409                         memcpy(optlist, lvp->text, sizeof(optlist));
9410                         free((char*)lvp->text);
9411                         optschanged();
9412                 } else if (lvp->flags == VUNSET) {
9413                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9414                         unsetvar(vp->var_text);
9415                 } else {
9416                         if (vp->var_func)
9417                                 vp->var_func(var_end(lvp->text));
9418                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9419                                 free((char*)vp->var_text);
9420                         vp->flags = lvp->flags;
9421                         vp->var_text = lvp->text;
9422                 }
9423                 free(lvp);
9424         }
9425         INT_ON;
9426 }
9427
9428 /*
9429  * Create a new localvar environment.
9430  */
9431 static struct localvar_list *
9432 pushlocalvars(void)
9433 {
9434         struct localvar_list *ll;
9435
9436         INT_OFF;
9437         ll = ckzalloc(sizeof(*ll));
9438         /*ll->lv = NULL; - zalloc did it */
9439         ll->next = localvar_stack;
9440         localvar_stack = ll;
9441         INT_ON;
9442
9443         return ll->next;
9444 }
9445
9446 static void
9447 unwindlocalvars(struct localvar_list *stop)
9448 {
9449         while (localvar_stack != stop)
9450                 poplocalvars(0);
9451 }
9452
9453 static int
9454 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9455 {
9456         volatile struct shparam saveparam;
9457         struct jmploc *volatile savehandler;
9458         struct jmploc jmploc;
9459         int e;
9460
9461         saveparam = shellparam;
9462         savehandler = exception_handler;
9463         e = setjmp(jmploc.loc);
9464         if (e) {
9465                 goto funcdone;
9466         }
9467         INT_OFF;
9468         exception_handler = &jmploc;
9469         shellparam.malloced = 0;
9470         func->count++;
9471         funcnest++;
9472         INT_ON;
9473         shellparam.nparam = argc - 1;
9474         shellparam.p = argv + 1;
9475 #if ENABLE_ASH_GETOPTS
9476         shellparam.optind = 1;
9477         shellparam.optoff = -1;
9478 #endif
9479         pushlocalvars();
9480         evaltree(func->n.narg.next, flags & EV_TESTED);
9481         poplocalvars(0);
9482  funcdone:
9483         INT_OFF;
9484         funcnest--;
9485         freefunc(func);
9486         freeparam(&shellparam);
9487         shellparam = saveparam;
9488         exception_handler = savehandler;
9489         INT_ON;
9490         evalskip &= ~SKIPFUNC;
9491         return e;
9492 }
9493
9494 /*
9495  * Make a variable a local variable.  When a variable is made local, it's
9496  * value and flags are saved in a localvar structure.  The saved values
9497  * will be restored when the shell function returns.  We handle the name
9498  * "-" as a special case: it makes changes to "set +-options" local
9499  * (options will be restored on return from the function).
9500  */
9501 static void
9502 mklocal(char *name)
9503 {
9504         struct localvar *lvp;
9505         struct var **vpp;
9506         struct var *vp;
9507         char *eq = strchr(name, '=');
9508
9509         INT_OFF;
9510         /* Cater for duplicate "local". Examples:
9511          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9512          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9513          */
9514         lvp = localvar_stack->lv;
9515         while (lvp) {
9516                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9517                         if (eq)
9518                                 setvareq(name, 0);
9519                         /* else:
9520                          * it's a duplicate "local VAR" declaration, do nothing
9521                          */
9522                         goto ret;
9523                 }
9524                 lvp = lvp->next;
9525         }
9526
9527         lvp = ckzalloc(sizeof(*lvp));
9528         if (LONE_DASH(name)) {
9529                 char *p;
9530                 p = ckmalloc(sizeof(optlist));
9531                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9532                 vp = NULL;
9533         } else {
9534                 vpp = hashvar(name);
9535                 vp = *findvar(vpp, name);
9536                 if (vp == NULL) {
9537                         /* variable did not exist yet */
9538                         if (eq)
9539                                 vp = setvareq(name, VSTRFIXED);
9540                         else
9541                                 vp = setvar(name, NULL, VSTRFIXED);
9542                         lvp->flags = VUNSET;
9543                 } else {
9544                         lvp->text = vp->var_text;
9545                         lvp->flags = vp->flags;
9546                         /* make sure neither "struct var" nor string gets freed
9547                          * during (un)setting:
9548                          */
9549                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9550                         if (eq)
9551                                 setvareq(name, 0);
9552                         else
9553                                 /* "local VAR" unsets VAR: */
9554                                 setvar0(name, NULL);
9555                 }
9556         }
9557         lvp->vp = vp;
9558         lvp->next = localvar_stack->lv;
9559         localvar_stack->lv = lvp;
9560  ret:
9561         INT_ON;
9562 }
9563
9564 /*
9565  * The "local" command.
9566  */
9567 static int FAST_FUNC
9568 localcmd(int argc UNUSED_PARAM, char **argv)
9569 {
9570         char *name;
9571
9572         if (!localvar_stack)
9573                 ash_msg_and_raise_error("not in a function");
9574
9575         argv = argptr;
9576         while ((name = *argv++) != NULL) {
9577                 mklocal(name);
9578         }
9579         return 0;
9580 }
9581
9582 static int FAST_FUNC
9583 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9584 {
9585         return 1;
9586 }
9587
9588 static int FAST_FUNC
9589 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9590 {
9591         return 0;
9592 }
9593
9594 static int FAST_FUNC
9595 execcmd(int argc UNUSED_PARAM, char **argv)
9596 {
9597         optionarg = NULL;
9598         while (nextopt("a:") != '\0')
9599                 /* nextopt() sets optionarg to "-a ARGV0" */;
9600
9601         argv = argptr;
9602         if (argv[0]) {
9603                 char *prog;
9604
9605                 iflag = 0;              /* exit on error */
9606                 mflag = 0;
9607                 optschanged();
9608                 /* We should set up signals for "exec CMD"
9609                  * the same way as for "CMD" without "exec".
9610                  * But optschanged->setinteractive->setsignal
9611                  * still thought we are a root shell. Therefore, for example,
9612                  * SIGQUIT is still set to IGN. Fix it:
9613                  */
9614                 shlvl++;
9615                 setsignal(SIGQUIT);
9616                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9617                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9618                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9619
9620                 prog = argv[0];
9621                 if (optionarg)
9622                         argv[0] = optionarg;
9623                 shellexec(prog, argv, pathval(), 0);
9624                 /* NOTREACHED */
9625         }
9626         return 0;
9627 }
9628
9629 /*
9630  * The return command.
9631  */
9632 static int FAST_FUNC
9633 returncmd(int argc UNUSED_PARAM, char **argv)
9634 {
9635         /*
9636          * If called outside a function, do what ksh does;
9637          * skip the rest of the file.
9638          */
9639         evalskip = SKIPFUNC;
9640         return argv[1] ? number(argv[1]) : exitstatus;
9641 }
9642
9643 /* Forward declarations for builtintab[] */
9644 static int breakcmd(int, char **) FAST_FUNC;
9645 static int dotcmd(int, char **) FAST_FUNC;
9646 static int evalcmd(int, char **, int) FAST_FUNC;
9647 static int exitcmd(int, char **) FAST_FUNC;
9648 static int exportcmd(int, char **) FAST_FUNC;
9649 #if ENABLE_ASH_GETOPTS
9650 static int getoptscmd(int, char **) FAST_FUNC;
9651 #endif
9652 #if ENABLE_ASH_HELP
9653 static int helpcmd(int, char **) FAST_FUNC;
9654 #endif
9655 #if MAX_HISTORY
9656 static int historycmd(int, char **) FAST_FUNC;
9657 #endif
9658 #if ENABLE_FEATURE_SH_MATH
9659 static int letcmd(int, char **) FAST_FUNC;
9660 #endif
9661 static int readcmd(int, char **) FAST_FUNC;
9662 static int setcmd(int, char **) FAST_FUNC;
9663 static int shiftcmd(int, char **) FAST_FUNC;
9664 static int timescmd(int, char **) FAST_FUNC;
9665 static int trapcmd(int, char **) FAST_FUNC;
9666 static int umaskcmd(int, char **) FAST_FUNC;
9667 static int unsetcmd(int, char **) FAST_FUNC;
9668 static int ulimitcmd(int, char **) FAST_FUNC;
9669
9670 #define BUILTIN_NOSPEC          "0"
9671 #define BUILTIN_SPECIAL         "1"
9672 #define BUILTIN_REGULAR         "2"
9673 #define BUILTIN_SPEC_REG        "3"
9674 #define BUILTIN_ASSIGN          "4"
9675 #define BUILTIN_SPEC_ASSG       "5"
9676 #define BUILTIN_REG_ASSG        "6"
9677 #define BUILTIN_SPEC_REG_ASSG   "7"
9678
9679 /* Stubs for calling non-FAST_FUNC's */
9680 #if ENABLE_ASH_ECHO
9681 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9682 #endif
9683 #if ENABLE_ASH_PRINTF
9684 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9685 #endif
9686 #if ENABLE_ASH_TEST || BASH_TEST2
9687 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9688 #endif
9689
9690 /* Keep these in proper order since it is searched via bsearch() */
9691 static const struct builtincmd builtintab[] = {
9692         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9693         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9694 #if ENABLE_ASH_TEST
9695         { BUILTIN_REGULAR       "["       , testcmd    },
9696 #endif
9697 #if BASH_TEST2
9698         { BUILTIN_REGULAR       "[["      , testcmd    },
9699 #endif
9700 #if ENABLE_ASH_ALIAS
9701         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9702 #endif
9703 #if JOBS
9704         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9705 #endif
9706         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9707         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9708         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9709 #if ENABLE_ASH_CMDCMD
9710         { BUILTIN_REGULAR       "command" , commandcmd },
9711 #endif
9712         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9713 #if ENABLE_ASH_ECHO
9714         { BUILTIN_REGULAR       "echo"    , echocmd    },
9715 #endif
9716         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9717         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9718         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9719         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9720         { BUILTIN_REGULAR       "false"   , falsecmd   },
9721 #if JOBS
9722         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9723 #endif
9724 #if ENABLE_ASH_GETOPTS
9725         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9726 #endif
9727         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9728 #if ENABLE_ASH_HELP
9729         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9730 #endif
9731 #if MAX_HISTORY
9732         { BUILTIN_NOSPEC        "history" , historycmd },
9733 #endif
9734 #if JOBS
9735         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9736         { BUILTIN_REGULAR       "kill"    , killcmd    },
9737 #endif
9738 #if ENABLE_FEATURE_SH_MATH
9739         { BUILTIN_NOSPEC        "let"     , letcmd     },
9740 #endif
9741         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9742 #if ENABLE_ASH_PRINTF
9743         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9744 #endif
9745         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9746         { BUILTIN_REGULAR       "read"    , readcmd    },
9747         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9748         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9749         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9750         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9751 #if BASH_SOURCE
9752         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9753 #endif
9754 #if ENABLE_ASH_TEST
9755         { BUILTIN_REGULAR       "test"    , testcmd    },
9756 #endif
9757         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9758         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9759         { BUILTIN_REGULAR       "true"    , truecmd    },
9760         { BUILTIN_NOSPEC        "type"    , typecmd    },
9761         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9762         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9763 #if ENABLE_ASH_ALIAS
9764         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9765 #endif
9766         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9767         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9768 };
9769
9770 /* Should match the above table! */
9771 #define COMMANDCMD (builtintab + \
9772         /* . : */       2 + \
9773         /* [ */         1 * ENABLE_ASH_TEST + \
9774         /* [[ */        1 * BASH_TEST2 + \
9775         /* alias */     1 * ENABLE_ASH_ALIAS + \
9776         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9777         /* break cd cddir  */   3)
9778 #define EVALCMD (COMMANDCMD + \
9779         /* command */   1 * ENABLE_ASH_CMDCMD + \
9780         /* continue */  1 + \
9781         /* echo */      1 * ENABLE_ASH_ECHO + \
9782         0)
9783 #define EXECCMD (EVALCMD + \
9784         /* eval */      1)
9785
9786 /*
9787  * Search the table of builtin commands.
9788  */
9789 static int
9790 pstrcmp1(const void *a, const void *b)
9791 {
9792         return strcmp((char*)a, *(char**)b + 1);
9793 }
9794 static struct builtincmd *
9795 find_builtin(const char *name)
9796 {
9797         struct builtincmd *bp;
9798
9799         bp = bsearch(
9800                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9801                 pstrcmp1
9802         );
9803         return bp;
9804 }
9805
9806 /*
9807  * Execute a simple command.
9808  */
9809 static int
9810 isassignment(const char *p)
9811 {
9812         const char *q = endofname(p);
9813         if (p == q)
9814                 return 0;
9815         return *q == '=';
9816 }
9817 static int FAST_FUNC
9818 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9819 {
9820         /* Preserve exitstatus of a previous possible redirection
9821          * as POSIX mandates */
9822         return back_exitstatus;
9823 }
9824 static int
9825 evalcommand(union node *cmd, int flags)
9826 {
9827         static const struct builtincmd null_bltin = {
9828                 "\0\0", bltincmd /* why three NULs? */
9829         };
9830         struct localvar_list *localvar_stop;
9831         struct redirtab *redir_stop;
9832         struct stackmark smark;
9833         union node *argp;
9834         struct arglist arglist;
9835         struct arglist varlist;
9836         char **argv;
9837         int argc;
9838         const struct strlist *sp;
9839         struct cmdentry cmdentry;
9840         struct job *jp;
9841         char *lastarg;
9842         const char *path;
9843         int spclbltin;
9844         int status;
9845         char **nargv;
9846         smallint cmd_is_exec;
9847
9848         /* First expand the arguments. */
9849         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9850         setstackmark(&smark);
9851         localvar_stop = pushlocalvars();
9852         back_exitstatus = 0;
9853
9854         cmdentry.cmdtype = CMDBUILTIN;
9855         cmdentry.u.cmd = &null_bltin;
9856         varlist.lastp = &varlist.list;
9857         *varlist.lastp = NULL;
9858         arglist.lastp = &arglist.list;
9859         *arglist.lastp = NULL;
9860
9861         argc = 0;
9862         if (cmd->ncmd.args) {
9863                 struct builtincmd *bcmd;
9864                 smallint pseudovarflag;
9865
9866                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9867                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9868
9869                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9870                         struct strlist **spp;
9871
9872                         spp = arglist.lastp;
9873                         if (pseudovarflag && isassignment(argp->narg.text))
9874                                 expandarg(argp, &arglist, EXP_VARTILDE);
9875                         else
9876                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9877
9878                         for (sp = *spp; sp; sp = sp->next)
9879                                 argc++;
9880                 }
9881         }
9882
9883         /* Reserve one extra spot at the front for shellexec. */
9884         nargv = stalloc(sizeof(char *) * (argc + 2));
9885         argv = ++nargv;
9886         for (sp = arglist.list; sp; sp = sp->next) {
9887                 TRACE(("evalcommand arg: %s\n", sp->text));
9888                 *nargv++ = sp->text;
9889         }
9890         *nargv = NULL;
9891
9892         lastarg = NULL;
9893         if (iflag && funcnest == 0 && argc > 0)
9894                 lastarg = nargv[-1];
9895
9896         expredir(cmd->ncmd.redirect);
9897         redir_stop = pushredir(cmd->ncmd.redirect);
9898         preverrout_fd = 2;
9899         if (BASH_XTRACEFD && xflag) {
9900                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9901                  * we do not emulate this. We only use its value.
9902                  */
9903                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9904                 if (xtracefd && is_number(xtracefd))
9905                         preverrout_fd = atoi(xtracefd);
9906
9907         }
9908         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9909
9910         path = vpath.var_text;
9911         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9912                 struct strlist **spp;
9913                 char *p;
9914
9915                 spp = varlist.lastp;
9916                 expandarg(argp, &varlist, EXP_VARTILDE);
9917
9918                 mklocal((*spp)->text);
9919
9920                 /*
9921                  * Modify the command lookup path, if a PATH= assignment
9922                  * is present
9923                  */
9924                 p = (*spp)->text;
9925                 if (varcmp(p, path) == 0)
9926                         path = p;
9927         }
9928
9929         /* Print the command if xflag is set. */
9930         if (xflag) {
9931                 const char *pfx = "";
9932
9933                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9934
9935                 sp = varlist.list;
9936                 while (sp) {
9937                         char *varval = sp->text;
9938                         char *eq = strchrnul(varval, '=');
9939                         if (*eq)
9940                                 eq++;
9941                         fdprintf(preverrout_fd, "%s%.*s%s",
9942                                 pfx,
9943                                 (int)(eq - varval), varval,
9944                                 maybe_single_quote(eq)
9945                         );
9946                         sp = sp->next;
9947                         pfx = " ";
9948                 }
9949
9950                 sp = arglist.list;
9951                 while (sp) {
9952                         fdprintf(preverrout_fd, "%s%s",
9953                                 pfx,
9954                                 /* always quote if matches reserved word: */
9955                                 findkwd(sp->text)
9956                                 ? single_quote(sp->text)
9957                                 : maybe_single_quote(sp->text)
9958                         );
9959                         sp = sp->next;
9960                         pfx = " ";
9961                 }
9962                 safe_write(preverrout_fd, "\n", 1);
9963         }
9964
9965         cmd_is_exec = 0;
9966         spclbltin = -1;
9967
9968         /* Now locate the command. */
9969         if (argc) {
9970                 int cmd_flag = DO_ERR;
9971 #if ENABLE_ASH_CMDCMD
9972                 const char *oldpath = path + 5;
9973 #endif
9974                 path += 5;
9975                 for (;;) {
9976                         find_command(argv[0], &cmdentry, cmd_flag, path);
9977                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9978                                 flush_stdout_stderr();
9979                                 status = 127;
9980                                 goto bail;
9981                         }
9982
9983                         /* implement bltin and command here */
9984                         if (cmdentry.cmdtype != CMDBUILTIN)
9985                                 break;
9986                         if (spclbltin < 0)
9987                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9988                         if (cmdentry.u.cmd == EXECCMD)
9989                                 cmd_is_exec = 1;
9990 #if ENABLE_ASH_CMDCMD
9991                         if (cmdentry.u.cmd == COMMANDCMD) {
9992                                 path = oldpath;
9993                                 nargv = parse_command_args(argv, &path);
9994                                 if (!nargv)
9995                                         break;
9996                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9997                                  * nargv => "PROG". path is updated if -p.
9998                                  */
9999                                 argc -= nargv - argv;
10000                                 argv = nargv;
10001                                 cmd_flag |= DO_NOFUNC;
10002                         } else
10003 #endif
10004                                 break;
10005                 }
10006         }
10007
10008         if (status) {
10009  bail:
10010                 exitstatus = status;
10011
10012                 /* We have a redirection error. */
10013                 if (spclbltin > 0)
10014                         raise_exception(EXERROR);
10015
10016                 goto out;
10017         }
10018
10019         /* Execute the command. */
10020         switch (cmdentry.cmdtype) {
10021         default: {
10022
10023 #if ENABLE_FEATURE_SH_STANDALONE \
10024  && ENABLE_FEATURE_SH_NOFORK \
10025  && NUM_APPLETS > 1
10026 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10027  *     around run_nofork_applet() call.
10028  * (2) Should this check also be done in forkshell()?
10029  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10030  */
10031                 /* find_command() encodes applet_no as (-2 - applet_no) */
10032                 int applet_no = (- cmdentry.u.index - 2);
10033                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10034                         char **sv_environ;
10035
10036                         INT_OFF;
10037                         sv_environ = environ;
10038                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10039                         /*
10040                          * Run <applet>_main().
10041                          * Signals (^C) can't interrupt here.
10042                          * Otherwise we can mangle stdio or malloc internal state.
10043                          * This makes applets which can run for a long time
10044                          * and/or wait for user input ineligible for NOFORK:
10045                          * for example, "yes" or "rm" (rm -i waits for input).
10046                          */
10047                         status = run_nofork_applet(applet_no, argv);
10048                         environ = sv_environ;
10049                         /*
10050                          * Try enabling NOFORK for "yes" applet.
10051                          * ^C _will_ stop it (write returns EINTR),
10052                          * but this causes stdout FILE to be stuck
10053                          * and needing clearerr(). What if other applets
10054                          * also can get EINTRs? Do we need to switch
10055                          * our signals to SA_RESTART?
10056                          */
10057                         /*clearerr(stdout);*/
10058                         INT_ON;
10059                         break;
10060                 }
10061 #endif
10062                 /* Can we avoid forking? For example, very last command
10063                  * in a script or a subshell does not need forking,
10064                  * we can just exec it.
10065                  */
10066                 if (!(flags & EV_EXIT) || may_have_traps) {
10067                         /* No, forking off a child is necessary */
10068                         INT_OFF;
10069                         get_tty_state();
10070                         jp = makejob(/*cmd,*/ 1);
10071                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10072                                 /* parent */
10073                                 status = waitforjob(jp);
10074                                 INT_ON;
10075                                 TRACE(("forked child exited with %d\n", status));
10076                                 break;
10077                         }
10078                         /* child */
10079                         FORCE_INT_ON;
10080                         /* fall through to exec'ing external program */
10081                 }
10082                 listsetvar(varlist.list, VEXPORT|VSTACK);
10083                 shellexec(argv[0], argv, path, cmdentry.u.index);
10084                 /* NOTREACHED */
10085         } /* default */
10086         case CMDBUILTIN:
10087                 if (spclbltin > 0 || argc == 0) {
10088                         poplocalvars(1);
10089                         if (cmd_is_exec && argc > 1)
10090                                 listsetvar(varlist.list, VEXPORT);
10091                 }
10092
10093                 /* Tight loop with builtins only:
10094                  * "while kill -0 $child; do true; done"
10095                  * will never exit even if $child died, unless we do this
10096                  * to reap the zombie and make kill detect that it's gone: */
10097                 dowait(DOWAIT_NONBLOCK, NULL);
10098
10099                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10100                         if (exception_type == EXERROR && spclbltin <= 0) {
10101                                 FORCE_INT_ON;
10102                                 goto readstatus;
10103                         }
10104  raise:
10105                         longjmp(exception_handler->loc, 1);
10106                 }
10107                 goto readstatus;
10108
10109         case CMDFUNCTION:
10110                 poplocalvars(1);
10111                 /* See above for the rationale */
10112                 dowait(DOWAIT_NONBLOCK, NULL);
10113                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10114                         goto raise;
10115  readstatus:
10116                 status = exitstatus;
10117                 break;
10118         } /* switch */
10119
10120  out:
10121         if (cmd->ncmd.redirect)
10122                 popredir(/*drop:*/ cmd_is_exec);
10123         unwindredir(redir_stop);
10124         unwindlocalvars(localvar_stop);
10125         if (lastarg) {
10126                 /* dsl: I think this is intended to be used to support
10127                  * '_' in 'vi' command mode during line editing...
10128                  * However I implemented that within libedit itself.
10129                  */
10130                 setvar0("_", lastarg);
10131         }
10132         popstackmark(&smark);
10133
10134         return status;
10135 }
10136
10137 static int
10138 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10139 {
10140         char *volatile savecmdname;
10141         struct jmploc *volatile savehandler;
10142         struct jmploc jmploc;
10143         int status;
10144         int i;
10145
10146         savecmdname = commandname;
10147         savehandler = exception_handler;
10148         i = setjmp(jmploc.loc);
10149         if (i)
10150                 goto cmddone;
10151         exception_handler = &jmploc;
10152         commandname = argv[0];
10153         argptr = argv + 1;
10154         optptr = NULL;                  /* initialize nextopt */
10155         if (cmd == EVALCMD)
10156                 status = evalcmd(argc, argv, flags);
10157         else
10158                 status = (*cmd->builtin)(argc, argv);
10159         flush_stdout_stderr();
10160         status |= ferror(stdout);
10161         exitstatus = status;
10162  cmddone:
10163         clearerr(stdout);
10164         commandname = savecmdname;
10165         exception_handler = savehandler;
10166
10167         return i;
10168 }
10169
10170 static int
10171 goodname(const char *p)
10172 {
10173         return endofname(p)[0] == '\0';
10174 }
10175
10176
10177 /*
10178  * Search for a command.  This is called before we fork so that the
10179  * location of the command will be available in the parent as well as
10180  * the child.  The check for "goodname" is an overly conservative
10181  * check that the name will not be subject to expansion.
10182  */
10183 static void
10184 prehash(union node *n)
10185 {
10186         struct cmdentry entry;
10187
10188         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10189                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10190 }
10191
10192
10193 /* ============ Builtin commands
10194  *
10195  * Builtin commands whose functions are closely tied to evaluation
10196  * are implemented here.
10197  */
10198
10199 /*
10200  * Handle break and continue commands.  Break, continue, and return are
10201  * all handled by setting the evalskip flag.  The evaluation routines
10202  * above all check this flag, and if it is set they start skipping
10203  * commands rather than executing them.  The variable skipcount is
10204  * the number of loops to break/continue, or the number of function
10205  * levels to return.  (The latter is always 1.)  It should probably
10206  * be an error to break out of more loops than exist, but it isn't
10207  * in the standard shell so we don't make it one here.
10208  */
10209 static int FAST_FUNC
10210 breakcmd(int argc UNUSED_PARAM, char **argv)
10211 {
10212         int n = argv[1] ? number(argv[1]) : 1;
10213
10214         if (n <= 0)
10215                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10216         if (n > loopnest)
10217                 n = loopnest;
10218         if (n > 0) {
10219                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10220                 skipcount = n;
10221         }
10222         return 0;
10223 }
10224
10225
10226 /*
10227  * This implements the input routines used by the parser.
10228  */
10229
10230 enum {
10231         INPUT_PUSH_FILE = 1,
10232         INPUT_NOFILE_OK = 2,
10233 };
10234
10235 static smallint checkkwd;
10236 /* values of checkkwd variable */
10237 #define CHKALIAS        0x1
10238 #define CHKKWD          0x2
10239 #define CHKNL           0x4
10240 #define CHKEOFMARK      0x8
10241
10242 /*
10243  * Push a string back onto the input at this current parsefile level.
10244  * We handle aliases this way.
10245  */
10246 #if !ENABLE_ASH_ALIAS
10247 #define pushstring(s, ap) pushstring(s)
10248 #endif
10249 static void
10250 pushstring(char *s, struct alias *ap)
10251 {
10252         struct strpush *sp;
10253         int len;
10254
10255         len = strlen(s);
10256         INT_OFF;
10257         if (g_parsefile->strpush) {
10258                 sp = ckzalloc(sizeof(*sp));
10259                 sp->prev = g_parsefile->strpush;
10260         } else {
10261                 sp = &(g_parsefile->basestrpush);
10262         }
10263         g_parsefile->strpush = sp;
10264         sp->prev_string = g_parsefile->next_to_pgetc;
10265         sp->prev_left_in_line = g_parsefile->left_in_line;
10266         sp->unget = g_parsefile->unget;
10267         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10268 #if ENABLE_ASH_ALIAS
10269         sp->ap = ap;
10270         if (ap) {
10271                 ap->flag |= ALIASINUSE;
10272                 sp->string = s;
10273         }
10274 #endif
10275         g_parsefile->next_to_pgetc = s;
10276         g_parsefile->left_in_line = len;
10277         g_parsefile->unget = 0;
10278         INT_ON;
10279 }
10280
10281 static void
10282 popstring(void)
10283 {
10284         struct strpush *sp = g_parsefile->strpush;
10285
10286         INT_OFF;
10287 #if ENABLE_ASH_ALIAS
10288         if (sp->ap) {
10289                 if (g_parsefile->next_to_pgetc[-1] == ' '
10290                  || g_parsefile->next_to_pgetc[-1] == '\t'
10291                 ) {
10292                         checkkwd |= CHKALIAS;
10293                 }
10294                 if (sp->string != sp->ap->val) {
10295                         free(sp->string);
10296                 }
10297                 sp->ap->flag &= ~ALIASINUSE;
10298                 if (sp->ap->flag & ALIASDEAD) {
10299                         unalias(sp->ap->name);
10300                 }
10301         }
10302 #endif
10303         g_parsefile->next_to_pgetc = sp->prev_string;
10304         g_parsefile->left_in_line = sp->prev_left_in_line;
10305         g_parsefile->unget = sp->unget;
10306         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10307         g_parsefile->strpush = sp->prev;
10308         if (sp != &(g_parsefile->basestrpush))
10309                 free(sp);
10310         INT_ON;
10311 }
10312
10313 static int
10314 preadfd(void)
10315 {
10316         int nr;
10317         char *buf = g_parsefile->buf;
10318
10319         g_parsefile->next_to_pgetc = buf;
10320 #if ENABLE_FEATURE_EDITING
10321  retry:
10322         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10323                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10324         else {
10325 # if ENABLE_ASH_IDLE_TIMEOUT
10326                 int timeout = -1;
10327                 if (iflag) {
10328                         const char *tmout_var = lookupvar("TMOUT");
10329                         if (tmout_var) {
10330                                 timeout = atoi(tmout_var) * 1000;
10331                                 if (timeout <= 0)
10332                                         timeout = -1;
10333                         }
10334                 }
10335                 line_input_state->timeout = timeout;
10336 # endif
10337 # if ENABLE_FEATURE_TAB_COMPLETION
10338                 line_input_state->path_lookup = pathval();
10339 # endif
10340                 reinit_unicode_for_ash();
10341                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10342                 if (nr == 0) {
10343                         /* ^C pressed, "convert" to SIGINT */
10344                         write(STDOUT_FILENO, "^C", 2);
10345                         if (trap[SIGINT]) {
10346                                 buf[0] = '\n';
10347                                 buf[1] = '\0';
10348                                 raise(SIGINT);
10349                                 return 1;
10350                         }
10351                         exitstatus = 128 + SIGINT;
10352                         bb_putchar('\n');
10353                         goto retry;
10354                 }
10355                 if (nr < 0) {
10356                         if (errno == 0) {
10357                                 /* Ctrl+D pressed */
10358                                 nr = 0;
10359                         }
10360 # if ENABLE_ASH_IDLE_TIMEOUT
10361                         else if (errno == EAGAIN && timeout > 0) {
10362                                 puts("\007timed out waiting for input: auto-logout");
10363                                 exitshell();
10364                         }
10365 # endif
10366                 }
10367         }
10368 #else
10369         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10370 #endif
10371
10372 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10373         if (nr < 0) {
10374                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10375                         int flags = fcntl(0, F_GETFL);
10376                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10377                                 flags &= ~O_NONBLOCK;
10378                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10379                                         out2str("sh: turning off NDELAY mode\n");
10380                                         goto retry;
10381                                 }
10382                         }
10383                 }
10384         }
10385 #endif
10386         return nr;
10387 }
10388
10389 /*
10390  * Refill the input buffer and return the next input character:
10391  *
10392  * 1) If a string was pushed back on the input, pop it;
10393  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10394  *    or we are reading from a string so we can't refill the buffer,
10395  *    return EOF.
10396  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10397  * 4) Process input up to the next newline, deleting nul characters.
10398  */
10399 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10400 #define pgetc_debug(...) ((void)0)
10401 static int pgetc(void);
10402 static int
10403 preadbuffer(void)
10404 {
10405         char *q;
10406         int more;
10407
10408         if (g_parsefile->strpush) {
10409 #if ENABLE_ASH_ALIAS
10410                 if (g_parsefile->left_in_line == -1
10411                  && g_parsefile->strpush->ap
10412                  && g_parsefile->next_to_pgetc[-1] != ' '
10413                  && g_parsefile->next_to_pgetc[-1] != '\t'
10414                 ) {
10415                         pgetc_debug("preadbuffer PEOA");
10416                         return PEOA;
10417                 }
10418 #endif
10419                 popstring();
10420                 return pgetc();
10421         }
10422         /* on both branches above g_parsefile->left_in_line < 0.
10423          * "pgetc" needs refilling.
10424          */
10425
10426         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10427          * pungetc() may increment it a few times.
10428          * Assuming it won't increment it to less than -90.
10429          */
10430         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10431                 pgetc_debug("preadbuffer PEOF1");
10432                 /* even in failure keep left_in_line and next_to_pgetc
10433                  * in lock step, for correct multi-layer pungetc.
10434                  * left_in_line was decremented before preadbuffer(),
10435                  * must inc next_to_pgetc: */
10436                 g_parsefile->next_to_pgetc++;
10437                 return PEOF;
10438         }
10439
10440         more = g_parsefile->left_in_buffer;
10441         if (more <= 0) {
10442                 flush_stdout_stderr();
10443  again:
10444                 more = preadfd();
10445                 if (more <= 0) {
10446                         /* don't try reading again */
10447                         g_parsefile->left_in_line = -99;
10448                         pgetc_debug("preadbuffer PEOF2");
10449                         g_parsefile->next_to_pgetc++;
10450                         return PEOF;
10451                 }
10452         }
10453
10454         /* Find out where's the end of line.
10455          * Set g_parsefile->left_in_line
10456          * and g_parsefile->left_in_buffer acordingly.
10457          * NUL chars are deleted.
10458          */
10459         q = g_parsefile->next_to_pgetc;
10460         for (;;) {
10461                 char c;
10462
10463                 more--;
10464
10465                 c = *q;
10466                 if (c == '\0') {
10467                         memmove(q, q + 1, more);
10468                 } else {
10469                         q++;
10470                         if (c == '\n') {
10471                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10472                                 break;
10473                         }
10474                 }
10475
10476                 if (more <= 0) {
10477                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10478                         if (g_parsefile->left_in_line < 0)
10479                                 goto again;
10480                         break;
10481                 }
10482         }
10483         g_parsefile->left_in_buffer = more;
10484
10485         if (vflag) {
10486                 char save = *q;
10487                 *q = '\0';
10488                 out2str(g_parsefile->next_to_pgetc);
10489                 *q = save;
10490         }
10491
10492         pgetc_debug("preadbuffer at %d:%p'%s'",
10493                         g_parsefile->left_in_line,
10494                         g_parsefile->next_to_pgetc,
10495                         g_parsefile->next_to_pgetc);
10496         return (unsigned char)*g_parsefile->next_to_pgetc++;
10497 }
10498
10499 static void
10500 nlprompt(void)
10501 {
10502         g_parsefile->linno++;
10503         setprompt_if(doprompt, 2);
10504 }
10505 static void
10506 nlnoprompt(void)
10507 {
10508         g_parsefile->linno++;
10509         needprompt = doprompt;
10510 }
10511
10512 static int
10513 pgetc(void)
10514 {
10515         int c;
10516
10517         pgetc_debug("pgetc at %d:%p'%s'",
10518                         g_parsefile->left_in_line,
10519                         g_parsefile->next_to_pgetc,
10520                         g_parsefile->next_to_pgetc);
10521         if (g_parsefile->unget)
10522                 return g_parsefile->lastc[--g_parsefile->unget];
10523
10524         if (--g_parsefile->left_in_line >= 0)
10525                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10526         else
10527                 c = preadbuffer();
10528
10529         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10530         g_parsefile->lastc[0] = c;
10531
10532         return c;
10533 }
10534
10535 #if ENABLE_ASH_ALIAS
10536 static int
10537 pgetc_without_PEOA(void)
10538 {
10539         int c;
10540         do {
10541                 pgetc_debug("pgetc at %d:%p'%s'",
10542                                 g_parsefile->left_in_line,
10543                                 g_parsefile->next_to_pgetc,
10544                                 g_parsefile->next_to_pgetc);
10545                 c = pgetc();
10546         } while (c == PEOA);
10547         return c;
10548 }
10549 #else
10550 # define pgetc_without_PEOA() pgetc()
10551 #endif
10552
10553 /*
10554  * Undo a call to pgetc.  Only two characters may be pushed back.
10555  * PEOF may be pushed back.
10556  */
10557 static void
10558 pungetc(void)
10559 {
10560         g_parsefile->unget++;
10561 }
10562
10563 /* This one eats backslash+newline */
10564 static int
10565 pgetc_eatbnl(void)
10566 {
10567         int c;
10568
10569         while ((c = pgetc()) == '\\') {
10570                 if (pgetc() != '\n') {
10571                         pungetc();
10572                         break;
10573                 }
10574
10575                 nlprompt();
10576         }
10577
10578         return c;
10579 }
10580
10581 /*
10582  * To handle the "." command, a stack of input files is used.  Pushfile
10583  * adds a new entry to the stack and popfile restores the previous level.
10584  */
10585 static void
10586 pushfile(void)
10587 {
10588         struct parsefile *pf;
10589
10590         pf = ckzalloc(sizeof(*pf));
10591         pf->prev = g_parsefile;
10592         pf->pf_fd = -1;
10593         /*pf->strpush = NULL; - ckzalloc did it */
10594         /*pf->basestrpush.prev = NULL;*/
10595         /*pf->unget = 0;*/
10596         g_parsefile = pf;
10597 }
10598
10599 static void
10600 popfile(void)
10601 {
10602         struct parsefile *pf = g_parsefile;
10603
10604         if (pf == &basepf)
10605                 return;
10606
10607         INT_OFF;
10608         if (pf->pf_fd >= 0)
10609                 close(pf->pf_fd);
10610         free(pf->buf);
10611         while (pf->strpush)
10612                 popstring();
10613         g_parsefile = pf->prev;
10614         free(pf);
10615         INT_ON;
10616 }
10617
10618 /*
10619  * Return to top level.
10620  */
10621 static void
10622 popallfiles(void)
10623 {
10624         while (g_parsefile != &basepf)
10625                 popfile();
10626 }
10627
10628 /*
10629  * Close the file(s) that the shell is reading commands from.  Called
10630  * after a fork is done.
10631  */
10632 static void
10633 closescript(void)
10634 {
10635         popallfiles();
10636         if (g_parsefile->pf_fd > 0) {
10637                 close(g_parsefile->pf_fd);
10638                 g_parsefile->pf_fd = 0;
10639         }
10640 }
10641
10642 /*
10643  * Like setinputfile, but takes an open file descriptor.  Call this with
10644  * interrupts off.
10645  */
10646 static void
10647 setinputfd(int fd, int push)
10648 {
10649         if (push) {
10650                 pushfile();
10651                 g_parsefile->buf = NULL;
10652         }
10653         g_parsefile->pf_fd = fd;
10654         if (g_parsefile->buf == NULL)
10655                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10656         g_parsefile->left_in_buffer = 0;
10657         g_parsefile->left_in_line = 0;
10658         g_parsefile->linno = 1;
10659 }
10660
10661 /*
10662  * Set the input to take input from a file.  If push is set, push the
10663  * old input onto the stack first.
10664  */
10665 static int
10666 setinputfile(const char *fname, int flags)
10667 {
10668         int fd;
10669
10670         INT_OFF;
10671         fd = open(fname, O_RDONLY);
10672         if (fd < 0) {
10673                 if (flags & INPUT_NOFILE_OK)
10674                         goto out;
10675                 exitstatus = 127;
10676                 ash_msg_and_raise_perror("can't open '%s'", fname);
10677         }
10678         if (fd < 10)
10679                 fd = savefd(fd);
10680         else
10681                 close_on_exec_on(fd);
10682         setinputfd(fd, flags & INPUT_PUSH_FILE);
10683  out:
10684         INT_ON;
10685         return fd;
10686 }
10687
10688 /*
10689  * Like setinputfile, but takes input from a string.
10690  */
10691 static void
10692 setinputstring(char *string)
10693 {
10694         INT_OFF;
10695         pushfile();
10696         g_parsefile->next_to_pgetc = string;
10697         g_parsefile->left_in_line = strlen(string);
10698         g_parsefile->buf = NULL;
10699         g_parsefile->linno = 1;
10700         INT_ON;
10701 }
10702
10703
10704 /*
10705  * Routines to check for mail.
10706  */
10707
10708 #if ENABLE_ASH_MAIL
10709
10710 /* Hash of mtimes of mailboxes */
10711 static unsigned mailtime_hash;
10712 /* Set if MAIL or MAILPATH is changed. */
10713 static smallint mail_var_path_changed;
10714
10715 /*
10716  * Print appropriate message(s) if mail has arrived.
10717  * If mail_var_path_changed is set,
10718  * then the value of MAIL has mail_var_path_changed,
10719  * so we just update the values.
10720  */
10721 static void
10722 chkmail(void)
10723 {
10724         const char *mpath;
10725         char *p;
10726         char *q;
10727         unsigned new_hash;
10728         struct stackmark smark;
10729         struct stat statb;
10730
10731         setstackmark(&smark);
10732         mpath = mpathset() ? mpathval() : mailval();
10733         new_hash = 0;
10734         for (;;) {
10735                 p = path_advance(&mpath, nullstr);
10736                 if (p == NULL)
10737                         break;
10738                 if (*p == '\0')
10739                         continue;
10740                 for (q = p; *q; q++)
10741                         continue;
10742 #if DEBUG
10743                 if (q[-1] != '/')
10744                         abort();
10745 #endif
10746                 q[-1] = '\0';                   /* delete trailing '/' */
10747                 if (stat(p, &statb) < 0) {
10748                         continue;
10749                 }
10750                 /* Very simplistic "hash": just a sum of all mtimes */
10751                 new_hash += (unsigned)statb.st_mtime;
10752         }
10753         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10754                 if (mailtime_hash != 0)
10755                         out2str("you have mail\n");
10756                 mailtime_hash = new_hash;
10757         }
10758         mail_var_path_changed = 0;
10759         popstackmark(&smark);
10760 }
10761
10762 static void FAST_FUNC
10763 changemail(const char *val UNUSED_PARAM)
10764 {
10765         mail_var_path_changed = 1;
10766 }
10767
10768 #endif /* ASH_MAIL */
10769
10770
10771 /* ============ ??? */
10772
10773 /*
10774  * Set the shell parameters.
10775  */
10776 static void
10777 setparam(char **argv)
10778 {
10779         char **newparam;
10780         char **ap;
10781         int nparam;
10782
10783         for (nparam = 0; argv[nparam]; nparam++)
10784                 continue;
10785         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10786         while (*argv) {
10787                 *ap++ = ckstrdup(*argv++);
10788         }
10789         *ap = NULL;
10790         freeparam(&shellparam);
10791         shellparam.malloced = 1;
10792         shellparam.nparam = nparam;
10793         shellparam.p = newparam;
10794 #if ENABLE_ASH_GETOPTS
10795         shellparam.optind = 1;
10796         shellparam.optoff = -1;
10797 #endif
10798 }
10799
10800 /*
10801  * Process shell options.  The global variable argptr contains a pointer
10802  * to the argument list; we advance it past the options.
10803  *
10804  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10805  * For a non-interactive shell, an error condition encountered
10806  * by a special built-in ... shall cause the shell to write a diagnostic message
10807  * to standard error and exit as shown in the following table:
10808  * Error                                           Special Built-In
10809  * ...
10810  * Utility syntax error (option or operand error)  Shall exit
10811  * ...
10812  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10813  * we see that bash does not do that (set "finishes" with error code 1 instead,
10814  * and shell continues), and people rely on this behavior!
10815  * Testcase:
10816  * set -o barfoo 2>/dev/null
10817  * echo $?
10818  *
10819  * Oh well. Let's mimic that.
10820  */
10821 static int
10822 plus_minus_o(char *name, int val)
10823 {
10824         int i;
10825
10826         if (name) {
10827                 for (i = 0; i < NOPTS; i++) {
10828                         if (strcmp(name, optnames(i)) == 0) {
10829                                 optlist[i] = val;
10830                                 return 0;
10831                         }
10832                 }
10833                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10834                 return 1;
10835         }
10836         for (i = 0; i < NOPTS; i++) {
10837                 if (val) {
10838                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10839                 } else {
10840                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10841                 }
10842         }
10843         return 0;
10844 }
10845 static void
10846 setoption(int flag, int val)
10847 {
10848         int i;
10849
10850         for (i = 0; i < NOPTS; i++) {
10851                 if (optletters(i) == flag) {
10852                         optlist[i] = val;
10853                         return;
10854                 }
10855         }
10856         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10857         /* NOTREACHED */
10858 }
10859 static int
10860 options(int cmdline, int *login_sh)
10861 {
10862         char *p;
10863         int val;
10864         int c;
10865
10866         if (cmdline)
10867                 minusc = NULL;
10868         while ((p = *argptr) != NULL) {
10869                 c = *p++;
10870                 if (c != '-' && c != '+')
10871                         break;
10872                 argptr++;
10873                 val = 0; /* val = 0 if c == '+' */
10874                 if (c == '-') {
10875                         val = 1;
10876                         if (p[0] == '\0' || LONE_DASH(p)) {
10877                                 if (!cmdline) {
10878                                         /* "-" means turn off -x and -v */
10879                                         if (p[0] == '\0')
10880                                                 xflag = vflag = 0;
10881                                         /* "--" means reset params */
10882                                         else if (*argptr == NULL)
10883                                                 setparam(argptr);
10884                                 }
10885                                 break;    /* "-" or "--" terminates options */
10886                         }
10887                 }
10888                 /* first char was + or - */
10889                 while ((c = *p++) != '\0') {
10890                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10891                         if (c == 'c' && cmdline) {
10892                                 minusc = p;     /* command is after shell args */
10893                         } else if (c == 'o') {
10894                                 if (plus_minus_o(*argptr, val)) {
10895                                         /* it already printed err message */
10896                                         return 1; /* error */
10897                                 }
10898                                 if (*argptr)
10899                                         argptr++;
10900                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10901                                 if (login_sh)
10902                                         *login_sh = 1;
10903                         /* bash does not accept +-login, we also won't */
10904                         } else if (cmdline && val && (c == '-')) { /* long options */
10905                                 if (strcmp(p, "login") == 0) {
10906                                         if (login_sh)
10907                                                 *login_sh = 1;
10908                                 }
10909                                 break;
10910                         } else {
10911                                 setoption(c, val);
10912                         }
10913                 }
10914         }
10915         return 0;
10916 }
10917
10918 /*
10919  * The shift builtin command.
10920  */
10921 static int FAST_FUNC
10922 shiftcmd(int argc UNUSED_PARAM, char **argv)
10923 {
10924         int n;
10925         char **ap1, **ap2;
10926
10927         n = 1;
10928         if (argv[1])
10929                 n = number(argv[1]);
10930         if (n > shellparam.nparam)
10931                 return 1;
10932         INT_OFF;
10933         shellparam.nparam -= n;
10934         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10935                 if (shellparam.malloced)
10936                         free(*ap1);
10937         }
10938         ap2 = shellparam.p;
10939         while ((*ap2++ = *ap1++) != NULL)
10940                 continue;
10941 #if ENABLE_ASH_GETOPTS
10942         shellparam.optind = 1;
10943         shellparam.optoff = -1;
10944 #endif
10945         INT_ON;
10946         return 0;
10947 }
10948
10949 /*
10950  * POSIX requires that 'set' (but not export or readonly) output the
10951  * variables in lexicographic order - by the locale's collating order (sigh).
10952  * Maybe we could keep them in an ordered balanced binary tree
10953  * instead of hashed lists.
10954  * For now just roll 'em through qsort for printing...
10955  */
10956 static int
10957 showvars(const char *sep_prefix, int on, int off)
10958 {
10959         const char *sep;
10960         char **ep, **epend;
10961
10962         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
10963         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10964
10965         sep = *sep_prefix ? " " : sep_prefix;
10966
10967         for (; ep < epend; ep++) {
10968                 const char *p;
10969                 const char *q;
10970
10971                 p = endofname(*ep);
10972 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
10973  * makes "export -p" to have output not suitable for "eval":
10974  * import os
10975  * os.environ["test-test"]="test"
10976  * if os.fork() == 0:
10977  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
10978  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
10979  */
10980                 q = nullstr;
10981                 if (*p == '=')
10982                         q = single_quote(++p);
10983                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10984         }
10985         return 0;
10986 }
10987
10988 /*
10989  * The set command builtin.
10990  */
10991 static int FAST_FUNC
10992 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10993 {
10994         int retval;
10995
10996         if (!argv[1])
10997                 return showvars(nullstr, 0, VUNSET);
10998
10999         INT_OFF;
11000         retval = options(/*cmdline:*/ 0, NULL);
11001         if (retval == 0) { /* if no parse error... */
11002                 optschanged();
11003                 if (*argptr != NULL) {
11004                         setparam(argptr);
11005                 }
11006         }
11007         INT_ON;
11008         return retval;
11009 }
11010
11011 #if ENABLE_ASH_RANDOM_SUPPORT
11012 static void FAST_FUNC
11013 change_random(const char *value)
11014 {
11015         uint32_t t;
11016
11017         if (value == NULL) {
11018                 /* "get", generate */
11019                 t = next_random(&random_gen);
11020                 /* set without recursion */
11021                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11022                 vrandom.flags &= ~VNOFUNC;
11023         } else {
11024                 /* set/reset */
11025                 t = strtoul(value, NULL, 10);
11026                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11027         }
11028 }
11029 #endif
11030
11031 #if ENABLE_ASH_GETOPTS
11032 static int
11033 getopts(char *optstr, char *optvar, char **optfirst)
11034 {
11035         char *p, *q;
11036         char c = '?';
11037         int done = 0;
11038         char sbuf[2];
11039         char **optnext;
11040         int ind = shellparam.optind;
11041         int off = shellparam.optoff;
11042
11043         sbuf[1] = '\0';
11044
11045         shellparam.optind = -1;
11046         optnext = optfirst + ind - 1;
11047
11048         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11049                 p = NULL;
11050         else
11051                 p = optnext[-1] + off;
11052         if (p == NULL || *p == '\0') {
11053                 /* Current word is done, advance */
11054                 p = *optnext;
11055                 if (p == NULL || *p != '-' || *++p == '\0') {
11056  atend:
11057                         unsetvar("OPTARG");
11058                         p = NULL;
11059                         done = 1;
11060                         goto out;
11061                 }
11062                 optnext++;
11063                 if (LONE_DASH(p))        /* check for "--" */
11064                         goto atend;
11065         }
11066
11067         c = *p++;
11068         for (q = optstr; *q != c;) {
11069                 if (*q == '\0') {
11070                         /* OPTERR is a bashism */
11071                         const char *cp = lookupvar("OPTERR");
11072                         if ((cp && LONE_CHAR(cp, '0'))
11073                          || (optstr[0] == ':')
11074                         ) {
11075                                 sbuf[0] = c;
11076                                 /*sbuf[1] = '\0'; - already is */
11077                                 setvar0("OPTARG", sbuf);
11078                         } else {
11079                                 fprintf(stderr, "Illegal option -%c\n", c);
11080                                 unsetvar("OPTARG");
11081                         }
11082                         c = '?';
11083                         goto out;
11084                 }
11085                 if (*++q == ':')
11086                         q++;
11087         }
11088
11089         if (*++q == ':') {
11090                 if (*p == '\0' && (p = *optnext) == NULL) {
11091                         /* OPTERR is a bashism */
11092                         const char *cp = lookupvar("OPTERR");
11093                         if ((cp && LONE_CHAR(cp, '0'))
11094                          || (optstr[0] == ':')
11095                         ) {
11096                                 sbuf[0] = c;
11097                                 /*sbuf[1] = '\0'; - already is */
11098                                 setvar0("OPTARG", sbuf);
11099                                 c = ':';
11100                         } else {
11101                                 fprintf(stderr, "No arg for -%c option\n", c);
11102                                 unsetvar("OPTARG");
11103                                 c = '?';
11104                         }
11105                         goto out;
11106                 }
11107
11108                 if (p == *optnext)
11109                         optnext++;
11110                 setvar0("OPTARG", p);
11111                 p = NULL;
11112         } else
11113                 setvar0("OPTARG", nullstr);
11114  out:
11115         ind = optnext - optfirst + 1;
11116         setvar("OPTIND", itoa(ind), VNOFUNC);
11117         sbuf[0] = c;
11118         /*sbuf[1] = '\0'; - already is */
11119         setvar0(optvar, sbuf);
11120
11121         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11122         shellparam.optind = ind;
11123
11124         return done;
11125 }
11126
11127 /*
11128  * The getopts builtin.  Shellparam.optnext points to the next argument
11129  * to be processed.  Shellparam.optptr points to the next character to
11130  * be processed in the current argument.  If shellparam.optnext is NULL,
11131  * then it's the first time getopts has been called.
11132  */
11133 static int FAST_FUNC
11134 getoptscmd(int argc, char **argv)
11135 {
11136         char **optbase;
11137
11138         if (argc < 3)
11139                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11140         if (argc == 3) {
11141                 optbase = shellparam.p;
11142                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11143                         shellparam.optind = 1;
11144                         shellparam.optoff = -1;
11145                 }
11146         } else {
11147                 optbase = &argv[3];
11148                 if ((unsigned)shellparam.optind > argc - 2) {
11149                         shellparam.optind = 1;
11150                         shellparam.optoff = -1;
11151                 }
11152         }
11153
11154         return getopts(argv[1], argv[2], optbase);
11155 }
11156 #endif /* ASH_GETOPTS */
11157
11158
11159 /* ============ Shell parser */
11160
11161 struct heredoc {
11162         struct heredoc *next;   /* next here document in list */
11163         union node *here;       /* redirection node */
11164         char *eofmark;          /* string indicating end of input */
11165         smallint striptabs;     /* if set, strip leading tabs */
11166 };
11167
11168 static smallint tokpushback;           /* last token pushed back */
11169 static smallint quoteflag;             /* set if (part of) last token was quoted */
11170 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11171 static struct heredoc *heredoclist;    /* list of here documents to read */
11172 static char *wordtext;                 /* text of last word returned by readtoken */
11173 static struct nodelist *backquotelist;
11174 static union node *redirnode;
11175 static struct heredoc *heredoc;
11176
11177 static const char *
11178 tokname(char *buf, int tok)
11179 {
11180         if (tok < TSEMI)
11181                 return tokname_array[tok];
11182         sprintf(buf, "\"%s\"", tokname_array[tok]);
11183         return buf;
11184 }
11185
11186 /* raise_error_unexpected_syntax:
11187  * Called when an unexpected token is read during the parse.  The argument
11188  * is the token that is expected, or -1 if more than one type of token can
11189  * occur at this point.
11190  */
11191 static void raise_error_unexpected_syntax(int) NORETURN;
11192 static void
11193 raise_error_unexpected_syntax(int token)
11194 {
11195         char msg[64];
11196         char buf[16];
11197         int l;
11198
11199         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11200         if (token >= 0)
11201                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11202         raise_error_syntax(msg);
11203         /* NOTREACHED */
11204 }
11205
11206 /* parsing is heavily cross-recursive, need these forward decls */
11207 static union node *andor(void);
11208 static union node *pipeline(void);
11209 static union node *parse_command(void);
11210 static void parseheredoc(void);
11211 static int peektoken(void);
11212 static int readtoken(void);
11213
11214 static union node *
11215 list(int nlflag)
11216 {
11217         union node *n1, *n2, *n3;
11218         int tok;
11219
11220         n1 = NULL;
11221         for (;;) {
11222                 switch (peektoken()) {
11223                 case TNL:
11224                         if (!(nlflag & 1))
11225                                 break;
11226                         parseheredoc();
11227                         return n1;
11228
11229                 case TEOF:
11230                         if (!n1 && (nlflag & 1))
11231                                 n1 = NODE_EOF;
11232                         parseheredoc();
11233                         return n1;
11234                 }
11235
11236                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11237                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11238                         return n1;
11239                 nlflag |= 2;
11240
11241                 n2 = andor();
11242                 tok = readtoken();
11243                 if (tok == TBACKGND) {
11244                         if (n2->type == NPIPE) {
11245                                 n2->npipe.pipe_backgnd = 1;
11246                         } else {
11247                                 if (n2->type != NREDIR) {
11248                                         n3 = stzalloc(sizeof(struct nredir));
11249                                         n3->nredir.n = n2;
11250                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11251                                         n2 = n3;
11252                                 }
11253                                 n2->type = NBACKGND;
11254                         }
11255                 }
11256                 if (n1 == NULL) {
11257                         n1 = n2;
11258                 } else {
11259                         n3 = stzalloc(sizeof(struct nbinary));
11260                         n3->type = NSEMI;
11261                         n3->nbinary.ch1 = n1;
11262                         n3->nbinary.ch2 = n2;
11263                         n1 = n3;
11264                 }
11265                 switch (tok) {
11266                 case TNL:
11267                 case TEOF:
11268                         tokpushback = 1;
11269                         /* fall through */
11270                 case TBACKGND:
11271                 case TSEMI:
11272                         break;
11273                 default:
11274                         if ((nlflag & 1))
11275                                 raise_error_unexpected_syntax(-1);
11276                         tokpushback = 1;
11277                         return n1;
11278                 }
11279         }
11280 }
11281
11282 static union node *
11283 andor(void)
11284 {
11285         union node *n1, *n2, *n3;
11286         int t;
11287
11288         n1 = pipeline();
11289         for (;;) {
11290                 t = readtoken();
11291                 if (t == TAND) {
11292                         t = NAND;
11293                 } else if (t == TOR) {
11294                         t = NOR;
11295                 } else {
11296                         tokpushback = 1;
11297                         return n1;
11298                 }
11299                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11300                 n2 = pipeline();
11301                 n3 = stzalloc(sizeof(struct nbinary));
11302                 n3->type = t;
11303                 n3->nbinary.ch1 = n1;
11304                 n3->nbinary.ch2 = n2;
11305                 n1 = n3;
11306         }
11307 }
11308
11309 static union node *
11310 pipeline(void)
11311 {
11312         union node *n1, *n2, *pipenode;
11313         struct nodelist *lp, *prev;
11314         int negate;
11315
11316         negate = 0;
11317         TRACE(("pipeline: entered\n"));
11318         if (readtoken() == TNOT) {
11319                 negate = !negate;
11320                 checkkwd = CHKKWD | CHKALIAS;
11321         } else
11322                 tokpushback = 1;
11323         n1 = parse_command();
11324         if (readtoken() == TPIPE) {
11325                 pipenode = stzalloc(sizeof(struct npipe));
11326                 pipenode->type = NPIPE;
11327                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11328                 lp = stzalloc(sizeof(struct nodelist));
11329                 pipenode->npipe.cmdlist = lp;
11330                 lp->n = n1;
11331                 do {
11332                         prev = lp;
11333                         lp = stzalloc(sizeof(struct nodelist));
11334                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11335                         lp->n = parse_command();
11336                         prev->next = lp;
11337                 } while (readtoken() == TPIPE);
11338                 lp->next = NULL;
11339                 n1 = pipenode;
11340         }
11341         tokpushback = 1;
11342         if (negate) {
11343                 n2 = stzalloc(sizeof(struct nnot));
11344                 n2->type = NNOT;
11345                 n2->nnot.com = n1;
11346                 return n2;
11347         }
11348         return n1;
11349 }
11350
11351 static union node *
11352 makename(void)
11353 {
11354         union node *n;
11355
11356         n = stzalloc(sizeof(struct narg));
11357         n->type = NARG;
11358         /*n->narg.next = NULL; - stzalloc did it */
11359         n->narg.text = wordtext;
11360         n->narg.backquote = backquotelist;
11361         return n;
11362 }
11363
11364 static void
11365 fixredir(union node *n, const char *text, int err)
11366 {
11367         int fd;
11368
11369         TRACE(("Fix redir %s %d\n", text, err));
11370         if (!err)
11371                 n->ndup.vname = NULL;
11372
11373         fd = bb_strtou(text, NULL, 10);
11374         if (!errno && fd >= 0)
11375                 n->ndup.dupfd = fd;
11376         else if (LONE_DASH(text))
11377                 n->ndup.dupfd = -1;
11378         else {
11379                 if (err)
11380                         raise_error_syntax("bad fd number");
11381                 n->ndup.vname = makename();
11382         }
11383 }
11384
11385 static void
11386 parsefname(void)
11387 {
11388         union node *n = redirnode;
11389
11390         if (n->type == NHERE)
11391                 checkkwd = CHKEOFMARK;
11392         if (readtoken() != TWORD)
11393                 raise_error_unexpected_syntax(-1);
11394         if (n->type == NHERE) {
11395                 struct heredoc *here = heredoc;
11396                 struct heredoc *p;
11397
11398                 if (quoteflag == 0)
11399                         n->type = NXHERE;
11400                 TRACE(("Here document %d\n", n->type));
11401                 rmescapes(wordtext, 0, NULL);
11402                 here->eofmark = wordtext;
11403                 here->next = NULL;
11404                 if (heredoclist == NULL)
11405                         heredoclist = here;
11406                 else {
11407                         for (p = heredoclist; p->next; p = p->next)
11408                                 continue;
11409                         p->next = here;
11410                 }
11411         } else if (n->type == NTOFD || n->type == NFROMFD) {
11412                 fixredir(n, wordtext, 0);
11413         } else {
11414                 n->nfile.fname = makename();
11415         }
11416 }
11417
11418 static union node *
11419 simplecmd(void)
11420 {
11421         union node *args, **app;
11422         union node *n = NULL;
11423         union node *vars, **vpp;
11424         union node **rpp, *redir;
11425         int savecheckkwd;
11426 #if BASH_TEST2
11427         smallint double_brackets_flag = 0;
11428 #endif
11429         IF_BASH_FUNCTION(smallint function_flag = 0;)
11430
11431         args = NULL;
11432         app = &args;
11433         vars = NULL;
11434         vpp = &vars;
11435         redir = NULL;
11436         rpp = &redir;
11437
11438         savecheckkwd = CHKALIAS;
11439         for (;;) {
11440                 int t;
11441                 checkkwd = savecheckkwd;
11442                 t = readtoken();
11443                 switch (t) {
11444 #if BASH_FUNCTION
11445                 case TFUNCTION:
11446                         if (peektoken() != TWORD)
11447                                 raise_error_unexpected_syntax(TWORD);
11448                         function_flag = 1;
11449                         break;
11450 #endif
11451 #if BASH_TEST2
11452                 case TAND: /* "&&" */
11453                 case TOR: /* "||" */
11454                         if (!double_brackets_flag) {
11455                                 tokpushback = 1;
11456                                 goto out;
11457                         }
11458                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11459 #endif
11460                 case TWORD:
11461                         n = stzalloc(sizeof(struct narg));
11462                         n->type = NARG;
11463                         /*n->narg.next = NULL; - stzalloc did it */
11464                         n->narg.text = wordtext;
11465 #if BASH_TEST2
11466                         if (strcmp("[[", wordtext) == 0)
11467                                 double_brackets_flag = 1;
11468                         else if (strcmp("]]", wordtext) == 0)
11469                                 double_brackets_flag = 0;
11470 #endif
11471                         n->narg.backquote = backquotelist;
11472                         if (savecheckkwd && isassignment(wordtext)) {
11473                                 *vpp = n;
11474                                 vpp = &n->narg.next;
11475                         } else {
11476                                 *app = n;
11477                                 app = &n->narg.next;
11478                                 savecheckkwd = 0;
11479                         }
11480 #if BASH_FUNCTION
11481                         if (function_flag) {
11482                                 checkkwd = CHKNL | CHKKWD;
11483                                 switch (peektoken()) {
11484                                 case TBEGIN:
11485                                 case TIF:
11486                                 case TCASE:
11487                                 case TUNTIL:
11488                                 case TWHILE:
11489                                 case TFOR:
11490                                         goto do_func;
11491                                 case TLP:
11492                                         function_flag = 0;
11493                                         break;
11494                                 case TWORD:
11495                                         if (strcmp("[[", wordtext) == 0)
11496                                                 goto do_func;
11497                                         /* fall through */
11498                                 default:
11499                                         raise_error_unexpected_syntax(-1);
11500                                 }
11501                         }
11502 #endif
11503                         break;
11504                 case TREDIR:
11505                         *rpp = n = redirnode;
11506                         rpp = &n->nfile.next;
11507                         parsefname();   /* read name of redirection file */
11508                         break;
11509                 case TLP:
11510  IF_BASH_FUNCTION(do_func:)
11511                         if (args && app == &args->narg.next
11512                          && !vars && !redir
11513                         ) {
11514                                 struct builtincmd *bcmd;
11515                                 const char *name;
11516
11517                                 /* We have a function */
11518                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11519                                         raise_error_unexpected_syntax(TRP);
11520                                 name = n->narg.text;
11521                                 if (!goodname(name)
11522                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11523                                 ) {
11524                                         raise_error_syntax("bad function name");
11525                                 }
11526                                 n->type = NDEFUN;
11527                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11528                                 n->narg.next = parse_command();
11529                                 return n;
11530                         }
11531                         IF_BASH_FUNCTION(function_flag = 0;)
11532                         /* fall through */
11533                 default:
11534                         tokpushback = 1;
11535                         goto out;
11536                 }
11537         }
11538  out:
11539         *app = NULL;
11540         *vpp = NULL;
11541         *rpp = NULL;
11542         n = stzalloc(sizeof(struct ncmd));
11543         n->type = NCMD;
11544         n->ncmd.args = args;
11545         n->ncmd.assign = vars;
11546         n->ncmd.redirect = redir;
11547         return n;
11548 }
11549
11550 static union node *
11551 parse_command(void)
11552 {
11553         union node *n1, *n2;
11554         union node *ap, **app;
11555         union node *cp, **cpp;
11556         union node *redir, **rpp;
11557         union node **rpp2;
11558         int t;
11559
11560         redir = NULL;
11561         rpp2 = &redir;
11562
11563         switch (readtoken()) {
11564         default:
11565                 raise_error_unexpected_syntax(-1);
11566                 /* NOTREACHED */
11567         case TIF:
11568                 n1 = stzalloc(sizeof(struct nif));
11569                 n1->type = NIF;
11570                 n1->nif.test = list(0);
11571                 if (readtoken() != TTHEN)
11572                         raise_error_unexpected_syntax(TTHEN);
11573                 n1->nif.ifpart = list(0);
11574                 n2 = n1;
11575                 while (readtoken() == TELIF) {
11576                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11577                         n2 = n2->nif.elsepart;
11578                         n2->type = NIF;
11579                         n2->nif.test = list(0);
11580                         if (readtoken() != TTHEN)
11581                                 raise_error_unexpected_syntax(TTHEN);
11582                         n2->nif.ifpart = list(0);
11583                 }
11584                 if (lasttoken == TELSE)
11585                         n2->nif.elsepart = list(0);
11586                 else {
11587                         n2->nif.elsepart = NULL;
11588                         tokpushback = 1;
11589                 }
11590                 t = TFI;
11591                 break;
11592         case TWHILE:
11593         case TUNTIL: {
11594                 int got;
11595                 n1 = stzalloc(sizeof(struct nbinary));
11596                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11597                 n1->nbinary.ch1 = list(0);
11598                 got = readtoken();
11599                 if (got != TDO) {
11600                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11601                                         got == TWORD ? wordtext : ""));
11602                         raise_error_unexpected_syntax(TDO);
11603                 }
11604                 n1->nbinary.ch2 = list(0);
11605                 t = TDONE;
11606                 break;
11607         }
11608         case TFOR:
11609                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11610                         raise_error_syntax("bad for loop variable");
11611                 n1 = stzalloc(sizeof(struct nfor));
11612                 n1->type = NFOR;
11613                 n1->nfor.var = wordtext;
11614                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11615                 if (readtoken() == TIN) {
11616                         app = &ap;
11617                         while (readtoken() == TWORD) {
11618                                 n2 = stzalloc(sizeof(struct narg));
11619                                 n2->type = NARG;
11620                                 /*n2->narg.next = NULL; - stzalloc did it */
11621                                 n2->narg.text = wordtext;
11622                                 n2->narg.backquote = backquotelist;
11623                                 *app = n2;
11624                                 app = &n2->narg.next;
11625                         }
11626                         *app = NULL;
11627                         n1->nfor.args = ap;
11628                         if (lasttoken != TNL && lasttoken != TSEMI)
11629                                 raise_error_unexpected_syntax(-1);
11630                 } else {
11631                         n2 = stzalloc(sizeof(struct narg));
11632                         n2->type = NARG;
11633                         /*n2->narg.next = NULL; - stzalloc did it */
11634                         n2->narg.text = (char *)dolatstr;
11635                         /*n2->narg.backquote = NULL;*/
11636                         n1->nfor.args = n2;
11637                         /*
11638                          * Newline or semicolon here is optional (but note
11639                          * that the original Bourne shell only allowed NL).
11640                          */
11641                         if (lasttoken != TSEMI)
11642                                 tokpushback = 1;
11643                 }
11644                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11645                 if (readtoken() != TDO)
11646                         raise_error_unexpected_syntax(TDO);
11647                 n1->nfor.body = list(0);
11648                 t = TDONE;
11649                 break;
11650         case TCASE:
11651                 n1 = stzalloc(sizeof(struct ncase));
11652                 n1->type = NCASE;
11653                 if (readtoken() != TWORD)
11654                         raise_error_unexpected_syntax(TWORD);
11655                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11656                 n2->type = NARG;
11657                 /*n2->narg.next = NULL; - stzalloc did it */
11658                 n2->narg.text = wordtext;
11659                 n2->narg.backquote = backquotelist;
11660                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11661                 if (readtoken() != TIN)
11662                         raise_error_unexpected_syntax(TIN);
11663                 cpp = &n1->ncase.cases;
11664  next_case:
11665                 checkkwd = CHKNL | CHKKWD;
11666                 t = readtoken();
11667                 while (t != TESAC) {
11668                         if (lasttoken == TLP)
11669                                 readtoken();
11670                         *cpp = cp = stzalloc(sizeof(struct nclist));
11671                         cp->type = NCLIST;
11672                         app = &cp->nclist.pattern;
11673                         for (;;) {
11674                                 *app = ap = stzalloc(sizeof(struct narg));
11675                                 ap->type = NARG;
11676                                 /*ap->narg.next = NULL; - stzalloc did it */
11677                                 ap->narg.text = wordtext;
11678                                 ap->narg.backquote = backquotelist;
11679                                 if (readtoken() != TPIPE)
11680                                         break;
11681                                 app = &ap->narg.next;
11682                                 readtoken();
11683                         }
11684                         //ap->narg.next = NULL;
11685                         if (lasttoken != TRP)
11686                                 raise_error_unexpected_syntax(TRP);
11687                         cp->nclist.body = list(2);
11688
11689                         cpp = &cp->nclist.next;
11690
11691                         checkkwd = CHKNL | CHKKWD;
11692                         t = readtoken();
11693                         if (t != TESAC) {
11694                                 if (t != TENDCASE)
11695                                         raise_error_unexpected_syntax(TENDCASE);
11696                                 goto next_case;
11697                         }
11698                 }
11699                 *cpp = NULL;
11700                 goto redir;
11701         case TLP:
11702                 n1 = stzalloc(sizeof(struct nredir));
11703                 n1->type = NSUBSHELL;
11704                 n1->nredir.n = list(0);
11705                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11706                 t = TRP;
11707                 break;
11708         case TBEGIN:
11709                 n1 = list(0);
11710                 t = TEND;
11711                 break;
11712         IF_BASH_FUNCTION(case TFUNCTION:)
11713         case TWORD:
11714         case TREDIR:
11715                 tokpushback = 1;
11716                 return simplecmd();
11717         }
11718
11719         if (readtoken() != t)
11720                 raise_error_unexpected_syntax(t);
11721
11722  redir:
11723         /* Now check for redirection which may follow command */
11724         checkkwd = CHKKWD | CHKALIAS;
11725         rpp = rpp2;
11726         while (readtoken() == TREDIR) {
11727                 *rpp = n2 = redirnode;
11728                 rpp = &n2->nfile.next;
11729                 parsefname();
11730         }
11731         tokpushback = 1;
11732         *rpp = NULL;
11733         if (redir) {
11734                 if (n1->type != NSUBSHELL) {
11735                         n2 = stzalloc(sizeof(struct nredir));
11736                         n2->type = NREDIR;
11737                         n2->nredir.n = n1;
11738                         n1 = n2;
11739                 }
11740                 n1->nredir.redirect = redir;
11741         }
11742         return n1;
11743 }
11744
11745 #if BASH_DOLLAR_SQUOTE
11746 static int
11747 decode_dollar_squote(void)
11748 {
11749         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11750         int c, cnt;
11751         char *p;
11752         char buf[4];
11753
11754         c = pgetc();
11755         p = strchr(C_escapes, c);
11756         if (p) {
11757                 buf[0] = c;
11758                 p = buf;
11759                 cnt = 3;
11760                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11761                         do {
11762                                 c = pgetc();
11763                                 *++p = c;
11764                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11765                         pungetc();
11766                 } else if (c == 'x') { /* \xHH */
11767                         do {
11768                                 c = pgetc();
11769                                 *++p = c;
11770                         } while (isxdigit(c) && --cnt);
11771                         pungetc();
11772                         if (cnt == 3) { /* \x but next char is "bad" */
11773                                 c = 'x';
11774                                 goto unrecognized;
11775                         }
11776                 } else { /* simple seq like \\ or \t */
11777                         p++;
11778                 }
11779                 *p = '\0';
11780                 p = buf;
11781                 c = bb_process_escape_sequence((void*)&p);
11782         } else { /* unrecognized "\z": print both chars unless ' or " */
11783                 if (c != '\'' && c != '"') {
11784  unrecognized:
11785                         c |= 0x100; /* "please encode \, then me" */
11786                 }
11787         }
11788         return c;
11789 }
11790 #endif
11791
11792 /* Used by expandstr to get here-doc like behaviour. */
11793 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11794
11795 static ALWAYS_INLINE int
11796 realeofmark(const char *eofmark)
11797 {
11798         return eofmark && eofmark != FAKEEOFMARK;
11799 }
11800
11801 /*
11802  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11803  * is not NULL, read a here document.  In the latter case, eofmark is the
11804  * word which marks the end of the document and striptabs is true if
11805  * leading tabs should be stripped from the document.  The argument c
11806  * is the first character of the input token or document.
11807  *
11808  * Because C does not have internal subroutines, I have simulated them
11809  * using goto's to implement the subroutine linkage.  The following macros
11810  * will run code that appears at the end of readtoken1.
11811  */
11812 #define CHECKEND()      {goto checkend; checkend_return:;}
11813 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11814 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11815 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11816 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11817 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11818 static int
11819 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11820 {
11821         /* NB: syntax parameter fits into smallint */
11822         /* c parameter is an unsigned char or PEOF or PEOA */
11823         char *out;
11824         size_t len;
11825         struct nodelist *bqlist;
11826         smallint quotef;
11827         smallint dblquote;
11828         smallint oldstyle;
11829         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11830         smallint pssyntax;   /* we are expanding a prompt string */
11831         int varnest;         /* levels of variables expansion */
11832         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11833         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11834         int dqvarnest;       /* levels of variables expansion within double quotes */
11835
11836         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11837
11838         startlinno = g_parsefile->linno;
11839         bqlist = NULL;
11840         quotef = 0;
11841         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11842 #if ENABLE_ASH_EXPAND_PRMT
11843         pssyntax = (syntax == PSSYNTAX);
11844         if (pssyntax)
11845                 syntax = DQSYNTAX;
11846 #else
11847         pssyntax = 0; /* constant */
11848 #endif
11849         dblquote = (syntax == DQSYNTAX);
11850         varnest = 0;
11851         IF_FEATURE_SH_MATH(arinest = 0;)
11852         IF_FEATURE_SH_MATH(parenlevel = 0;)
11853         dqvarnest = 0;
11854
11855         STARTSTACKSTR(out);
11856  loop:
11857         /* For each line, until end of word */
11858         CHECKEND();     /* set c to PEOF if at end of here document */
11859         for (;;) {      /* until end of line or end of word */
11860                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11861                 switch (SIT(c, syntax)) {
11862                 case CNL:       /* '\n' */
11863                         if (syntax == BASESYNTAX)
11864                                 goto endword;   /* exit outer loop */
11865                         USTPUTC(c, out);
11866                         nlprompt();
11867                         c = pgetc();
11868                         goto loop;              /* continue outer loop */
11869                 case CWORD:
11870                         USTPUTC(c, out);
11871                         break;
11872                 case CCTL:
11873 #if BASH_DOLLAR_SQUOTE
11874                         if (c == '\\' && bash_dollar_squote) {
11875                                 c = decode_dollar_squote();
11876                                 if (c == '\0') {
11877                                         /* skip $'\000', $'\x00' (like bash) */
11878                                         break;
11879                                 }
11880                                 if (c & 0x100) {
11881                                         /* Unknown escape. Encode as '\z' */
11882                                         c = (unsigned char)c;
11883                                         if (eofmark == NULL || dblquote)
11884                                                 USTPUTC(CTLESC, out);
11885                                         USTPUTC('\\', out);
11886                                 }
11887                         }
11888 #endif
11889                         if (eofmark == NULL || dblquote)
11890                                 USTPUTC(CTLESC, out);
11891                         USTPUTC(c, out);
11892                         break;
11893                 case CBACK:     /* backslash */
11894                         c = pgetc_without_PEOA();
11895                         if (c == PEOF) {
11896                                 USTPUTC(CTLESC, out);
11897                                 USTPUTC('\\', out);
11898                                 pungetc();
11899                         } else if (c == '\n') {
11900                                 nlprompt();
11901                         } else {
11902                                 if (pssyntax && c == '$') {
11903                                         USTPUTC(CTLESC, out);
11904                                         USTPUTC('\\', out);
11905                                 }
11906                                 /* Backslash is retained if we are in "str" and next char isn't special */
11907                                 if (dblquote
11908                                  && c != '\\'
11909                                  && c != '`'
11910                                  && c != '$'
11911                                  && (c != '"' || eofmark != NULL)
11912                                 ) {
11913                                         USTPUTC('\\', out);
11914                                 }
11915                                 USTPUTC(CTLESC, out);
11916                                 USTPUTC(c, out);
11917                                 quotef = 1;
11918                         }
11919                         break;
11920                 case CSQUOTE:
11921                         syntax = SQSYNTAX;
11922  quotemark:
11923                         if (eofmark == NULL) {
11924                                 USTPUTC(CTLQUOTEMARK, out);
11925                         }
11926                         break;
11927                 case CDQUOTE:
11928                         syntax = DQSYNTAX;
11929                         dblquote = 1;
11930                         goto quotemark;
11931                 case CENDQUOTE:
11932                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11933                         if (eofmark != NULL && varnest == 0) {
11934                                 USTPUTC(c, out);
11935                         } else {
11936                                 if (dqvarnest == 0) {
11937                                         syntax = BASESYNTAX;
11938                                         dblquote = 0;
11939                                 }
11940                                 quotef = 1;
11941                                 goto quotemark;
11942                         }
11943                         break;
11944                 case CVAR:      /* '$' */
11945                         PARSESUB();             /* parse substitution */
11946                         break;
11947                 case CENDVAR:   /* '}' */
11948                         if (varnest > 0) {
11949                                 varnest--;
11950                                 if (dqvarnest > 0) {
11951                                         dqvarnest--;
11952                                 }
11953                                 c = CTLENDVAR;
11954                         }
11955                         USTPUTC(c, out);
11956                         break;
11957 #if ENABLE_FEATURE_SH_MATH
11958                 case CLP:       /* '(' in arithmetic */
11959                         parenlevel++;
11960                         USTPUTC(c, out);
11961                         break;
11962                 case CRP:       /* ')' in arithmetic */
11963                         if (parenlevel > 0) {
11964                                 parenlevel--;
11965                         } else {
11966                                 if (pgetc_eatbnl() == ')') {
11967                                         c = CTLENDARI;
11968                                         if (--arinest == 0) {
11969                                                 syntax = prevsyntax;
11970                                         }
11971                                 } else {
11972                                         /*
11973                                          * unbalanced parens
11974                                          * (don't 2nd guess - no error)
11975                                          */
11976                                         pungetc();
11977                                 }
11978                         }
11979                         USTPUTC(c, out);
11980                         break;
11981 #endif
11982                 case CBQUOTE:   /* '`' */
11983                         PARSEBACKQOLD();
11984                         break;
11985                 case CENDFILE:
11986                         goto endword;           /* exit outer loop */
11987                 case CIGN:
11988                         break;
11989                 default:
11990                         if (varnest == 0) {
11991 #if BASH_REDIR_OUTPUT
11992                                 if (c == '&') {
11993 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11994                                         if (pgetc() == '>')
11995                                                 c = 0x100 + '>'; /* flag &> */
11996                                         pungetc();
11997                                 }
11998 #endif
11999                                 goto endword;   /* exit outer loop */
12000                         }
12001                         IF_ASH_ALIAS(if (c != PEOA))
12002                                 USTPUTC(c, out);
12003                 }
12004                 c = pgetc();
12005         } /* for (;;) */
12006  endword:
12007
12008 #if ENABLE_FEATURE_SH_MATH
12009         if (syntax == ARISYNTAX)
12010                 raise_error_syntax("missing '))'");
12011 #endif
12012         if (syntax != BASESYNTAX && eofmark == NULL)
12013                 raise_error_syntax("unterminated quoted string");
12014         if (varnest != 0) {
12015                 startlinno = g_parsefile->linno;
12016                 /* { */
12017                 raise_error_syntax("missing '}'");
12018         }
12019         USTPUTC('\0', out);
12020         len = out - (char *)stackblock();
12021         out = stackblock();
12022         if (eofmark == NULL) {
12023                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12024                  && quotef == 0
12025                 ) {
12026                         if (isdigit_str9(out)) {
12027                                 PARSEREDIR(); /* passed as params: out, c */
12028                                 lasttoken = TREDIR;
12029                                 return lasttoken;
12030                         }
12031                         /* else: non-number X seen, interpret it
12032                          * as "NNNX>file" = "NNNX >file" */
12033                 }
12034                 pungetc();
12035         }
12036         quoteflag = quotef;
12037         backquotelist = bqlist;
12038         grabstackblock(len);
12039         wordtext = out;
12040         lasttoken = TWORD;
12041         return lasttoken;
12042 /* end of readtoken routine */
12043
12044 /*
12045  * Check to see whether we are at the end of the here document.  When this
12046  * is called, c is set to the first character of the next input line.  If
12047  * we are at the end of the here document, this routine sets the c to PEOF.
12048  */
12049 checkend: {
12050         if (realeofmark(eofmark)) {
12051                 int markloc;
12052                 char *p;
12053
12054 #if ENABLE_ASH_ALIAS
12055                 if (c == PEOA)
12056                         c = pgetc_without_PEOA();
12057 #endif
12058                 if (striptabs) {
12059                         while (c == '\t') {
12060                                 c = pgetc_without_PEOA();
12061                         }
12062                 }
12063
12064                 markloc = out - (char *)stackblock();
12065                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12066                         if (c != *p)
12067                                 goto more_heredoc;
12068
12069                         c = pgetc_without_PEOA();
12070                 }
12071
12072                 if (c == '\n' || c == PEOF) {
12073                         c = PEOF;
12074                         g_parsefile->linno++;
12075                         needprompt = doprompt;
12076                 } else {
12077                         int len_here;
12078
12079  more_heredoc:
12080                         p = (char *)stackblock() + markloc + 1;
12081                         len_here = out - p;
12082
12083                         if (len_here) {
12084                                 len_here -= (c >= PEOF);
12085                                 c = p[-1];
12086
12087                                 if (len_here) {
12088                                         char *str;
12089
12090                                         str = alloca(len_here + 1);
12091                                         *(char *)mempcpy(str, p, len_here) = '\0';
12092
12093                                         pushstring(str, NULL);
12094                                 }
12095                         }
12096                 }
12097
12098                 STADJUST((char *)stackblock() + markloc - out, out);
12099         }
12100         goto checkend_return;
12101 }
12102
12103 /*
12104  * Parse a redirection operator.  The variable "out" points to a string
12105  * specifying the fd to be redirected.  The variable "c" contains the
12106  * first character of the redirection operator.
12107  */
12108 parseredir: {
12109         /* out is already checked to be a valid number or "" */
12110         int fd = (*out == '\0' ? -1 : atoi(out));
12111         union node *np;
12112
12113         np = stzalloc(sizeof(struct nfile));
12114         if (c == '>') {
12115                 np->nfile.fd = 1;
12116                 c = pgetc();
12117                 if (c == '>')
12118                         np->type = NAPPEND;
12119                 else if (c == '|')
12120                         np->type = NCLOBBER;
12121                 else if (c == '&')
12122                         np->type = NTOFD;
12123                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12124                 else {
12125                         np->type = NTO;
12126                         pungetc();
12127                 }
12128         }
12129 #if BASH_REDIR_OUTPUT
12130         else if (c == 0x100 + '>') { /* this flags &> redirection */
12131                 np->nfile.fd = 1;
12132                 pgetc(); /* this is '>', no need to check */
12133                 np->type = NTO2;
12134         }
12135 #endif
12136         else { /* c == '<' */
12137                 /*np->nfile.fd = 0; - stzalloc did it */
12138                 c = pgetc();
12139                 switch (c) {
12140                 case '<':
12141                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12142                                 np = stzalloc(sizeof(struct nhere));
12143                                 /*np->nfile.fd = 0; - stzalloc did it */
12144                         }
12145                         np->type = NHERE;
12146                         heredoc = stzalloc(sizeof(struct heredoc));
12147                         heredoc->here = np;
12148                         c = pgetc();
12149                         if (c == '-') {
12150                                 heredoc->striptabs = 1;
12151                         } else {
12152                                 /*heredoc->striptabs = 0; - stzalloc did it */
12153                                 pungetc();
12154                         }
12155                         break;
12156
12157                 case '&':
12158                         np->type = NFROMFD;
12159                         break;
12160
12161                 case '>':
12162                         np->type = NFROMTO;
12163                         break;
12164
12165                 default:
12166                         np->type = NFROM;
12167                         pungetc();
12168                         break;
12169                 }
12170         }
12171         if (fd >= 0)
12172                 np->nfile.fd = fd;
12173         redirnode = np;
12174         goto parseredir_return;
12175 }
12176
12177 /*
12178  * Parse a substitution.  At this point, we have read the dollar sign
12179  * and nothing else.
12180  */
12181
12182 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12183  * (assuming ascii char codes, as the original implementation did) */
12184 #define is_special(c) \
12185         (((unsigned)(c) - 33 < 32) \
12186                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12187 parsesub: {
12188         unsigned char subtype;
12189         int typeloc;
12190
12191         c = pgetc_eatbnl();
12192         if ((checkkwd & CHKEOFMARK)
12193          || c > 255 /* PEOA or PEOF */
12194          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12195         ) {
12196 #if BASH_DOLLAR_SQUOTE
12197                 if (syntax != DQSYNTAX && c == '\'')
12198                         bash_dollar_squote = 1;
12199                 else
12200 #endif
12201                         USTPUTC('$', out);
12202                 pungetc();
12203         } else if (c == '(') {
12204                 /* $(command) or $((arith)) */
12205                 if (pgetc_eatbnl() == '(') {
12206 #if ENABLE_FEATURE_SH_MATH
12207                         PARSEARITH();
12208 #else
12209                         raise_error_syntax("support for $((arith)) is disabled");
12210 #endif
12211                 } else {
12212                         pungetc();
12213                         PARSEBACKQNEW();
12214                 }
12215         } else {
12216                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12217                 USTPUTC(CTLVAR, out);
12218                 typeloc = out - (char *)stackblock();
12219                 STADJUST(1, out);
12220                 subtype = VSNORMAL;
12221                 if (c == '{') {
12222                         c = pgetc_eatbnl();
12223                         subtype = 0;
12224                 }
12225  varname:
12226                 if (is_name(c)) {
12227                         /* $[{[#]]NAME[}] */
12228                         do {
12229                                 STPUTC(c, out);
12230                                 c = pgetc_eatbnl();
12231                         } while (is_in_name(c));
12232                 } else if (isdigit(c)) {
12233                         /* $[{[#]]NUM[}] */
12234                         do {
12235                                 STPUTC(c, out);
12236                                 c = pgetc_eatbnl();
12237                         } while (isdigit(c));
12238                 } else {
12239                         /* $[{[#]]<specialchar>[}] */
12240                         int cc = c;
12241
12242                         c = pgetc_eatbnl();
12243                         if (!subtype && cc == '#') {
12244                                 subtype = VSLENGTH;
12245                                 if (c == '_' || isalnum(c))
12246                                         goto varname;
12247                                 cc = c;
12248                                 c = pgetc_eatbnl();
12249                                 if (cc == '}' || c != '}') {
12250                                         pungetc();
12251                                         subtype = 0;
12252                                         c = cc;
12253                                         cc = '#';
12254                                 }
12255                         }
12256
12257                         if (!is_special(cc)) {
12258                                 if (subtype == VSLENGTH)
12259                                         subtype = 0;
12260                                 goto badsub;
12261                         }
12262
12263                         USTPUTC(cc, out);
12264                 }
12265
12266                 if (c != '}' && subtype == VSLENGTH) {
12267                         /* ${#VAR didn't end with } */
12268                         goto badsub;
12269                 }
12270
12271                 if (subtype == 0) {
12272                         static const char types[] ALIGN1 = "}-+?=";
12273                         /* ${VAR...} but not $VAR or ${#VAR} */
12274                         /* c == first char after VAR */
12275                         switch (c) {
12276                         case ':':
12277                                 c = pgetc_eatbnl();
12278 #if BASH_SUBSTR
12279                                 /* This check is only needed to not misinterpret
12280                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12281                                  * constructs.
12282                                  */
12283                                 if (!strchr(types, c)) {
12284                                         subtype = VSSUBSTR;
12285                                         pungetc();
12286                                         break; /* "goto badsub" is bigger (!) */
12287                                 }
12288 #endif
12289                                 subtype = VSNUL;
12290                                 /*FALLTHROUGH*/
12291                         default: {
12292                                 const char *p = strchr(types, c);
12293                                 if (p == NULL)
12294                                         break;
12295                                 subtype |= p - types + VSNORMAL;
12296                                 break;
12297                         }
12298                         case '%':
12299                         case '#': {
12300                                 int cc = c;
12301                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12302                                 c = pgetc_eatbnl();
12303                                 if (c != cc)
12304                                         goto badsub;
12305                                 subtype++;
12306                                 break;
12307                         }
12308 #if BASH_PATTERN_SUBST
12309                         case '/':
12310                                 /* ${v/[/]pattern/repl} */
12311 //TODO: encode pattern and repl separately.
12312 // Currently ${v/$var_with_slash/repl} is horribly broken
12313                                 subtype = VSREPLACE;
12314                                 c = pgetc_eatbnl();
12315                                 if (c != '/')
12316                                         goto badsub;
12317                                 subtype++; /* VSREPLACEALL */
12318                                 break;
12319 #endif
12320                         }
12321                 } else {
12322  badsub:
12323                         pungetc();
12324                 }
12325                 ((unsigned char *)stackblock())[typeloc] = subtype;
12326                 if (subtype != VSNORMAL) {
12327                         varnest++;
12328                         if (dblquote)
12329                                 dqvarnest++;
12330                 }
12331                 STPUTC('=', out);
12332         }
12333         goto parsesub_return;
12334 }
12335
12336 /*
12337  * Called to parse command substitutions.  Newstyle is set if the command
12338  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12339  * list of commands (passed by reference), and savelen is the number of
12340  * characters on the top of the stack which must be preserved.
12341  */
12342 parsebackq: {
12343         struct nodelist **nlpp;
12344         union node *n;
12345         char *str;
12346         size_t savelen;
12347         smallint saveprompt = 0;
12348
12349         str = NULL;
12350         savelen = out - (char *)stackblock();
12351         if (savelen > 0) {
12352                 /*
12353                  * FIXME: this can allocate very large block on stack and SEGV.
12354                  * Example:
12355                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12356                  * allocates 100kb for every command subst. With about
12357                  * a hundred command substitutions stack overflows.
12358                  * With larger prepended string, SEGV happens sooner.
12359                  */
12360                 str = alloca(savelen);
12361                 memcpy(str, stackblock(), savelen);
12362         }
12363
12364         if (oldstyle) {
12365                 /* We must read until the closing backquote, giving special
12366                  * treatment to some slashes, and then push the string and
12367                  * reread it as input, interpreting it normally.
12368                  */
12369                 char *pout;
12370                 size_t psavelen;
12371                 char *pstr;
12372
12373                 STARTSTACKSTR(pout);
12374                 for (;;) {
12375                         int pc;
12376
12377                         setprompt_if(needprompt, 2);
12378                         pc = pgetc();
12379                         switch (pc) {
12380                         case '`':
12381                                 goto done;
12382
12383                         case '\\':
12384                                 pc = pgetc();
12385                                 if (pc == '\n') {
12386                                         nlprompt();
12387                                         /*
12388                                          * If eating a newline, avoid putting
12389                                          * the newline into the new character
12390                                          * stream (via the STPUTC after the
12391                                          * switch).
12392                                          */
12393                                         continue;
12394                                 }
12395                                 if (pc != '\\' && pc != '`' && pc != '$'
12396                                  && (!dblquote || pc != '"')
12397                                 ) {
12398                                         STPUTC('\\', pout);
12399                                 }
12400                                 if (pc <= 255 /* not PEOA or PEOF */) {
12401                                         break;
12402                                 }
12403                                 /* fall through */
12404
12405                         case PEOF:
12406                         IF_ASH_ALIAS(case PEOA:)
12407                                 startlinno = g_parsefile->linno;
12408                                 raise_error_syntax("EOF in backquote substitution");
12409
12410                         case '\n':
12411                                 nlnoprompt();
12412                                 break;
12413
12414                         default:
12415                                 break;
12416                         }
12417                         STPUTC(pc, pout);
12418                 }
12419  done:
12420                 STPUTC('\0', pout);
12421                 psavelen = pout - (char *)stackblock();
12422                 if (psavelen > 0) {
12423                         pstr = grabstackstr(pout);
12424                         setinputstring(pstr);
12425                 }
12426         }
12427         nlpp = &bqlist;
12428         while (*nlpp)
12429                 nlpp = &(*nlpp)->next;
12430         *nlpp = stzalloc(sizeof(**nlpp));
12431         /* (*nlpp)->next = NULL; - stzalloc did it */
12432
12433         if (oldstyle) {
12434                 saveprompt = doprompt;
12435                 doprompt = 0;
12436         }
12437
12438         n = list(2);
12439
12440         if (oldstyle)
12441                 doprompt = saveprompt;
12442         else if (readtoken() != TRP)
12443                 raise_error_unexpected_syntax(TRP);
12444
12445         (*nlpp)->n = n;
12446         if (oldstyle) {
12447                 /*
12448                  * Start reading from old file again, ignoring any pushed back
12449                  * tokens left from the backquote parsing
12450                  */
12451                 popfile();
12452                 tokpushback = 0;
12453         }
12454         while (stackblocksize() <= savelen)
12455                 growstackblock();
12456         STARTSTACKSTR(out);
12457         if (str) {
12458                 memcpy(out, str, savelen);
12459                 STADJUST(savelen, out);
12460         }
12461         USTPUTC(CTLBACKQ, out);
12462         if (oldstyle)
12463                 goto parsebackq_oldreturn;
12464         goto parsebackq_newreturn;
12465 }
12466
12467 #if ENABLE_FEATURE_SH_MATH
12468 /*
12469  * Parse an arithmetic expansion (indicate start of one and set state)
12470  */
12471 parsearith: {
12472         if (++arinest == 1) {
12473                 prevsyntax = syntax;
12474                 syntax = ARISYNTAX;
12475         }
12476         USTPUTC(CTLARI, out);
12477         goto parsearith_return;
12478 }
12479 #endif
12480 } /* end of readtoken */
12481
12482 /*
12483  * Read the next input token.
12484  * If the token is a word, we set backquotelist to the list of cmds in
12485  *      backquotes.  We set quoteflag to true if any part of the word was
12486  *      quoted.
12487  * If the token is TREDIR, then we set redirnode to a structure containing
12488  *      the redirection.
12489  * In all cases, the variable startlinno is set to the number of the line
12490  *      on which the token starts.
12491  *
12492  * [Change comment:  here documents and internal procedures]
12493  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12494  *  word parsing code into a separate routine.  In this case, readtoken
12495  *  doesn't need to have any internal procedures, but parseword does.
12496  *  We could also make parseoperator in essence the main routine, and
12497  *  have parseword (readtoken1?) handle both words and redirection.]
12498  */
12499 #define NEW_xxreadtoken
12500 #ifdef NEW_xxreadtoken
12501 /* singles must be first! */
12502 static const char xxreadtoken_chars[7] ALIGN1 = {
12503         '\n', '(', ')', /* singles */
12504         '&', '|', ';',  /* doubles */
12505         0
12506 };
12507
12508 #define xxreadtoken_singles 3
12509 #define xxreadtoken_doubles 3
12510
12511 static const char xxreadtoken_tokens[] ALIGN1 = {
12512         TNL, TLP, TRP,          /* only single occurrence allowed */
12513         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12514         TEOF,                   /* corresponds to trailing nul */
12515         TAND, TOR, TENDCASE     /* if double occurrence */
12516 };
12517
12518 static int
12519 xxreadtoken(void)
12520 {
12521         int c;
12522
12523         if (tokpushback) {
12524                 tokpushback = 0;
12525                 return lasttoken;
12526         }
12527         setprompt_if(needprompt, 2);
12528         startlinno = g_parsefile->linno;
12529         for (;;) {                      /* until token or start of word found */
12530                 c = pgetc();
12531                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12532                         continue;
12533
12534                 if (c == '#') {
12535                         while ((c = pgetc()) != '\n' && c != PEOF)
12536                                 continue;
12537                         pungetc();
12538                 } else if (c == '\\') {
12539                         if (pgetc() != '\n') {
12540                                 pungetc();
12541                                 break; /* return readtoken1(...) */
12542                         }
12543                         nlprompt();
12544                 } else {
12545                         const char *p;
12546
12547                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12548                         if (c != PEOF) {
12549                                 if (c == '\n') {
12550                                         nlnoprompt();
12551                                 }
12552
12553                                 p = strchr(xxreadtoken_chars, c);
12554                                 if (p == NULL)
12555                                         break; /* return readtoken1(...) */
12556
12557                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12558                                         int cc = pgetc();
12559                                         if (cc == c) {    /* double occurrence? */
12560                                                 p += xxreadtoken_doubles + 1;
12561                                         } else {
12562                                                 pungetc();
12563 #if BASH_REDIR_OUTPUT
12564                                                 if (c == '&' && cc == '>') /* &> */
12565                                                         break; /* return readtoken1(...) */
12566 #endif
12567                                         }
12568                                 }
12569                         }
12570                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12571                         return lasttoken;
12572                 }
12573         } /* for (;;) */
12574
12575         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12576 }
12577 #else /* old xxreadtoken */
12578 #define RETURN(token)   return lasttoken = token
12579 static int
12580 xxreadtoken(void)
12581 {
12582         int c;
12583
12584         if (tokpushback) {
12585                 tokpushback = 0;
12586                 return lasttoken;
12587         }
12588         setprompt_if(needprompt, 2);
12589         startlinno = g_parsefile->linno;
12590         for (;;) {      /* until token or start of word found */
12591                 c = pgetc();
12592                 switch (c) {
12593                 case ' ': case '\t':
12594                 IF_ASH_ALIAS(case PEOA:)
12595                         continue;
12596                 case '#':
12597                         while ((c = pgetc()) != '\n' && c != PEOF)
12598                                 continue;
12599                         pungetc();
12600                         continue;
12601                 case '\\':
12602                         if (pgetc() == '\n') {
12603                                 nlprompt();
12604                                 continue;
12605                         }
12606                         pungetc();
12607                         goto breakloop;
12608                 case '\n':
12609                         nlnoprompt();
12610                         RETURN(TNL);
12611                 case PEOF:
12612                         RETURN(TEOF);
12613                 case '&':
12614                         if (pgetc() == '&')
12615                                 RETURN(TAND);
12616                         pungetc();
12617                         RETURN(TBACKGND);
12618                 case '|':
12619                         if (pgetc() == '|')
12620                                 RETURN(TOR);
12621                         pungetc();
12622                         RETURN(TPIPE);
12623                 case ';':
12624                         if (pgetc() == ';')
12625                                 RETURN(TENDCASE);
12626                         pungetc();
12627                         RETURN(TSEMI);
12628                 case '(':
12629                         RETURN(TLP);
12630                 case ')':
12631                         RETURN(TRP);
12632                 default:
12633                         goto breakloop;
12634                 }
12635         }
12636  breakloop:
12637         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12638 #undef RETURN
12639 }
12640 #endif /* old xxreadtoken */
12641
12642 static int
12643 readtoken(void)
12644 {
12645         int t;
12646         int kwd = checkkwd;
12647 #if DEBUG
12648         smallint alreadyseen = tokpushback;
12649 #endif
12650
12651 #if ENABLE_ASH_ALIAS
12652  top:
12653 #endif
12654
12655         t = xxreadtoken();
12656
12657         /*
12658          * eat newlines
12659          */
12660         if (kwd & CHKNL) {
12661                 while (t == TNL) {
12662                         parseheredoc();
12663                         t = xxreadtoken();
12664                 }
12665         }
12666
12667         if (t != TWORD || quoteflag) {
12668                 goto out;
12669         }
12670
12671         /*
12672          * check for keywords
12673          */
12674         if (kwd & CHKKWD) {
12675                 const char *const *pp;
12676
12677                 pp = findkwd(wordtext);
12678                 if (pp) {
12679                         lasttoken = t = pp - tokname_array;
12680                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12681                         goto out;
12682                 }
12683         }
12684
12685         if (checkkwd & CHKALIAS) {
12686 #if ENABLE_ASH_ALIAS
12687                 struct alias *ap;
12688                 ap = lookupalias(wordtext, 1);
12689                 if (ap != NULL) {
12690                         if (*ap->val) {
12691                                 pushstring(ap->val, ap);
12692                         }
12693                         goto top;
12694                 }
12695 #endif
12696         }
12697  out:
12698         checkkwd = 0;
12699 #if DEBUG
12700         if (!alreadyseen)
12701                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12702         else
12703                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12704 #endif
12705         return t;
12706 }
12707
12708 static int
12709 peektoken(void)
12710 {
12711         int t;
12712
12713         t = readtoken();
12714         tokpushback = 1;
12715         return t;
12716 }
12717
12718 /*
12719  * Read and parse a command.  Returns NODE_EOF on end of file.
12720  * (NULL is a valid parse tree indicating a blank line.)
12721  */
12722 static union node *
12723 parsecmd(int interact)
12724 {
12725         tokpushback = 0;
12726         checkkwd = 0;
12727         heredoclist = 0;
12728         doprompt = interact;
12729         setprompt_if(doprompt, doprompt);
12730         needprompt = 0;
12731         return list(1);
12732 }
12733
12734 /*
12735  * Input any here documents.
12736  */
12737 static void
12738 parseheredoc(void)
12739 {
12740         struct heredoc *here;
12741         union node *n;
12742
12743         here = heredoclist;
12744         heredoclist = NULL;
12745
12746         while (here) {
12747                 setprompt_if(needprompt, 2);
12748                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12749                                 here->eofmark, here->striptabs);
12750                 n = stzalloc(sizeof(struct narg));
12751                 n->narg.type = NARG;
12752                 /*n->narg.next = NULL; - stzalloc did it */
12753                 n->narg.text = wordtext;
12754                 n->narg.backquote = backquotelist;
12755                 here->here->nhere.doc = n;
12756                 here = here->next;
12757         }
12758 }
12759
12760
12761 static const char *
12762 expandstr(const char *ps, int syntax_type)
12763 {
12764         union node n;
12765         int saveprompt;
12766
12767         /* XXX Fix (char *) cast. */
12768         setinputstring((char *)ps);
12769
12770         saveprompt = doprompt;
12771         doprompt = 0;
12772
12773         /* readtoken1() might die horribly.
12774          * Try a prompt with syntactically wrong command:
12775          * PS1='$(date "+%H:%M:%S) > '
12776          */
12777         {
12778                 volatile int saveint;
12779                 struct jmploc *volatile savehandler = exception_handler;
12780                 struct jmploc jmploc;
12781                 SAVE_INT(saveint);
12782                 if (setjmp(jmploc.loc) == 0) {
12783                         exception_handler = &jmploc;
12784                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12785                 }
12786                 exception_handler = savehandler;
12787                 RESTORE_INT(saveint);
12788         }
12789
12790         doprompt = saveprompt;
12791
12792         popfile();
12793
12794         n.narg.type = NARG;
12795         n.narg.next = NULL;
12796         n.narg.text = wordtext;
12797         n.narg.backquote = backquotelist;
12798
12799         expandarg(&n, NULL, EXP_QUOTED);
12800         return stackblock();
12801 }
12802
12803 static inline int
12804 parser_eof(void)
12805 {
12806         return tokpushback && lasttoken == TEOF;
12807 }
12808
12809 /*
12810  * Execute a command or commands contained in a string.
12811  */
12812 static int
12813 evalstring(char *s, int flags)
12814 {
12815         struct jmploc *volatile savehandler;
12816         struct jmploc jmploc;
12817         int ex;
12818
12819         union node *n;
12820         struct stackmark smark;
12821         int status;
12822
12823         s = sstrdup(s);
12824         setinputstring(s);
12825         setstackmark(&smark);
12826
12827         status = 0;
12828         /* On exception inside execution loop, we must popfile().
12829          * Try interactively:
12830          *      readonly a=a
12831          *      command eval "a=b"  # throws "is read only" error
12832          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12833          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12834          */
12835         savehandler = exception_handler;
12836         ex = setjmp(jmploc.loc);
12837         if (ex)
12838                 goto out;
12839         exception_handler = &jmploc;
12840
12841         while ((n = parsecmd(0)) != NODE_EOF) {
12842                 int i;
12843
12844                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12845                 if (n)
12846                         status = i;
12847                 popstackmark(&smark);
12848                 if (evalskip)
12849                         break;
12850         }
12851  out:
12852         popstackmark(&smark);
12853         popfile();
12854         stunalloc(s);
12855
12856         exception_handler = savehandler;
12857         if (ex)
12858                 longjmp(exception_handler->loc, ex);
12859
12860         return status;
12861 }
12862
12863 /*
12864  * The eval command.
12865  */
12866 static int FAST_FUNC
12867 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12868 {
12869         char *p;
12870         char *concat;
12871
12872         if (argv[1]) {
12873                 p = argv[1];
12874                 argv += 2;
12875                 if (argv[0]) {
12876                         STARTSTACKSTR(concat);
12877                         for (;;) {
12878                                 concat = stack_putstr(p, concat);
12879                                 p = *argv++;
12880                                 if (p == NULL)
12881                                         break;
12882                                 STPUTC(' ', concat);
12883                         }
12884                         STPUTC('\0', concat);
12885                         p = grabstackstr(concat);
12886                 }
12887                 return evalstring(p, flags & EV_TESTED);
12888         }
12889         return 0;
12890 }
12891
12892 /*
12893  * Read and execute commands.
12894  * "Top" is nonzero for the top level command loop;
12895  * it turns on prompting if the shell is interactive.
12896  */
12897 static int
12898 cmdloop(int top)
12899 {
12900         union node *n;
12901         struct stackmark smark;
12902         int inter;
12903         int status = 0;
12904         int numeof = 0;
12905
12906         TRACE(("cmdloop(%d) called\n", top));
12907         for (;;) {
12908                 int skip;
12909
12910                 setstackmark(&smark);
12911 #if JOBS
12912                 if (doing_jobctl)
12913                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12914 #endif
12915                 inter = 0;
12916                 if (iflag && top) {
12917                         inter++;
12918                         chkmail();
12919                 }
12920                 n = parsecmd(inter);
12921 #if DEBUG
12922                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12923                         showtree(n);
12924 #endif
12925                 if (n == NODE_EOF) {
12926                         if (!top || numeof >= 50)
12927                                 break;
12928                         if (!stoppedjobs()) {
12929                                 if (!Iflag)
12930                                         break;
12931                                 out2str("\nUse \"exit\" to leave shell.\n");
12932                         }
12933                         numeof++;
12934                 } else if (nflag == 0) {
12935                         int i;
12936
12937                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12938                         job_warning >>= 1;
12939                         numeof = 0;
12940                         i = evaltree(n, 0);
12941                         if (n)
12942                                 status = i;
12943                 }
12944                 popstackmark(&smark);
12945                 skip = evalskip;
12946
12947                 if (skip) {
12948                         evalskip &= ~SKIPFUNC;
12949                         break;
12950                 }
12951         }
12952         return status;
12953 }
12954
12955 /*
12956  * Take commands from a file.  To be compatible we should do a path
12957  * search for the file, which is necessary to find sub-commands.
12958  */
12959 static char *
12960 find_dot_file(char *name)
12961 {
12962         char *fullname;
12963         const char *path = pathval();
12964         struct stat statb;
12965
12966         /* don't try this for absolute or relative paths */
12967         if (strchr(name, '/'))
12968                 return name;
12969
12970         while ((fullname = path_advance(&path, name)) != NULL) {
12971                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12972                         /*
12973                          * Don't bother freeing here, since it will
12974                          * be freed by the caller.
12975                          */
12976                         return fullname;
12977                 }
12978                 if (fullname != name)
12979                         stunalloc(fullname);
12980         }
12981
12982         /* not found in the PATH */
12983         ash_msg_and_raise_error("%s: not found", name);
12984         /* NOTREACHED */
12985 }
12986
12987 static int FAST_FUNC
12988 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12989 {
12990         /* "false; . empty_file; echo $?" should print 0, not 1: */
12991         int status = 0;
12992         char *fullname;
12993         char **argv;
12994         char *args_need_save;
12995         volatile struct shparam saveparam;
12996
12997 //???
12998 //      struct strlist *sp;
12999 //      for (sp = cmdenviron; sp; sp = sp->next)
13000 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13001
13002         nextopt(nullstr); /* handle possible "--" */
13003         argv = argptr;
13004
13005         if (!argv[0]) {
13006                 /* bash says: "bash: .: filename argument required" */
13007                 return 2; /* bash compat */
13008         }
13009
13010         /* This aborts if file isn't found, which is POSIXly correct.
13011          * bash returns exitcode 1 instead.
13012          */
13013         fullname = find_dot_file(argv[0]);
13014         argv++;
13015         args_need_save = argv[0];
13016         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13017                 int argc;
13018                 saveparam = shellparam;
13019                 shellparam.malloced = 0;
13020                 argc = 1;
13021                 while (argv[argc])
13022                         argc++;
13023                 shellparam.nparam = argc;
13024                 shellparam.p = argv;
13025         };
13026
13027         /* This aborts if file can't be opened, which is POSIXly correct.
13028          * bash returns exitcode 1 instead.
13029          */
13030         setinputfile(fullname, INPUT_PUSH_FILE);
13031         commandname = fullname;
13032         status = cmdloop(0);
13033         popfile();
13034
13035         if (args_need_save) {
13036                 freeparam(&shellparam);
13037                 shellparam = saveparam;
13038         };
13039
13040         return status;
13041 }
13042
13043 static int FAST_FUNC
13044 exitcmd(int argc UNUSED_PARAM, char **argv)
13045 {
13046         if (stoppedjobs())
13047                 return 0;
13048         if (argv[1])
13049                 exitstatus = number(argv[1]);
13050         raise_exception(EXEXIT);
13051         /* NOTREACHED */
13052 }
13053
13054 /*
13055  * Read a file containing shell functions.
13056  */
13057 static void
13058 readcmdfile(char *name)
13059 {
13060         setinputfile(name, INPUT_PUSH_FILE);
13061         cmdloop(0);
13062         popfile();
13063 }
13064
13065
13066 /* ============ find_command inplementation */
13067
13068 /*
13069  * Resolve a command name.  If you change this routine, you may have to
13070  * change the shellexec routine as well.
13071  */
13072 static void
13073 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13074 {
13075         struct tblentry *cmdp;
13076         int idx;
13077         int prev;
13078         char *fullname;
13079         struct stat statb;
13080         int e;
13081         int updatetbl;
13082         struct builtincmd *bcmd;
13083
13084         /* If name contains a slash, don't use PATH or hash table */
13085         if (strchr(name, '/') != NULL) {
13086                 entry->u.index = -1;
13087                 if (act & DO_ABS) {
13088                         while (stat(name, &statb) < 0) {
13089 #ifdef SYSV
13090                                 if (errno == EINTR)
13091                                         continue;
13092 #endif
13093                                 entry->cmdtype = CMDUNKNOWN;
13094                                 return;
13095                         }
13096                 }
13097                 entry->cmdtype = CMDNORMAL;
13098                 return;
13099         }
13100
13101 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13102
13103         updatetbl = (path == pathval());
13104         if (!updatetbl) {
13105                 act |= DO_ALTPATH;
13106                 if (strstr(path, "%builtin") != NULL)
13107                         act |= DO_ALTBLTIN;
13108         }
13109
13110         /* If name is in the table, check answer will be ok */
13111         cmdp = cmdlookup(name, 0);
13112         if (cmdp != NULL) {
13113                 int bit;
13114
13115                 switch (cmdp->cmdtype) {
13116                 default:
13117 #if DEBUG
13118                         abort();
13119 #endif
13120                 case CMDNORMAL:
13121                         bit = DO_ALTPATH;
13122                         break;
13123                 case CMDFUNCTION:
13124                         bit = DO_NOFUNC;
13125                         break;
13126                 case CMDBUILTIN:
13127                         bit = DO_ALTBLTIN;
13128                         break;
13129                 }
13130                 if (act & bit) {
13131                         updatetbl = 0;
13132                         cmdp = NULL;
13133                 } else if (cmdp->rehash == 0)
13134                         /* if not invalidated by cd, we're done */
13135                         goto success;
13136         }
13137
13138         /* If %builtin not in path, check for builtin next */
13139         bcmd = find_builtin(name);
13140         if (bcmd) {
13141                 if (IS_BUILTIN_REGULAR(bcmd))
13142                         goto builtin_success;
13143                 if (act & DO_ALTPATH) {
13144                         if (!(act & DO_ALTBLTIN))
13145                                 goto builtin_success;
13146                 } else if (builtinloc <= 0) {
13147                         goto builtin_success;
13148                 }
13149         }
13150
13151 #if ENABLE_FEATURE_SH_STANDALONE
13152         {
13153                 int applet_no = find_applet_by_name(name);
13154                 if (applet_no >= 0) {
13155                         entry->cmdtype = CMDNORMAL;
13156                         entry->u.index = -2 - applet_no;
13157                         return;
13158                 }
13159         }
13160 #endif
13161
13162         /* We have to search path. */
13163         prev = -1;              /* where to start */
13164         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13165                 if (cmdp->cmdtype == CMDBUILTIN)
13166                         prev = builtinloc;
13167                 else
13168                         prev = cmdp->param.index;
13169         }
13170
13171         e = ENOENT;
13172         idx = -1;
13173  loop:
13174         while ((fullname = path_advance(&path, name)) != NULL) {
13175                 stunalloc(fullname);
13176                 /* NB: code below will still use fullname
13177                  * despite it being "unallocated" */
13178                 idx++;
13179                 if (pathopt) {
13180                         if (prefix(pathopt, "builtin")) {
13181                                 if (bcmd)
13182                                         goto builtin_success;
13183                                 continue;
13184                         }
13185                         if ((act & DO_NOFUNC)
13186                          || !prefix(pathopt, "func")
13187                         ) {     /* ignore unimplemented options */
13188                                 continue;
13189                         }
13190                 }
13191                 /* if rehash, don't redo absolute path names */
13192                 if (fullname[0] == '/' && idx <= prev) {
13193                         if (idx < prev)
13194                                 continue;
13195                         TRACE(("searchexec \"%s\": no change\n", name));
13196                         goto success;
13197                 }
13198                 while (stat(fullname, &statb) < 0) {
13199 #ifdef SYSV
13200                         if (errno == EINTR)
13201                                 continue;
13202 #endif
13203                         if (errno != ENOENT && errno != ENOTDIR)
13204                                 e = errno;
13205                         goto loop;
13206                 }
13207                 e = EACCES;     /* if we fail, this will be the error */
13208                 if (!S_ISREG(statb.st_mode))
13209                         continue;
13210                 if (pathopt) {          /* this is a %func directory */
13211                         stalloc(strlen(fullname) + 1);
13212                         /* NB: stalloc will return space pointed by fullname
13213                          * (because we don't have any intervening allocations
13214                          * between stunalloc above and this stalloc) */
13215                         readcmdfile(fullname);
13216                         cmdp = cmdlookup(name, 0);
13217                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13218                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13219                         stunalloc(fullname);
13220                         goto success;
13221                 }
13222                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13223                 if (!updatetbl) {
13224                         entry->cmdtype = CMDNORMAL;
13225                         entry->u.index = idx;
13226                         return;
13227                 }
13228                 INT_OFF;
13229                 cmdp = cmdlookup(name, 1);
13230                 cmdp->cmdtype = CMDNORMAL;
13231                 cmdp->param.index = idx;
13232                 INT_ON;
13233                 goto success;
13234         }
13235
13236         /* We failed.  If there was an entry for this command, delete it */
13237         if (cmdp && updatetbl)
13238                 delete_cmd_entry();
13239         if (act & DO_ERR) {
13240 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13241                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13242                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13243                         char *argv[3];
13244                         argv[0] = (char*) "command_not_found_handle";
13245                         argv[1] = name;
13246                         argv[2] = NULL;
13247                         evalfun(hookp->param.func, 2, argv, 0);
13248                         entry->cmdtype = CMDUNKNOWN;
13249                         return;
13250                 }
13251 #endif
13252                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13253         }
13254         entry->cmdtype = CMDUNKNOWN;
13255         return;
13256
13257  builtin_success:
13258         if (!updatetbl) {
13259                 entry->cmdtype = CMDBUILTIN;
13260                 entry->u.cmd = bcmd;
13261                 return;
13262         }
13263         INT_OFF;
13264         cmdp = cmdlookup(name, 1);
13265         cmdp->cmdtype = CMDBUILTIN;
13266         cmdp->param.cmd = bcmd;
13267         INT_ON;
13268  success:
13269         cmdp->rehash = 0;
13270         entry->cmdtype = cmdp->cmdtype;
13271         entry->u = cmdp->param;
13272 }
13273
13274
13275 /*
13276  * The trap builtin.
13277  */
13278 static int FAST_FUNC
13279 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13280 {
13281         char *action;
13282         char **ap;
13283         int signo, exitcode;
13284
13285         nextopt(nullstr);
13286         ap = argptr;
13287         if (!*ap) {
13288                 for (signo = 0; signo < NSIG; signo++) {
13289                         char *tr = trap_ptr[signo];
13290                         if (tr) {
13291                                 /* note: bash adds "SIG", but only if invoked
13292                                  * as "bash". If called as "sh", or if set -o posix,
13293                                  * then it prints short signal names.
13294                                  * We are printing short names: */
13295                                 out1fmt("trap -- %s %s\n",
13296                                                 single_quote(tr),
13297                                                 get_signame(signo));
13298                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13299                  * In this case, we will exit very soon, no need to free(). */
13300                                 /* if (trap_ptr != trap && tp[0]) */
13301                                 /*      free(tr); */
13302                         }
13303                 }
13304                 /*
13305                 if (trap_ptr != trap) {
13306                         free(trap_ptr);
13307                         trap_ptr = trap;
13308                 }
13309                 */
13310                 return 0;
13311         }
13312
13313         /* Why the second check?
13314          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13315          * In this case, NUM is signal no, not an action.
13316          */
13317         action = NULL;
13318         if (ap[1] && !is_number(ap[0]))
13319                 action = *ap++;
13320
13321         exitcode = 0;
13322         while (*ap) {
13323                 signo = get_signum(*ap);
13324                 if (signo < 0) {
13325                         /* Mimic bash message exactly */
13326                         ash_msg("%s: invalid signal specification", *ap);
13327                         exitcode = 1;
13328                         goto next;
13329                 }
13330                 INT_OFF;
13331                 if (action) {
13332                         if (LONE_DASH(action))
13333                                 action = NULL;
13334                         else {
13335                                 if (action[0]) /* not NULL and not "" and not "-" */
13336                                         may_have_traps = 1;
13337                                 action = ckstrdup(action);
13338                         }
13339                 }
13340                 free(trap[signo]);
13341                 trap[signo] = action;
13342                 if (signo != 0)
13343                         setsignal(signo);
13344                 INT_ON;
13345  next:
13346                 ap++;
13347         }
13348         return exitcode;
13349 }
13350
13351
13352 /* ============ Builtins */
13353
13354 #if ENABLE_ASH_HELP
13355 static int FAST_FUNC
13356 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13357 {
13358         unsigned col;
13359         unsigned i;
13360
13361         out1fmt(
13362                 "Built-in commands:\n"
13363                 "------------------\n");
13364         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13365                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13366                                         builtintab[i].name + 1);
13367                 if (col > 60) {
13368                         out1fmt("\n");
13369                         col = 0;
13370                 }
13371         }
13372 # if ENABLE_FEATURE_SH_STANDALONE
13373         {
13374                 const char *a = applet_names;
13375                 while (*a) {
13376                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13377                         if (col > 60) {
13378                                 out1fmt("\n");
13379                                 col = 0;
13380                         }
13381                         while (*a++ != '\0')
13382                                 continue;
13383                 }
13384         }
13385 # endif
13386         newline_and_flush(stdout);
13387         return EXIT_SUCCESS;
13388 }
13389 #endif
13390
13391 #if MAX_HISTORY
13392 static int FAST_FUNC
13393 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13394 {
13395         show_history(line_input_state);
13396         return EXIT_SUCCESS;
13397 }
13398 #endif
13399
13400 /*
13401  * The export and readonly commands.
13402  */
13403 static int FAST_FUNC
13404 exportcmd(int argc UNUSED_PARAM, char **argv)
13405 {
13406         struct var *vp;
13407         char *name;
13408         const char *p;
13409         char **aptr;
13410         char opt;
13411         int flag;
13412         int flag_off;
13413
13414         /* "readonly" in bash accepts, but ignores -n.
13415          * We do the same: it saves a conditional in nextopt's param.
13416          */
13417         flag_off = 0;
13418         while ((opt = nextopt("np")) != '\0') {
13419                 if (opt == 'n')
13420                         flag_off = VEXPORT;
13421         }
13422         flag = VEXPORT;
13423         if (argv[0][0] == 'r') {
13424                 flag = VREADONLY;
13425                 flag_off = 0; /* readonly ignores -n */
13426         }
13427         flag_off = ~flag_off;
13428
13429         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13430         {
13431                 aptr = argptr;
13432                 name = *aptr;
13433                 if (name) {
13434                         do {
13435                                 p = strchr(name, '=');
13436                                 if (p != NULL) {
13437                                         p++;
13438                                 } else {
13439                                         vp = *findvar(hashvar(name), name);
13440                                         if (vp) {
13441                                                 vp->flags = ((vp->flags | flag) & flag_off);
13442                                                 continue;
13443                                         }
13444                                 }
13445                                 setvar(name, p, (flag & flag_off));
13446                         } while ((name = *++aptr) != NULL);
13447                         return 0;
13448                 }
13449         }
13450
13451         /* No arguments. Show the list of exported or readonly vars.
13452          * -n is ignored.
13453          */
13454         showvars(argv[0], flag, 0);
13455         return 0;
13456 }
13457
13458 /*
13459  * Delete a function if it exists.
13460  */
13461 static void
13462 unsetfunc(const char *name)
13463 {
13464         struct tblentry *cmdp;
13465
13466         cmdp = cmdlookup(name, 0);
13467         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13468                 delete_cmd_entry();
13469 }
13470
13471 /*
13472  * The unset builtin command.  We unset the function before we unset the
13473  * variable to allow a function to be unset when there is a readonly variable
13474  * with the same name.
13475  */
13476 static int FAST_FUNC
13477 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13478 {
13479         char **ap;
13480         int i;
13481         int flag = 0;
13482
13483         while ((i = nextopt("vf")) != 0) {
13484                 flag = i;
13485         }
13486
13487         for (ap = argptr; *ap; ap++) {
13488                 if (flag != 'f') {
13489                         unsetvar(*ap);
13490                         continue;
13491                 }
13492                 if (flag != 'v')
13493                         unsetfunc(*ap);
13494         }
13495         return 0;
13496 }
13497
13498 static const unsigned char timescmd_str[] ALIGN1 = {
13499         ' ',  offsetof(struct tms, tms_utime),
13500         '\n', offsetof(struct tms, tms_stime),
13501         ' ',  offsetof(struct tms, tms_cutime),
13502         '\n', offsetof(struct tms, tms_cstime),
13503         0
13504 };
13505 static int FAST_FUNC
13506 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13507 {
13508         unsigned clk_tck;
13509         const unsigned char *p;
13510         struct tms buf;
13511
13512         clk_tck = bb_clk_tck();
13513
13514         times(&buf);
13515         p = timescmd_str;
13516         do {
13517                 unsigned sec, frac;
13518                 unsigned long t;
13519                 t = *(clock_t *)(((char *) &buf) + p[1]);
13520                 sec = t / clk_tck;
13521                 frac = t % clk_tck;
13522                 out1fmt("%um%u.%03us%c",
13523                         sec / 60, sec % 60,
13524                         (frac * 1000) / clk_tck,
13525                         p[0]);
13526                 p += 2;
13527         } while (*p);
13528
13529         return 0;
13530 }
13531
13532 #if ENABLE_FEATURE_SH_MATH
13533 /*
13534  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13535  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13536  *
13537  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13538  */
13539 static int FAST_FUNC
13540 letcmd(int argc UNUSED_PARAM, char **argv)
13541 {
13542         arith_t i;
13543
13544         argv++;
13545         if (!*argv)
13546                 ash_msg_and_raise_error("expression expected");
13547         do {
13548                 i = ash_arith(*argv);
13549         } while (*++argv);
13550
13551         return !i;
13552 }
13553 #endif
13554
13555 /*
13556  * The read builtin. Options:
13557  *      -r              Do not interpret '\' specially
13558  *      -s              Turn off echo (tty only)
13559  *      -n NCHARS       Read NCHARS max
13560  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13561  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13562  *      -u FD           Read from given FD instead of fd 0
13563  *      -d DELIM        End on DELIM char, not newline
13564  * This uses unbuffered input, which may be avoidable in some cases.
13565  * TODO: bash also has:
13566  *      -a ARRAY        Read into array[0],[1],etc
13567  *      -e              Use line editing (tty only)
13568  */
13569 static int FAST_FUNC
13570 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13571 {
13572         char *opt_n = NULL;
13573         char *opt_p = NULL;
13574         char *opt_t = NULL;
13575         char *opt_u = NULL;
13576         char *opt_d = NULL; /* optimized out if !BASH */
13577         int read_flags = 0;
13578         const char *r;
13579         int i;
13580
13581         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13582                 switch (i) {
13583                 case 'p':
13584                         opt_p = optionarg;
13585                         break;
13586                 case 'n':
13587                         opt_n = optionarg;
13588                         break;
13589                 case 's':
13590                         read_flags |= BUILTIN_READ_SILENT;
13591                         break;
13592                 case 't':
13593                         opt_t = optionarg;
13594                         break;
13595                 case 'r':
13596                         read_flags |= BUILTIN_READ_RAW;
13597                         break;
13598                 case 'u':
13599                         opt_u = optionarg;
13600                         break;
13601 #if BASH_READ_D
13602                 case 'd':
13603                         opt_d = optionarg;
13604                         break;
13605 #endif
13606                 default:
13607                         break;
13608                 }
13609         }
13610
13611         /* "read -s" needs to save/restore termios, can't allow ^C
13612          * to jump out of it.
13613          */
13614  again:
13615         INT_OFF;
13616         r = shell_builtin_read(setvar0,
13617                 argptr,
13618                 bltinlookup("IFS"), /* can be NULL */
13619                 read_flags,
13620                 opt_n,
13621                 opt_p,
13622                 opt_t,
13623                 opt_u,
13624                 opt_d
13625         );
13626         INT_ON;
13627
13628         if ((uintptr_t)r == 1 && errno == EINTR) {
13629                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13630                  * Correct behavior is to not exit "read"
13631                  */
13632                 if (pending_sig == 0)
13633                         goto again;
13634         }
13635
13636         if ((uintptr_t)r > 1)
13637                 ash_msg_and_raise_error(r);
13638
13639         return (uintptr_t)r;
13640 }
13641
13642 static int FAST_FUNC
13643 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13644 {
13645         static const char permuser[3] ALIGN1 = "ogu";
13646
13647         mode_t mask;
13648         int symbolic_mode = 0;
13649
13650         while (nextopt("S") != '\0') {
13651                 symbolic_mode = 1;
13652         }
13653
13654         INT_OFF;
13655         mask = umask(0);
13656         umask(mask);
13657         INT_ON;
13658
13659         if (*argptr == NULL) {
13660                 if (symbolic_mode) {
13661                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13662                         char *p = buf;
13663                         int i;
13664
13665                         i = 2;
13666                         for (;;) {
13667                                 *p++ = ',';
13668                                 *p++ = permuser[i];
13669                                 *p++ = '=';
13670                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13671                                 if (!(mask & 0400)) *p++ = 'r';
13672                                 if (!(mask & 0200)) *p++ = 'w';
13673                                 if (!(mask & 0100)) *p++ = 'x';
13674                                 mask <<= 3;
13675                                 if (--i < 0)
13676                                         break;
13677                         }
13678                         *p = '\0';
13679                         puts(buf + 1);
13680                 } else {
13681                         out1fmt("%04o\n", mask);
13682                 }
13683         } else {
13684                 char *modestr = *argptr;
13685                 /* numeric umasks are taken as-is */
13686                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13687                 if (!isdigit(modestr[0]))
13688                         mask ^= 0777;
13689                 mask = bb_parse_mode(modestr, mask);
13690                 if ((unsigned)mask > 0777) {
13691                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13692                 }
13693                 if (!isdigit(modestr[0]))
13694                         mask ^= 0777;
13695                 umask(mask);
13696         }
13697         return 0;
13698 }
13699
13700 static int FAST_FUNC
13701 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13702 {
13703         return shell_builtin_ulimit(argv);
13704 }
13705
13706 /* ============ main() and helpers */
13707
13708 /*
13709  * Called to exit the shell.
13710  */
13711 static void
13712 exitshell(void)
13713 {
13714         struct jmploc loc;
13715         char *p;
13716         int status;
13717
13718 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13719         save_history(line_input_state);
13720 #endif
13721         status = exitstatus;
13722         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13723         if (setjmp(loc.loc)) {
13724                 if (exception_type == EXEXIT)
13725                         status = exitstatus;
13726                 goto out;
13727         }
13728         exception_handler = &loc;
13729         p = trap[0];
13730         if (p) {
13731                 trap[0] = NULL;
13732                 evalskip = 0;
13733                 evalstring(p, 0);
13734                 /*free(p); - we'll exit soon */
13735         }
13736  out:
13737         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13738          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13739          */
13740         setjobctl(0);
13741         flush_stdout_stderr();
13742         _exit(status);
13743         /* NOTREACHED */
13744 }
13745
13746 /* Don't inline: conserve stack of caller from having our locals too */
13747 static NOINLINE void
13748 init(void)
13749 {
13750         /* we will never free this */
13751         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13752         basepf.linno = 1;
13753
13754         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13755         setsignal(SIGCHLD);
13756
13757         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13758          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13759          */
13760         signal(SIGHUP, SIG_DFL);
13761
13762         {
13763                 char **envp;
13764                 const char *p;
13765
13766                 initvar();
13767                 for (envp = environ; envp && *envp; envp++) {
13768 /* Used to have
13769  *                      p = endofname(*envp);
13770  *                      if (p != *envp && *p == '=') {
13771  * here to weed out badly-named variables, but this breaks
13772  * scenarios where people do want them passed to children:
13773  * import os
13774  * os.environ["test-test"]="test"
13775  * if os.fork() == 0:
13776  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13777  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13778  */
13779                         if (strchr(*envp, '=')) {
13780                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13781                         }
13782                 }
13783
13784                 setvareq((char*)defoptindvar, VTEXTFIXED);
13785
13786                 setvar0("PPID", utoa(getppid()));
13787 #if BASH_SHLVL_VAR
13788                 p = lookupvar("SHLVL");
13789                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13790 #endif
13791 #if BASH_HOSTNAME_VAR
13792                 if (!lookupvar("HOSTNAME")) {
13793                         struct utsname uts;
13794                         uname(&uts);
13795                         setvar0("HOSTNAME", uts.nodename);
13796                 }
13797 #endif
13798                 p = lookupvar("PWD");
13799                 if (p) {
13800                         struct stat st1, st2;
13801                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13802                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13803                         ) {
13804                                 p = NULL;
13805                         }
13806                 }
13807                 setpwd(p, 0);
13808         }
13809 }
13810
13811
13812 //usage:#define ash_trivial_usage
13813 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13814 //usage:#define ash_full_usage "\n\n"
13815 //usage:        "Unix shell interpreter"
13816
13817 /*
13818  * Process the shell command line arguments.
13819  */
13820 static int
13821 procargs(char **argv)
13822 {
13823         int i;
13824         const char *xminusc;
13825         char **xargv;
13826         int login_sh;
13827
13828         xargv = argv;
13829         login_sh = xargv[0] && xargv[0][0] == '-';
13830         arg0 = xargv[0];
13831         /* if (xargv[0]) - mmm, this is always true! */
13832                 xargv++;
13833         for (i = 0; i < NOPTS; i++)
13834                 optlist[i] = 2;
13835         argptr = xargv;
13836         if (options(/*cmdline:*/ 1, &login_sh)) {
13837                 /* it already printed err message */
13838                 raise_exception(EXERROR);
13839         }
13840         xargv = argptr;
13841         xminusc = minusc;
13842         if (*xargv == NULL) {
13843                 if (xminusc)
13844                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13845                 sflag = 1;
13846         }
13847         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13848                 iflag = 1;
13849         if (mflag == 2)
13850                 mflag = iflag;
13851         for (i = 0; i < NOPTS; i++)
13852                 if (optlist[i] == 2)
13853                         optlist[i] = 0;
13854 #if DEBUG == 2
13855         debug = 1;
13856 #endif
13857         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13858         if (xminusc) {
13859                 minusc = *xargv++;
13860                 if (*xargv)
13861                         goto setarg0;
13862         } else if (!sflag) {
13863                 setinputfile(*xargv, 0);
13864  setarg0:
13865                 arg0 = *xargv++;
13866                 commandname = arg0;
13867         }
13868
13869         shellparam.p = xargv;
13870 #if ENABLE_ASH_GETOPTS
13871         shellparam.optind = 1;
13872         shellparam.optoff = -1;
13873 #endif
13874         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13875         while (*xargv) {
13876                 shellparam.nparam++;
13877                 xargv++;
13878         }
13879         optschanged();
13880
13881         return login_sh;
13882 }
13883
13884 /*
13885  * Read /etc/profile, ~/.profile, $ENV.
13886  */
13887 static void
13888 read_profile(const char *name)
13889 {
13890         name = expandstr(name, DQSYNTAX);
13891         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13892                 return;
13893         cmdloop(0);
13894         popfile();
13895 }
13896
13897 /*
13898  * This routine is called when an error or an interrupt occurs in an
13899  * interactive shell and control is returned to the main command loop.
13900  * (In dash, this function is auto-generated by build machinery).
13901  */
13902 static void
13903 reset(void)
13904 {
13905         /* from eval.c: */
13906         evalskip = 0;
13907         loopnest = 0;
13908
13909         /* from expand.c: */
13910         ifsfree();
13911
13912         /* from input.c: */
13913         g_parsefile->left_in_buffer = 0;
13914         g_parsefile->left_in_line = 0;      /* clear input buffer */
13915         popallfiles();
13916
13917         /* from redir.c: */
13918         unwindredir(NULL);
13919
13920         /* from var.c: */
13921         unwindlocalvars(NULL);
13922 }
13923
13924 #if PROFILE
13925 static short profile_buf[16384];
13926 extern int etext();
13927 #endif
13928
13929 /*
13930  * Main routine.  We initialize things, parse the arguments, execute
13931  * profiles if we're a login shell, and then call cmdloop to execute
13932  * commands.  The setjmp call sets up the location to jump to when an
13933  * exception occurs.  When an exception occurs the variable "state"
13934  * is used to figure out how far we had gotten.
13935  */
13936 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13937 int ash_main(int argc UNUSED_PARAM, char **argv)
13938 {
13939         volatile smallint state;
13940         struct jmploc jmploc;
13941         struct stackmark smark;
13942         int login_sh;
13943
13944         /* Initialize global data */
13945         INIT_G_misc();
13946         INIT_G_memstack();
13947         INIT_G_var();
13948 #if ENABLE_ASH_ALIAS
13949         INIT_G_alias();
13950 #endif
13951         INIT_G_cmdtable();
13952
13953 #if PROFILE
13954         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13955 #endif
13956
13957 #if ENABLE_FEATURE_EDITING
13958         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13959 #endif
13960         state = 0;
13961         if (setjmp(jmploc.loc)) {
13962                 smallint e;
13963                 smallint s;
13964
13965                 reset();
13966
13967                 e = exception_type;
13968                 s = state;
13969                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13970                         exitshell();
13971                 }
13972                 if (e == EXINT) {
13973                         newline_and_flush(stderr);
13974                 }
13975
13976                 popstackmark(&smark);
13977                 FORCE_INT_ON; /* enable interrupts */
13978                 if (s == 1)
13979                         goto state1;
13980                 if (s == 2)
13981                         goto state2;
13982                 if (s == 3)
13983                         goto state3;
13984                 goto state4;
13985         }
13986         exception_handler = &jmploc;
13987         rootpid = getpid();
13988
13989         init();
13990         setstackmark(&smark);
13991         login_sh = procargs(argv);
13992 #if DEBUG
13993         TRACE(("Shell args: "));
13994         trace_puts_args(argv);
13995 #endif
13996
13997         if (login_sh) {
13998                 const char *hp;
13999
14000                 state = 1;
14001                 read_profile("/etc/profile");
14002  state1:
14003                 state = 2;
14004                 hp = lookupvar("HOME");
14005                 if (hp)
14006                         read_profile("$HOME/.profile");
14007         }
14008  state2:
14009         state = 3;
14010         if (
14011 #ifndef linux
14012          getuid() == geteuid() && getgid() == getegid() &&
14013 #endif
14014          iflag
14015         ) {
14016                 const char *shinit = lookupvar("ENV");
14017                 if (shinit != NULL && *shinit != '\0')
14018                         read_profile(shinit);
14019         }
14020         popstackmark(&smark);
14021  state3:
14022         state = 4;
14023         if (minusc) {
14024                 /* evalstring pushes parsefile stack.
14025                  * Ensure we don't falsely claim that 0 (stdin)
14026                  * is one of stacked source fds.
14027                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14028                 // if (!sflag) g_parsefile->pf_fd = -1;
14029                 // ^^ not necessary since now we special-case fd 0
14030                 // in save_fd_on_redirect()
14031                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14032         }
14033
14034         if (sflag || minusc == NULL) {
14035 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14036                 if (iflag) {
14037                         const char *hp = lookupvar("HISTFILE");
14038                         if (!hp) {
14039                                 hp = lookupvar("HOME");
14040                                 if (hp) {
14041                                         INT_OFF;
14042                                         hp = concat_path_file(hp, ".ash_history");
14043                                         setvar0("HISTFILE", hp);
14044                                         free((char*)hp);
14045                                         INT_ON;
14046                                         hp = lookupvar("HISTFILE");
14047                                 }
14048                         }
14049                         if (hp)
14050                                 line_input_state->hist_file = hp;
14051 # if ENABLE_FEATURE_SH_HISTFILESIZE
14052                         hp = lookupvar("HISTFILESIZE");
14053                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14054 # endif
14055                 }
14056 #endif
14057  state4: /* XXX ??? - why isn't this before the "if" statement */
14058                 cmdloop(1);
14059         }
14060 #if PROFILE
14061         monitor(0);
14062 #endif
14063 #ifdef GPROF
14064         {
14065                 extern void _mcleanup(void);
14066                 _mcleanup();
14067         }
14068 #endif
14069         TRACE(("End of main reached\n"));
14070         exitshell();
14071         /* NOTREACHED */
14072 }
14073
14074
14075 /*-
14076  * Copyright (c) 1989, 1991, 1993, 1994
14077  *      The Regents of the University of California.  All rights reserved.
14078  *
14079  * This code is derived from software contributed to Berkeley by
14080  * Kenneth Almquist.
14081  *
14082  * Redistribution and use in source and binary forms, with or without
14083  * modification, are permitted provided that the following conditions
14084  * are met:
14085  * 1. Redistributions of source code must retain the above copyright
14086  *    notice, this list of conditions and the following disclaimer.
14087  * 2. Redistributions in binary form must reproduce the above copyright
14088  *    notice, this list of conditions and the following disclaimer in the
14089  *    documentation and/or other materials provided with the distribution.
14090  * 3. Neither the name of the University nor the names of its contributors
14091  *    may be used to endorse or promote products derived from this software
14092  *    without specific prior written permission.
14093  *
14094  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14095  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14096  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14097  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14098  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14099  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14100  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14101  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14102  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14103  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14104  * SUCH DAMAGE.
14105  */