ash: when cd fails, say why
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
192 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
193 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
194
195 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
196 /* Bionic at least up to version 24 has no glob() */
197 # undef  ENABLE_ASH_INTERNAL_GLOB
198 # define ENABLE_ASH_INTERNAL_GLOB 1
199 #endif
200
201 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
202 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
203 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
204 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
205 # error glob() should unbackslash them and match. uClibc does not unbackslash,
206 # error fails to match dirname, subsequently not expanding <pattern> in it.
207 // Testcase:
208 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
209 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
210 #endif
211
212 #if !ENABLE_ASH_INTERNAL_GLOB
213 # include <glob.h>
214 #endif
215
216 #include "unicode.h"
217 #include "shell_common.h"
218 #if ENABLE_FEATURE_SH_MATH
219 # include "math.h"
220 #else
221 typedef long arith_t;
222 # define ARITH_FMT "%ld"
223 #endif
224 #if ENABLE_ASH_RANDOM_SUPPORT
225 # include "random.h"
226 #else
227 # define CLEAR_RANDOM_T(rnd) ((void)0)
228 #endif
229
230 #include "NUM_APPLETS.h"
231 #if NUM_APPLETS == 1
232 /* STANDALONE does not make sense, and won't compile */
233 # undef CONFIG_FEATURE_SH_STANDALONE
234 # undef ENABLE_FEATURE_SH_STANDALONE
235 # undef IF_FEATURE_SH_STANDALONE
236 # undef IF_NOT_FEATURE_SH_STANDALONE
237 # define ENABLE_FEATURE_SH_STANDALONE 0
238 # define IF_FEATURE_SH_STANDALONE(...)
239 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
240 #endif
241
242 #ifndef PIPE_BUF
243 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
244 #endif
245
246 #if !BB_MMU
247 # error "Do not even bother, ash will not run on NOMMU machine"
248 #endif
249
250
251 /* ============ Hash table sizes. Configurable. */
252
253 #define VTABSIZE 39
254 #define ATABSIZE 39
255 #define CMDTABLESIZE 31         /* should be prime */
256
257
258 /* ============ Shell options */
259
260 static const char *const optletters_optnames[] = {
261         "e"   "errexit",
262         "f"   "noglob",
263         "I"   "ignoreeof",
264         "i"   "interactive",
265         "m"   "monitor",
266         "n"   "noexec",
267         "s"   "stdin",
268         "x"   "xtrace",
269         "v"   "verbose",
270         "C"   "noclobber",
271         "a"   "allexport",
272         "b"   "notify",
273         "u"   "nounset",
274         "\0"  "vi"
275 #if BASH_PIPEFAIL
276         ,"\0"  "pipefail"
277 #endif
278 #if DEBUG
279         ,"\0"  "nolog"
280         ,"\0"  "debug"
281 #endif
282 };
283
284 #define optletters(n)  optletters_optnames[n][0]
285 #define optnames(n)   (optletters_optnames[n] + 1)
286
287 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
288
289
290 /* ============ Misc data */
291
292 #define msg_illnum "Illegal number: %s"
293
294 /*
295  * We enclose jmp_buf in a structure so that we can declare pointers to
296  * jump locations.  The global variable handler contains the location to
297  * jump to when an exception occurs, and the global variable exception_type
298  * contains a code identifying the exception.  To implement nested
299  * exception handlers, the user should save the value of handler on entry
300  * to an inner scope, set handler to point to a jmploc structure for the
301  * inner scope, and restore handler on exit from the scope.
302  */
303 struct jmploc {
304         jmp_buf loc;
305 };
306
307 struct globals_misc {
308         uint8_t exitstatus;     /* exit status of last command */
309         uint8_t back_exitstatus;/* exit status of backquoted command */
310         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
311         int rootpid;            /* pid of main shell */
312         /* shell level: 0 for the main shell, 1 for its children, and so on */
313         int shlvl;
314 #define rootshell (!shlvl)
315         char *minusc;  /* argument to -c option */
316
317         char *curdir; // = nullstr;     /* current working directory */
318         char *physdir; // = nullstr;    /* physical working directory */
319
320         char *arg0; /* value of $0 */
321
322         struct jmploc *exception_handler;
323
324         volatile int suppress_int; /* counter */
325         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
326         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
327         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
328         smallint exception_type; /* kind of exception (0..5) */
329         /* exceptions */
330 #define EXINT 0         /* SIGINT received */
331 #define EXERROR 1       /* a generic error */
332 #define EXEXIT 4        /* exit the shell */
333
334         char nullstr[1];        /* zero length string */
335
336         char optlist[NOPTS];
337 #define eflag optlist[0]
338 #define fflag optlist[1]
339 #define Iflag optlist[2]
340 #define iflag optlist[3]
341 #define mflag optlist[4]
342 #define nflag optlist[5]
343 #define sflag optlist[6]
344 #define xflag optlist[7]
345 #define vflag optlist[8]
346 #define Cflag optlist[9]
347 #define aflag optlist[10]
348 #define bflag optlist[11]
349 #define uflag optlist[12]
350 #define viflag optlist[13]
351 #if BASH_PIPEFAIL
352 # define pipefail optlist[14]
353 #else
354 # define pipefail 0
355 #endif
356 #if DEBUG
357 # define nolog optlist[14 + BASH_PIPEFAIL]
358 # define debug optlist[15 + BASH_PIPEFAIL]
359 #endif
360
361         /* trap handler commands */
362         /*
363          * Sigmode records the current value of the signal handlers for the various
364          * modes.  A value of zero means that the current handler is not known.
365          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
366          */
367         char sigmode[NSIG - 1];
368 #define S_DFL      1            /* default signal handling (SIG_DFL) */
369 #define S_CATCH    2            /* signal is caught */
370 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
371 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
372
373         /* indicates specified signal received */
374         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
375         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
376         char *trap[NSIG];
377         char **trap_ptr;        /* used only by "trap hack" */
378
379         /* Rarely referenced stuff */
380 #if ENABLE_ASH_RANDOM_SUPPORT
381         random_t random_gen;
382 #endif
383         pid_t backgndpid;        /* pid of last background process */
384 };
385 extern struct globals_misc *const ash_ptr_to_globals_misc;
386 #define G_misc (*ash_ptr_to_globals_misc)
387 #define exitstatus        (G_misc.exitstatus )
388 #define back_exitstatus   (G_misc.back_exitstatus )
389 #define job_warning       (G_misc.job_warning)
390 #define rootpid     (G_misc.rootpid    )
391 #define shlvl       (G_misc.shlvl      )
392 #define minusc      (G_misc.minusc     )
393 #define curdir      (G_misc.curdir     )
394 #define physdir     (G_misc.physdir    )
395 #define arg0        (G_misc.arg0       )
396 #define exception_handler (G_misc.exception_handler)
397 #define exception_type    (G_misc.exception_type   )
398 #define suppress_int      (G_misc.suppress_int     )
399 #define pending_int       (G_misc.pending_int      )
400 #define got_sigchld       (G_misc.got_sigchld      )
401 #define pending_sig       (G_misc.pending_sig      )
402 #define nullstr     (G_misc.nullstr    )
403 #define optlist     (G_misc.optlist    )
404 #define sigmode     (G_misc.sigmode    )
405 #define gotsig      (G_misc.gotsig     )
406 #define may_have_traps    (G_misc.may_have_traps   )
407 #define trap        (G_misc.trap       )
408 #define trap_ptr    (G_misc.trap_ptr   )
409 #define random_gen  (G_misc.random_gen )
410 #define backgndpid  (G_misc.backgndpid )
411 #define INIT_G_misc() do { \
412         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
413         barrier(); \
414         curdir = nullstr; \
415         physdir = nullstr; \
416         trap_ptr = trap; \
417 } while (0)
418
419
420 /* ============ DEBUG */
421 #if DEBUG
422 static void trace_printf(const char *fmt, ...);
423 static void trace_vprintf(const char *fmt, va_list va);
424 # define TRACE(param)    trace_printf param
425 # define TRACEV(param)   trace_vprintf param
426 # define close(fd) do { \
427         int dfd = (fd); \
428         if (close(dfd) < 0) \
429                 bb_error_msg("bug on %d: closing %d(0x%x)", \
430                         __LINE__, dfd, dfd); \
431 } while (0)
432 #else
433 # define TRACE(param)
434 # define TRACEV(param)
435 #endif
436
437
438 /* ============ Utility functions */
439 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
440 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
441
442 static int
443 isdigit_str9(const char *str)
444 {
445         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
446         while (--maxlen && isdigit(*str))
447                 str++;
448         return (*str == '\0');
449 }
450
451 static const char *
452 var_end(const char *var)
453 {
454         while (*var)
455                 if (*var++ == '=')
456                         break;
457         return var;
458 }
459
460
461 /* ============ Interrupts / exceptions */
462
463 static void exitshell(void) NORETURN;
464
465 /*
466  * These macros allow the user to suspend the handling of interrupt signals
467  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
468  * much more efficient and portable.  (But hacking the kernel is so much
469  * more fun than worrying about efficiency and portability. :-))
470  */
471 #if DEBUG_INTONOFF
472 # define INT_OFF do { \
473         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
474         suppress_int++; \
475         barrier(); \
476 } while (0)
477 #else
478 # define INT_OFF do { \
479         suppress_int++; \
480         barrier(); \
481 } while (0)
482 #endif
483
484 /*
485  * Called to raise an exception.  Since C doesn't include exceptions, we
486  * just do a longjmp to the exception handler.  The type of exception is
487  * stored in the global variable "exception_type".
488  */
489 static void raise_exception(int) NORETURN;
490 static void
491 raise_exception(int e)
492 {
493 #if DEBUG
494         if (exception_handler == NULL)
495                 abort();
496 #endif
497         INT_OFF;
498         exception_type = e;
499         longjmp(exception_handler->loc, 1);
500 }
501 #if DEBUG
502 #define raise_exception(e) do { \
503         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
504         raise_exception(e); \
505 } while (0)
506 #endif
507
508 /*
509  * Called when a SIGINT is received.  (If the user specifies
510  * that SIGINT is to be trapped or ignored using the trap builtin, then
511  * this routine is not called.)  Suppressint is nonzero when interrupts
512  * are held using the INT_OFF macro.  (The test for iflag is just
513  * defensive programming.)
514  */
515 static void raise_interrupt(void) NORETURN;
516 static void
517 raise_interrupt(void)
518 {
519         pending_int = 0;
520         /* Signal is not automatically unmasked after it is raised,
521          * do it ourself - unmask all signals */
522         sigprocmask_allsigs(SIG_UNBLOCK);
523         /* pending_sig = 0; - now done in signal_handler() */
524
525         if (!(rootshell && iflag)) {
526                 /* Kill ourself with SIGINT */
527                 signal(SIGINT, SIG_DFL);
528                 raise(SIGINT);
529         }
530         /* bash: ^C even on empty command line sets $? */
531         exitstatus = SIGINT + 128;
532         raise_exception(EXINT);
533         /* NOTREACHED */
534 }
535 #if DEBUG
536 #define raise_interrupt() do { \
537         TRACE(("raising interrupt on line %d\n", __LINE__)); \
538         raise_interrupt(); \
539 } while (0)
540 #endif
541
542 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
543 int_on(void)
544 {
545         barrier();
546         if (--suppress_int == 0 && pending_int) {
547                 raise_interrupt();
548         }
549 }
550 #if DEBUG_INTONOFF
551 # define INT_ON do { \
552         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
553         int_on(); \
554 } while (0)
555 #else
556 # define INT_ON int_on()
557 #endif
558 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
559 force_int_on(void)
560 {
561         barrier();
562         suppress_int = 0;
563         if (pending_int)
564                 raise_interrupt();
565 }
566 #define FORCE_INT_ON force_int_on()
567
568 #define SAVE_INT(v) ((v) = suppress_int)
569
570 #define RESTORE_INT(v) do { \
571         barrier(); \
572         suppress_int = (v); \
573         if (suppress_int == 0 && pending_int) \
574                 raise_interrupt(); \
575 } while (0)
576
577
578 /* ============ Stdout/stderr output */
579
580 static void
581 outstr(const char *p, FILE *file)
582 {
583         INT_OFF;
584         fputs(p, file);
585         INT_ON;
586 }
587
588 static void
589 flush_stdout_stderr(void)
590 {
591         INT_OFF;
592         fflush_all();
593         INT_ON;
594 }
595
596 /* Was called outcslow(c,FILE*), but c was always '\n' */
597 static void
598 newline_and_flush(FILE *dest)
599 {
600         INT_OFF;
601         putc('\n', dest);
602         fflush(dest);
603         INT_ON;
604 }
605
606 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
607 static int
608 out1fmt(const char *fmt, ...)
609 {
610         va_list ap;
611         int r;
612
613         INT_OFF;
614         va_start(ap, fmt);
615         r = vprintf(fmt, ap);
616         va_end(ap);
617         INT_ON;
618         return r;
619 }
620
621 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
622 static int
623 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
624 {
625         va_list ap;
626         int ret;
627
628         INT_OFF;
629         va_start(ap, fmt);
630         ret = vsnprintf(outbuf, length, fmt, ap);
631         va_end(ap);
632         INT_ON;
633         return ret;
634 }
635
636 static void
637 out1str(const char *p)
638 {
639         outstr(p, stdout);
640 }
641
642 static void
643 out2str(const char *p)
644 {
645         outstr(p, stderr);
646         flush_stdout_stderr();
647 }
648
649
650 /* ============ Parser structures */
651
652 /* control characters in argument strings */
653 #define CTL_FIRST CTLESC
654 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
655 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
656 #define CTLENDVAR    ((unsigned char)'\203')
657 #define CTLBACKQ     ((unsigned char)'\204')
658 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
659 #define CTLENDARI    ((unsigned char)'\207')
660 #define CTLQUOTEMARK ((unsigned char)'\210')
661 #define CTL_LAST CTLQUOTEMARK
662
663 /* variable substitution byte (follows CTLVAR) */
664 #define VSTYPE  0x0f            /* type of variable substitution */
665 #define VSNUL   0x10            /* colon--treat the empty string as unset */
666
667 /* values of VSTYPE field */
668 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
669 #define VSMINUS         0x2     /* ${var-text} */
670 #define VSPLUS          0x3     /* ${var+text} */
671 #define VSQUESTION      0x4     /* ${var?message} */
672 #define VSASSIGN        0x5     /* ${var=text} */
673 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
674 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
675 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
676 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
677 #define VSLENGTH        0xa     /* ${#var} */
678 #if BASH_SUBSTR
679 #define VSSUBSTR        0xc     /* ${var:position:length} */
680 #endif
681 #if BASH_PATTERN_SUBST
682 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
683 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
684 #endif
685
686 static const char dolatstr[] ALIGN1 = {
687         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
688 };
689 #define DOLATSTRLEN 6
690
691 #define NCMD      0
692 #define NPIPE     1
693 #define NREDIR    2
694 #define NBACKGND  3
695 #define NSUBSHELL 4
696 #define NAND      5
697 #define NOR       6
698 #define NSEMI     7
699 #define NIF       8
700 #define NWHILE    9
701 #define NUNTIL   10
702 #define NFOR     11
703 #define NCASE    12
704 #define NCLIST   13
705 #define NDEFUN   14
706 #define NARG     15
707 #define NTO      16
708 #if BASH_REDIR_OUTPUT
709 #define NTO2     17
710 #endif
711 #define NCLOBBER 18
712 #define NFROM    19
713 #define NFROMTO  20
714 #define NAPPEND  21
715 #define NTOFD    22
716 #define NFROMFD  23
717 #define NHERE    24
718 #define NXHERE   25
719 #define NNOT     26
720 #define N_NUMBER 27
721
722 union node;
723
724 struct ncmd {
725         smallint type; /* Nxxxx */
726         union node *assign;
727         union node *args;
728         union node *redirect;
729 };
730
731 struct npipe {
732         smallint type;
733         smallint pipe_backgnd;
734         struct nodelist *cmdlist;
735 };
736
737 struct nredir {
738         smallint type;
739         union node *n;
740         union node *redirect;
741 };
742
743 struct nbinary {
744         smallint type;
745         union node *ch1;
746         union node *ch2;
747 };
748
749 struct nif {
750         smallint type;
751         union node *test;
752         union node *ifpart;
753         union node *elsepart;
754 };
755
756 struct nfor {
757         smallint type;
758         union node *args;
759         union node *body;
760         char *var;
761 };
762
763 struct ncase {
764         smallint type;
765         union node *expr;
766         union node *cases;
767 };
768
769 struct nclist {
770         smallint type;
771         union node *next;
772         union node *pattern;
773         union node *body;
774 };
775
776 struct narg {
777         smallint type;
778         union node *next;
779         char *text;
780         struct nodelist *backquote;
781 };
782
783 /* nfile and ndup layout must match!
784  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
785  * that it is actually NTO2 (>&file), and change its type.
786  */
787 struct nfile {
788         smallint type;
789         union node *next;
790         int fd;
791         int _unused_dupfd;
792         union node *fname;
793         char *expfname;
794 };
795
796 struct ndup {
797         smallint type;
798         union node *next;
799         int fd;
800         int dupfd;
801         union node *vname;
802         char *_unused_expfname;
803 };
804
805 struct nhere {
806         smallint type;
807         union node *next;
808         int fd;
809         union node *doc;
810 };
811
812 struct nnot {
813         smallint type;
814         union node *com;
815 };
816
817 union node {
818         smallint type;
819         struct ncmd ncmd;
820         struct npipe npipe;
821         struct nredir nredir;
822         struct nbinary nbinary;
823         struct nif nif;
824         struct nfor nfor;
825         struct ncase ncase;
826         struct nclist nclist;
827         struct narg narg;
828         struct nfile nfile;
829         struct ndup ndup;
830         struct nhere nhere;
831         struct nnot nnot;
832 };
833
834 /*
835  * NODE_EOF is returned by parsecmd when it encounters an end of file.
836  * It must be distinct from NULL.
837  */
838 #define NODE_EOF ((union node *) -1L)
839
840 struct nodelist {
841         struct nodelist *next;
842         union node *n;
843 };
844
845 struct funcnode {
846         int count;
847         union node n;
848 };
849
850 /*
851  * Free a parse tree.
852  */
853 static void
854 freefunc(struct funcnode *f)
855 {
856         if (f && --f->count < 0)
857                 free(f);
858 }
859
860
861 /* ============ Debugging output */
862
863 #if DEBUG
864
865 static FILE *tracefile;
866
867 static void
868 trace_printf(const char *fmt, ...)
869 {
870         va_list va;
871
872         if (debug != 1)
873                 return;
874         if (DEBUG_TIME)
875                 fprintf(tracefile, "%u ", (int) time(NULL));
876         if (DEBUG_PID)
877                 fprintf(tracefile, "[%u] ", (int) getpid());
878         if (DEBUG_SIG)
879                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
880         va_start(va, fmt);
881         vfprintf(tracefile, fmt, va);
882         va_end(va);
883 }
884
885 static void
886 trace_vprintf(const char *fmt, va_list va)
887 {
888         if (debug != 1)
889                 return;
890         vfprintf(tracefile, fmt, va);
891         fprintf(tracefile, "\n");
892 }
893
894 static void
895 trace_puts(const char *s)
896 {
897         if (debug != 1)
898                 return;
899         fputs(s, tracefile);
900 }
901
902 static void
903 trace_puts_quoted(char *s)
904 {
905         char *p;
906         char c;
907
908         if (debug != 1)
909                 return;
910         putc('"', tracefile);
911         for (p = s; *p; p++) {
912                 switch ((unsigned char)*p) {
913                 case '\n': c = 'n'; goto backslash;
914                 case '\t': c = 't'; goto backslash;
915                 case '\r': c = 'r'; goto backslash;
916                 case '\"': c = '\"'; goto backslash;
917                 case '\\': c = '\\'; goto backslash;
918                 case CTLESC: c = 'e'; goto backslash;
919                 case CTLVAR: c = 'v'; goto backslash;
920                 case CTLBACKQ: c = 'q'; goto backslash;
921  backslash:
922                         putc('\\', tracefile);
923                         putc(c, tracefile);
924                         break;
925                 default:
926                         if (*p >= ' ' && *p <= '~')
927                                 putc(*p, tracefile);
928                         else {
929                                 putc('\\', tracefile);
930                                 putc((*p >> 6) & 03, tracefile);
931                                 putc((*p >> 3) & 07, tracefile);
932                                 putc(*p & 07, tracefile);
933                         }
934                         break;
935                 }
936         }
937         putc('"', tracefile);
938 }
939
940 static void
941 trace_puts_args(char **ap)
942 {
943         if (debug != 1)
944                 return;
945         if (!*ap)
946                 return;
947         while (1) {
948                 trace_puts_quoted(*ap);
949                 if (!*++ap) {
950                         putc('\n', tracefile);
951                         break;
952                 }
953                 putc(' ', tracefile);
954         }
955 }
956
957 static void
958 opentrace(void)
959 {
960         char s[100];
961 #ifdef O_APPEND
962         int flags;
963 #endif
964
965         if (debug != 1) {
966                 if (tracefile)
967                         fflush(tracefile);
968                 /* leave open because libedit might be using it */
969                 return;
970         }
971         strcpy(s, "./trace");
972         if (tracefile) {
973                 if (!freopen(s, "a", tracefile)) {
974                         fprintf(stderr, "Can't re-open %s\n", s);
975                         debug = 0;
976                         return;
977                 }
978         } else {
979                 tracefile = fopen(s, "a");
980                 if (tracefile == NULL) {
981                         fprintf(stderr, "Can't open %s\n", s);
982                         debug = 0;
983                         return;
984                 }
985         }
986 #ifdef O_APPEND
987         flags = fcntl(fileno(tracefile), F_GETFL);
988         if (flags >= 0)
989                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
990 #endif
991         setlinebuf(tracefile);
992         fputs("\nTracing started.\n", tracefile);
993 }
994
995 static void
996 indent(int amount, char *pfx, FILE *fp)
997 {
998         int i;
999
1000         for (i = 0; i < amount; i++) {
1001                 if (pfx && i == amount - 1)
1002                         fputs(pfx, fp);
1003                 putc('\t', fp);
1004         }
1005 }
1006
1007 /* little circular references here... */
1008 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1009
1010 static void
1011 sharg(union node *arg, FILE *fp)
1012 {
1013         char *p;
1014         struct nodelist *bqlist;
1015         unsigned char subtype;
1016
1017         if (arg->type != NARG) {
1018                 out1fmt("<node type %d>\n", arg->type);
1019                 abort();
1020         }
1021         bqlist = arg->narg.backquote;
1022         for (p = arg->narg.text; *p; p++) {
1023                 switch ((unsigned char)*p) {
1024                 case CTLESC:
1025                         p++;
1026                         putc(*p, fp);
1027                         break;
1028                 case CTLVAR:
1029                         putc('$', fp);
1030                         putc('{', fp);
1031                         subtype = *++p;
1032                         if (subtype == VSLENGTH)
1033                                 putc('#', fp);
1034
1035                         while (*p != '=') {
1036                                 putc(*p, fp);
1037                                 p++;
1038                         }
1039
1040                         if (subtype & VSNUL)
1041                                 putc(':', fp);
1042
1043                         switch (subtype & VSTYPE) {
1044                         case VSNORMAL:
1045                                 putc('}', fp);
1046                                 break;
1047                         case VSMINUS:
1048                                 putc('-', fp);
1049                                 break;
1050                         case VSPLUS:
1051                                 putc('+', fp);
1052                                 break;
1053                         case VSQUESTION:
1054                                 putc('?', fp);
1055                                 break;
1056                         case VSASSIGN:
1057                                 putc('=', fp);
1058                                 break;
1059                         case VSTRIMLEFT:
1060                                 putc('#', fp);
1061                                 break;
1062                         case VSTRIMLEFTMAX:
1063                                 putc('#', fp);
1064                                 putc('#', fp);
1065                                 break;
1066                         case VSTRIMRIGHT:
1067                                 putc('%', fp);
1068                                 break;
1069                         case VSTRIMRIGHTMAX:
1070                                 putc('%', fp);
1071                                 putc('%', fp);
1072                                 break;
1073                         case VSLENGTH:
1074                                 break;
1075                         default:
1076                                 out1fmt("<subtype %d>", subtype);
1077                         }
1078                         break;
1079                 case CTLENDVAR:
1080                         putc('}', fp);
1081                         break;
1082                 case CTLBACKQ:
1083                         putc('$', fp);
1084                         putc('(', fp);
1085                         shtree(bqlist->n, -1, NULL, fp);
1086                         putc(')', fp);
1087                         break;
1088                 default:
1089                         putc(*p, fp);
1090                         break;
1091                 }
1092         }
1093 }
1094
1095 static void
1096 shcmd(union node *cmd, FILE *fp)
1097 {
1098         union node *np;
1099         int first;
1100         const char *s;
1101         int dftfd;
1102
1103         first = 1;
1104         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1105                 if (!first)
1106                         putc(' ', fp);
1107                 sharg(np, fp);
1108                 first = 0;
1109         }
1110         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1111                 if (!first)
1112                         putc(' ', fp);
1113                 dftfd = 0;
1114                 switch (np->nfile.type) {
1115                 case NTO:      s = ">>"+1; dftfd = 1; break;
1116                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1117                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1118 #if BASH_REDIR_OUTPUT
1119                 case NTO2:
1120 #endif
1121                 case NTOFD:    s = ">&"; dftfd = 1; break;
1122                 case NFROM:    s = "<"; break;
1123                 case NFROMFD:  s = "<&"; break;
1124                 case NFROMTO:  s = "<>"; break;
1125                 default:       s = "*error*"; break;
1126                 }
1127                 if (np->nfile.fd != dftfd)
1128                         fprintf(fp, "%d", np->nfile.fd);
1129                 fputs(s, fp);
1130                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1131                         fprintf(fp, "%d", np->ndup.dupfd);
1132                 } else {
1133                         sharg(np->nfile.fname, fp);
1134                 }
1135                 first = 0;
1136         }
1137 }
1138
1139 static void
1140 shtree(union node *n, int ind, char *pfx, FILE *fp)
1141 {
1142         struct nodelist *lp;
1143         const char *s;
1144
1145         if (n == NULL)
1146                 return;
1147
1148         indent(ind, pfx, fp);
1149
1150         if (n == NODE_EOF) {
1151                 fputs("<EOF>", fp);
1152                 return;
1153         }
1154
1155         switch (n->type) {
1156         case NSEMI:
1157                 s = "; ";
1158                 goto binop;
1159         case NAND:
1160                 s = " && ";
1161                 goto binop;
1162         case NOR:
1163                 s = " || ";
1164  binop:
1165                 shtree(n->nbinary.ch1, ind, NULL, fp);
1166                 /* if (ind < 0) */
1167                         fputs(s, fp);
1168                 shtree(n->nbinary.ch2, ind, NULL, fp);
1169                 break;
1170         case NCMD:
1171                 shcmd(n, fp);
1172                 if (ind >= 0)
1173                         putc('\n', fp);
1174                 break;
1175         case NPIPE:
1176                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1177                         shtree(lp->n, 0, NULL, fp);
1178                         if (lp->next)
1179                                 fputs(" | ", fp);
1180                 }
1181                 if (n->npipe.pipe_backgnd)
1182                         fputs(" &", fp);
1183                 if (ind >= 0)
1184                         putc('\n', fp);
1185                 break;
1186         default:
1187                 fprintf(fp, "<node type %d>", n->type);
1188                 if (ind >= 0)
1189                         putc('\n', fp);
1190                 break;
1191         }
1192 }
1193
1194 static void
1195 showtree(union node *n)
1196 {
1197         trace_puts("showtree called\n");
1198         shtree(n, 1, NULL, stderr);
1199 }
1200
1201 #endif /* DEBUG */
1202
1203
1204 /* ============ Parser data */
1205
1206 /*
1207  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1208  */
1209 struct strlist {
1210         struct strlist *next;
1211         char *text;
1212 };
1213
1214 struct alias;
1215
1216 struct strpush {
1217         struct strpush *prev;   /* preceding string on stack */
1218         char *prev_string;
1219         int prev_left_in_line;
1220 #if ENABLE_ASH_ALIAS
1221         struct alias *ap;       /* if push was associated with an alias */
1222 #endif
1223         char *string;           /* remember the string since it may change */
1224
1225         /* Remember last two characters for pungetc. */
1226         int lastc[2];
1227
1228         /* Number of outstanding calls to pungetc. */
1229         int unget;
1230 };
1231
1232 /*
1233  * The parsefile structure pointed to by the global variable parsefile
1234  * contains information about the current file being read.
1235  */
1236 struct parsefile {
1237         struct parsefile *prev; /* preceding file on stack */
1238         int linno;              /* current line */
1239         int pf_fd;              /* file descriptor (or -1 if string) */
1240         int left_in_line;       /* number of chars left in this line */
1241         int left_in_buffer;     /* number of chars left in this buffer past the line */
1242         char *next_to_pgetc;    /* next char in buffer */
1243         char *buf;              /* input buffer */
1244         struct strpush *strpush; /* for pushing strings at this level */
1245         struct strpush basestrpush; /* so pushing one is fast */
1246
1247         /* Remember last two characters for pungetc. */
1248         int lastc[2];
1249
1250         /* Number of outstanding calls to pungetc. */
1251         int unget;
1252 };
1253
1254 static struct parsefile basepf;        /* top level input file */
1255 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1256 static int startlinno;                 /* line # where last token started */
1257 static char *commandname;              /* currently executing command */
1258
1259
1260 /* ============ Message printing */
1261
1262 static void
1263 ash_vmsg(const char *msg, va_list ap)
1264 {
1265         fprintf(stderr, "%s: ", arg0);
1266         if (commandname) {
1267                 if (strcmp(arg0, commandname))
1268                         fprintf(stderr, "%s: ", commandname);
1269                 if (!iflag || g_parsefile->pf_fd > 0)
1270                         fprintf(stderr, "line %d: ", startlinno);
1271         }
1272         vfprintf(stderr, msg, ap);
1273         newline_and_flush(stderr);
1274 }
1275
1276 /*
1277  * Exverror is called to raise the error exception.  If the second argument
1278  * is not NULL then error prints an error message using printf style
1279  * formatting.  It then raises the error exception.
1280  */
1281 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1282 static void
1283 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1284 {
1285 #if DEBUG
1286         if (msg) {
1287                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1288                 TRACEV((msg, ap));
1289         } else
1290                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1291         if (msg)
1292 #endif
1293                 ash_vmsg(msg, ap);
1294
1295         flush_stdout_stderr();
1296         raise_exception(cond);
1297         /* NOTREACHED */
1298 }
1299
1300 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1301 static void
1302 ash_msg_and_raise_error(const char *msg, ...)
1303 {
1304         va_list ap;
1305
1306         exitstatus = 2;
1307
1308         va_start(ap, msg);
1309         ash_vmsg_and_raise(EXERROR, msg, ap);
1310         /* NOTREACHED */
1311         va_end(ap);
1312 }
1313
1314 /*
1315  * Use '%m' to append error string on platforms that support it, '%s' and
1316  * strerror() on those that don't.
1317  *
1318  * 'fmt' must be a string literal.
1319  */
1320 #ifdef HAVE_PRINTF_PERCENTM
1321 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1322 #else
1323 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1324 #endif
1325
1326 static void raise_error_syntax(const char *) NORETURN;
1327 static void
1328 raise_error_syntax(const char *msg)
1329 {
1330         ash_msg_and_raise_error("syntax error: %s", msg);
1331         /* NOTREACHED */
1332 }
1333
1334 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1335 static void
1336 ash_msg_and_raise(int cond, const char *msg, ...)
1337 {
1338         va_list ap;
1339
1340         va_start(ap, msg);
1341         ash_vmsg_and_raise(cond, msg, ap);
1342         /* NOTREACHED */
1343         va_end(ap);
1344 }
1345
1346 /*
1347  * error/warning routines for external builtins
1348  */
1349 static void
1350 ash_msg(const char *fmt, ...)
1351 {
1352         va_list ap;
1353
1354         va_start(ap, fmt);
1355         ash_vmsg(fmt, ap);
1356         va_end(ap);
1357 }
1358
1359 /*
1360  * Return a string describing an error.  The returned string may be a
1361  * pointer to a static buffer that will be overwritten on the next call.
1362  * Action describes the operation that got the error.
1363  */
1364 static const char *
1365 errmsg(int e, const char *em)
1366 {
1367         if (e == ENOENT || e == ENOTDIR) {
1368                 return em;
1369         }
1370         return strerror(e);
1371 }
1372
1373
1374 /* ============ Memory allocation */
1375
1376 #if 0
1377 /* I consider these wrappers nearly useless:
1378  * ok, they return you to nearest exception handler, but
1379  * how much memory do you leak in the process, making
1380  * memory starvation worse?
1381  */
1382 static void *
1383 ckrealloc(void * p, size_t nbytes)
1384 {
1385         p = realloc(p, nbytes);
1386         if (!p)
1387                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1388         return p;
1389 }
1390
1391 static void *
1392 ckmalloc(size_t nbytes)
1393 {
1394         return ckrealloc(NULL, nbytes);
1395 }
1396
1397 static void *
1398 ckzalloc(size_t nbytes)
1399 {
1400         return memset(ckmalloc(nbytes), 0, nbytes);
1401 }
1402
1403 static char *
1404 ckstrdup(const char *s)
1405 {
1406         char *p = strdup(s);
1407         if (!p)
1408                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1409         return p;
1410 }
1411 #else
1412 /* Using bbox equivalents. They exit if out of memory */
1413 # define ckrealloc xrealloc
1414 # define ckmalloc  xmalloc
1415 # define ckzalloc  xzalloc
1416 # define ckstrdup  xstrdup
1417 #endif
1418
1419 /*
1420  * It appears that grabstackstr() will barf with such alignments
1421  * because stalloc() will return a string allocated in a new stackblock.
1422  */
1423 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1424 enum {
1425         /* Most machines require the value returned from malloc to be aligned
1426          * in some way.  The following macro will get this right
1427          * on many machines.  */
1428         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1429         /* Minimum size of a block */
1430         MINSIZE = SHELL_ALIGN(504),
1431 };
1432
1433 struct stack_block {
1434         struct stack_block *prev;
1435         char space[MINSIZE];
1436 };
1437
1438 struct stackmark {
1439         struct stack_block *stackp;
1440         char *stacknxt;
1441         size_t stacknleft;
1442 };
1443
1444
1445 struct globals_memstack {
1446         struct stack_block *g_stackp; // = &stackbase;
1447         char *g_stacknxt; // = stackbase.space;
1448         char *sstrend; // = stackbase.space + MINSIZE;
1449         size_t g_stacknleft; // = MINSIZE;
1450         struct stack_block stackbase;
1451 };
1452 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1453 #define G_memstack (*ash_ptr_to_globals_memstack)
1454 #define g_stackp     (G_memstack.g_stackp    )
1455 #define g_stacknxt   (G_memstack.g_stacknxt  )
1456 #define sstrend      (G_memstack.sstrend     )
1457 #define g_stacknleft (G_memstack.g_stacknleft)
1458 #define stackbase    (G_memstack.stackbase   )
1459 #define INIT_G_memstack() do { \
1460         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1461         barrier(); \
1462         g_stackp = &stackbase; \
1463         g_stacknxt = stackbase.space; \
1464         g_stacknleft = MINSIZE; \
1465         sstrend = stackbase.space + MINSIZE; \
1466 } while (0)
1467
1468
1469 #define stackblock()     ((void *)g_stacknxt)
1470 #define stackblocksize() g_stacknleft
1471
1472 /*
1473  * Parse trees for commands are allocated in lifo order, so we use a stack
1474  * to make this more efficient, and also to avoid all sorts of exception
1475  * handling code to handle interrupts in the middle of a parse.
1476  *
1477  * The size 504 was chosen because the Ultrix malloc handles that size
1478  * well.
1479  */
1480 static void *
1481 stalloc(size_t nbytes)
1482 {
1483         char *p;
1484         size_t aligned;
1485
1486         aligned = SHELL_ALIGN(nbytes);
1487         if (aligned > g_stacknleft) {
1488                 size_t len;
1489                 size_t blocksize;
1490                 struct stack_block *sp;
1491
1492                 blocksize = aligned;
1493                 if (blocksize < MINSIZE)
1494                         blocksize = MINSIZE;
1495                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1496                 if (len < blocksize)
1497                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1498                 INT_OFF;
1499                 sp = ckmalloc(len);
1500                 sp->prev = g_stackp;
1501                 g_stacknxt = sp->space;
1502                 g_stacknleft = blocksize;
1503                 sstrend = g_stacknxt + blocksize;
1504                 g_stackp = sp;
1505                 INT_ON;
1506         }
1507         p = g_stacknxt;
1508         g_stacknxt += aligned;
1509         g_stacknleft -= aligned;
1510         return p;
1511 }
1512
1513 static void *
1514 stzalloc(size_t nbytes)
1515 {
1516         return memset(stalloc(nbytes), 0, nbytes);
1517 }
1518
1519 static void
1520 stunalloc(void *p)
1521 {
1522 #if DEBUG
1523         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1524                 write(STDERR_FILENO, "stunalloc\n", 10);
1525                 abort();
1526         }
1527 #endif
1528         g_stacknleft += g_stacknxt - (char *)p;
1529         g_stacknxt = p;
1530 }
1531
1532 /*
1533  * Like strdup but works with the ash stack.
1534  */
1535 static char *
1536 sstrdup(const char *p)
1537 {
1538         size_t len = strlen(p) + 1;
1539         return memcpy(stalloc(len), p, len);
1540 }
1541
1542 static inline void
1543 grabstackblock(size_t len)
1544 {
1545         stalloc(len);
1546 }
1547
1548 static void
1549 pushstackmark(struct stackmark *mark, size_t len)
1550 {
1551         mark->stackp = g_stackp;
1552         mark->stacknxt = g_stacknxt;
1553         mark->stacknleft = g_stacknleft;
1554         grabstackblock(len);
1555 }
1556
1557 static void
1558 setstackmark(struct stackmark *mark)
1559 {
1560         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1561 }
1562
1563 static void
1564 popstackmark(struct stackmark *mark)
1565 {
1566         struct stack_block *sp;
1567
1568         if (!mark->stackp)
1569                 return;
1570
1571         INT_OFF;
1572         while (g_stackp != mark->stackp) {
1573                 sp = g_stackp;
1574                 g_stackp = sp->prev;
1575                 free(sp);
1576         }
1577         g_stacknxt = mark->stacknxt;
1578         g_stacknleft = mark->stacknleft;
1579         sstrend = mark->stacknxt + mark->stacknleft;
1580         INT_ON;
1581 }
1582
1583 /*
1584  * When the parser reads in a string, it wants to stick the string on the
1585  * stack and only adjust the stack pointer when it knows how big the
1586  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1587  * of space on top of the stack and stackblocklen returns the length of
1588  * this block.  Growstackblock will grow this space by at least one byte,
1589  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1590  * part of the block that has been used.
1591  */
1592 static void
1593 growstackblock(void)
1594 {
1595         size_t newlen;
1596
1597         newlen = g_stacknleft * 2;
1598         if (newlen < g_stacknleft)
1599                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1600         if (newlen < 128)
1601                 newlen += 128;
1602
1603         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1604                 struct stack_block *sp;
1605                 struct stack_block *prevstackp;
1606                 size_t grosslen;
1607
1608                 INT_OFF;
1609                 sp = g_stackp;
1610                 prevstackp = sp->prev;
1611                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1612                 sp = ckrealloc(sp, grosslen);
1613                 sp->prev = prevstackp;
1614                 g_stackp = sp;
1615                 g_stacknxt = sp->space;
1616                 g_stacknleft = newlen;
1617                 sstrend = sp->space + newlen;
1618                 INT_ON;
1619         } else {
1620                 char *oldspace = g_stacknxt;
1621                 size_t oldlen = g_stacknleft;
1622                 char *p = stalloc(newlen);
1623
1624                 /* free the space we just allocated */
1625                 g_stacknxt = memcpy(p, oldspace, oldlen);
1626                 g_stacknleft += newlen;
1627         }
1628 }
1629
1630 /*
1631  * The following routines are somewhat easier to use than the above.
1632  * The user declares a variable of type STACKSTR, which may be declared
1633  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1634  * the user uses the macro STPUTC to add characters to the string.  In
1635  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1636  * grown as necessary.  When the user is done, she can just leave the
1637  * string there and refer to it using stackblock().  Or she can allocate
1638  * the space for it using grabstackstr().  If it is necessary to allow
1639  * someone else to use the stack temporarily and then continue to grow
1640  * the string, the user should use grabstack to allocate the space, and
1641  * then call ungrabstr(p) to return to the previous mode of operation.
1642  *
1643  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1644  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1645  * is space for at least one character.
1646  */
1647 static void *
1648 growstackstr(void)
1649 {
1650         size_t len = stackblocksize();
1651         growstackblock();
1652         return (char *)stackblock() + len;
1653 }
1654
1655 /*
1656  * Called from CHECKSTRSPACE.
1657  */
1658 static char *
1659 makestrspace(size_t newlen, char *p)
1660 {
1661         size_t len = p - g_stacknxt;
1662         size_t size;
1663
1664         for (;;) {
1665                 size_t nleft;
1666
1667                 size = stackblocksize();
1668                 nleft = size - len;
1669                 if (nleft >= newlen)
1670                         break;
1671                 growstackblock();
1672         }
1673         return (char *)stackblock() + len;
1674 }
1675
1676 static char *
1677 stack_nputstr(const char *s, size_t n, char *p)
1678 {
1679         p = makestrspace(n, p);
1680         p = (char *)mempcpy(p, s, n);
1681         return p;
1682 }
1683
1684 static char *
1685 stack_putstr(const char *s, char *p)
1686 {
1687         return stack_nputstr(s, strlen(s), p);
1688 }
1689
1690 static char *
1691 _STPUTC(int c, char *p)
1692 {
1693         if (p == sstrend)
1694                 p = growstackstr();
1695         *p++ = c;
1696         return p;
1697 }
1698
1699 #define STARTSTACKSTR(p)        ((p) = stackblock())
1700 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1701 #define CHECKSTRSPACE(n, p) do { \
1702         char *q = (p); \
1703         size_t l = (n); \
1704         size_t m = sstrend - q; \
1705         if (l > m) \
1706                 (p) = makestrspace(l, q); \
1707 } while (0)
1708 #define USTPUTC(c, p)           (*(p)++ = (c))
1709 #define STACKSTRNUL(p) do { \
1710         if ((p) == sstrend) \
1711                 (p) = growstackstr(); \
1712         *(p) = '\0'; \
1713 } while (0)
1714 #define STUNPUTC(p)             (--(p))
1715 #define STTOPC(p)               ((p)[-1])
1716 #define STADJUST(amount, p)     ((p) += (amount))
1717
1718 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1719 #define ungrabstackstr(s, p)    stunalloc(s)
1720 #define stackstrend()           ((void *)sstrend)
1721
1722
1723 /* ============ String helpers */
1724
1725 /*
1726  * prefix -- see if pfx is a prefix of string.
1727  */
1728 static char *
1729 prefix(const char *string, const char *pfx)
1730 {
1731         while (*pfx) {
1732                 if (*pfx++ != *string++)
1733                         return NULL;
1734         }
1735         return (char *) string;
1736 }
1737
1738 /*
1739  * Check for a valid number.  This should be elsewhere.
1740  */
1741 static int
1742 is_number(const char *p)
1743 {
1744         do {
1745                 if (!isdigit(*p))
1746                         return 0;
1747         } while (*++p != '\0');
1748         return 1;
1749 }
1750
1751 /*
1752  * Convert a string of digits to an integer, printing an error message on
1753  * failure.
1754  */
1755 static int
1756 number(const char *s)
1757 {
1758         if (!is_number(s))
1759                 ash_msg_and_raise_error(msg_illnum, s);
1760         return atoi(s);
1761 }
1762
1763 /*
1764  * Produce a single quoted string suitable as input to the shell.
1765  * The return string is allocated on the stack.
1766  */
1767 static char *
1768 single_quote(const char *s)
1769 {
1770         char *p;
1771
1772         STARTSTACKSTR(p);
1773
1774         do {
1775                 char *q;
1776                 size_t len;
1777
1778                 len = strchrnul(s, '\'') - s;
1779
1780                 q = p = makestrspace(len + 3, p);
1781
1782                 *q++ = '\'';
1783                 q = (char *)mempcpy(q, s, len);
1784                 *q++ = '\'';
1785                 s += len;
1786
1787                 STADJUST(q - p, p);
1788
1789                 if (*s != '\'')
1790                         break;
1791                 len = 0;
1792                 do len++; while (*++s == '\'');
1793
1794                 q = p = makestrspace(len + 3, p);
1795
1796                 *q++ = '"';
1797                 q = (char *)mempcpy(q, s - len, len);
1798                 *q++ = '"';
1799
1800                 STADJUST(q - p, p);
1801         } while (*s);
1802
1803         USTPUTC('\0', p);
1804
1805         return stackblock();
1806 }
1807
1808 /*
1809  * Produce a possibly single quoted string suitable as input to the shell.
1810  * If quoting was done, the return string is allocated on the stack,
1811  * otherwise a pointer to the original string is returned.
1812  */
1813 static const char *
1814 maybe_single_quote(const char *s)
1815 {
1816         const char *p = s;
1817
1818         while (*p) {
1819                 /* Assuming ACSII */
1820                 /* quote ctrl_chars space !"#$%&'()* */
1821                 if (*p < '+')
1822                         goto need_quoting;
1823                 /* quote ;<=>? */
1824                 if (*p >= ';' && *p <= '?')
1825                         goto need_quoting;
1826                 /* quote `[\ */
1827                 if (*p == '`')
1828                         goto need_quoting;
1829                 if (*p == '[')
1830                         goto need_quoting;
1831                 if (*p == '\\')
1832                         goto need_quoting;
1833                 /* quote {|}~ DEL and high bytes */
1834                 if (*p > 'z')
1835                         goto need_quoting;
1836                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1837                 /* TODO: maybe avoid quoting % */
1838                 p++;
1839         }
1840         return s;
1841
1842  need_quoting:
1843         return single_quote(s);
1844 }
1845
1846
1847 /* ============ nextopt */
1848
1849 static char **argptr;                  /* argument list for builtin commands */
1850 static char *optionarg;                /* set by nextopt (like getopt) */
1851 static char *optptr;                   /* used by nextopt */
1852
1853 /*
1854  * XXX - should get rid of. Have all builtins use getopt(3).
1855  * The library getopt must have the BSD extension static variable
1856  * "optreset", otherwise it can't be used within the shell safely.
1857  *
1858  * Standard option processing (a la getopt) for builtin routines.
1859  * The only argument that is passed to nextopt is the option string;
1860  * the other arguments are unnecessary. It returns the character,
1861  * or '\0' on end of input.
1862  */
1863 static int
1864 nextopt(const char *optstring)
1865 {
1866         char *p;
1867         const char *q;
1868         char c;
1869
1870         p = optptr;
1871         if (p == NULL || *p == '\0') {
1872                 /* We ate entire "-param", take next one */
1873                 p = *argptr;
1874                 if (p == NULL)
1875                         return '\0';
1876                 if (*p != '-')
1877                         return '\0';
1878                 if (*++p == '\0') /* just "-" ? */
1879                         return '\0';
1880                 argptr++;
1881                 if (LONE_DASH(p)) /* "--" ? */
1882                         return '\0';
1883                 /* p => next "-param" */
1884         }
1885         /* p => some option char in the middle of a "-param" */
1886         c = *p++;
1887         for (q = optstring; *q != c;) {
1888                 if (*q == '\0')
1889                         ash_msg_and_raise_error("illegal option -%c", c);
1890                 if (*++q == ':')
1891                         q++;
1892         }
1893         if (*++q == ':') {
1894                 if (*p == '\0') {
1895                         p = *argptr++;
1896                         if (p == NULL)
1897                                 ash_msg_and_raise_error("no arg for -%c option", c);
1898                 }
1899                 optionarg = p;
1900                 p = NULL;
1901         }
1902         optptr = p;
1903         return c;
1904 }
1905
1906
1907 /* ============ Shell variables */
1908
1909 struct shparam {
1910         int nparam;             /* # of positional parameters (without $0) */
1911 #if ENABLE_ASH_GETOPTS
1912         int optind;             /* next parameter to be processed by getopts */
1913         int optoff;             /* used by getopts */
1914 #endif
1915         unsigned char malloced; /* if parameter list dynamically allocated */
1916         char **p;               /* parameter list */
1917 };
1918
1919 /*
1920  * Free the list of positional parameters.
1921  */
1922 static void
1923 freeparam(volatile struct shparam *param)
1924 {
1925         if (param->malloced) {
1926                 char **ap, **ap1;
1927                 ap = ap1 = param->p;
1928                 while (*ap)
1929                         free(*ap++);
1930                 free(ap1);
1931         }
1932 }
1933
1934 #if ENABLE_ASH_GETOPTS
1935 static void FAST_FUNC getoptsreset(const char *value);
1936 #endif
1937
1938 struct var {
1939         struct var *next;               /* next entry in hash list */
1940         int flags;                      /* flags are defined above */
1941         const char *var_text;           /* name=value */
1942         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1943                                         /* the variable gets set/unset */
1944 };
1945
1946 struct localvar {
1947         struct localvar *next;          /* next local variable in list */
1948         struct var *vp;                 /* the variable that was made local */
1949         int flags;                      /* saved flags */
1950         const char *text;               /* saved text */
1951 };
1952
1953 /* flags */
1954 #define VEXPORT         0x01    /* variable is exported */
1955 #define VREADONLY       0x02    /* variable cannot be modified */
1956 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1957 #define VTEXTFIXED      0x08    /* text is statically allocated */
1958 #define VSTACK          0x10    /* text is allocated on the stack */
1959 #define VUNSET          0x20    /* the variable is not set */
1960 #define VNOFUNC         0x40    /* don't call the callback function */
1961 #define VNOSET          0x80    /* do not set variable - just readonly test */
1962 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1963 #if ENABLE_ASH_RANDOM_SUPPORT
1964 # define VDYNAMIC       0x200   /* dynamic variable */
1965 #else
1966 # define VDYNAMIC       0
1967 #endif
1968
1969
1970 /* Need to be before varinit_data[] */
1971 #if ENABLE_LOCALE_SUPPORT
1972 static void FAST_FUNC
1973 change_lc_all(const char *value)
1974 {
1975         if (value && *value != '\0')
1976                 setlocale(LC_ALL, value);
1977 }
1978 static void FAST_FUNC
1979 change_lc_ctype(const char *value)
1980 {
1981         if (value && *value != '\0')
1982                 setlocale(LC_CTYPE, value);
1983 }
1984 #endif
1985 #if ENABLE_ASH_MAIL
1986 static void chkmail(void);
1987 static void changemail(const char *var_value) FAST_FUNC;
1988 #else
1989 # define chkmail()  ((void)0)
1990 #endif
1991 static void changepath(const char *) FAST_FUNC;
1992 #if ENABLE_ASH_RANDOM_SUPPORT
1993 static void change_random(const char *) FAST_FUNC;
1994 #endif
1995
1996 static const struct {
1997         int flags;
1998         const char *var_text;
1999         void (*var_func)(const char *) FAST_FUNC;
2000 } varinit_data[] = {
2001         /*
2002          * Note: VEXPORT would not work correctly here for NOFORK applets:
2003          * some environment strings may be constant.
2004          */
2005         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2006 #if ENABLE_ASH_MAIL
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2008         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2009 #endif
2010         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2011         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2012         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2013         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2014 #if ENABLE_ASH_GETOPTS
2015         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2016 #endif
2017 #if ENABLE_ASH_RANDOM_SUPPORT
2018         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2019 #endif
2020 #if ENABLE_LOCALE_SUPPORT
2021         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2022         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2023 #endif
2024 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2025         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2026 #endif
2027 };
2028
2029 struct redirtab;
2030
2031 struct globals_var {
2032         struct shparam shellparam;      /* $@ current positional parameters */
2033         struct redirtab *redirlist;
2034         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2035         struct var *vartab[VTABSIZE];
2036         struct var varinit[ARRAY_SIZE(varinit_data)];
2037 };
2038 extern struct globals_var *const ash_ptr_to_globals_var;
2039 #define G_var (*ash_ptr_to_globals_var)
2040 #define shellparam    (G_var.shellparam   )
2041 //#define redirlist     (G_var.redirlist    )
2042 #define preverrout_fd (G_var.preverrout_fd)
2043 #define vartab        (G_var.vartab       )
2044 #define varinit       (G_var.varinit      )
2045 #define INIT_G_var() do { \
2046         unsigned i; \
2047         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2048         barrier(); \
2049         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2050                 varinit[i].flags    = varinit_data[i].flags; \
2051                 varinit[i].var_text = varinit_data[i].var_text; \
2052                 varinit[i].var_func = varinit_data[i].var_func; \
2053         } \
2054 } while (0)
2055
2056 #define vifs      varinit[0]
2057 #if ENABLE_ASH_MAIL
2058 # define vmail    (&vifs)[1]
2059 # define vmpath   (&vmail)[1]
2060 # define vpath    (&vmpath)[1]
2061 #else
2062 # define vpath    (&vifs)[1]
2063 #endif
2064 #define vps1      (&vpath)[1]
2065 #define vps2      (&vps1)[1]
2066 #define vps4      (&vps2)[1]
2067 #if ENABLE_ASH_GETOPTS
2068 # define voptind  (&vps4)[1]
2069 # if ENABLE_ASH_RANDOM_SUPPORT
2070 #  define vrandom (&voptind)[1]
2071 # endif
2072 #else
2073 # if ENABLE_ASH_RANDOM_SUPPORT
2074 #  define vrandom (&vps4)[1]
2075 # endif
2076 #endif
2077
2078 /*
2079  * The following macros access the values of the above variables.
2080  * They have to skip over the name.  They return the null string
2081  * for unset variables.
2082  */
2083 #define ifsval()        (vifs.var_text + 4)
2084 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2085 #if ENABLE_ASH_MAIL
2086 # define mailval()      (vmail.var_text + 5)
2087 # define mpathval()     (vmpath.var_text + 9)
2088 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2089 #endif
2090 #define pathval()       (vpath.var_text + 5)
2091 #define ps1val()        (vps1.var_text + 4)
2092 #define ps2val()        (vps2.var_text + 4)
2093 #define ps4val()        (vps4.var_text + 4)
2094 #if ENABLE_ASH_GETOPTS
2095 # define optindval()    (voptind.var_text + 7)
2096 #endif
2097
2098 #if ENABLE_ASH_GETOPTS
2099 static void FAST_FUNC
2100 getoptsreset(const char *value)
2101 {
2102         shellparam.optind = 1;
2103         if (is_number(value))
2104                 shellparam.optind = number(value) ?: 1;
2105         shellparam.optoff = -1;
2106 }
2107 #endif
2108
2109 /*
2110  * Compares two strings up to the first = or '\0'.  The first
2111  * string must be terminated by '='; the second may be terminated by
2112  * either '=' or '\0'.
2113  */
2114 static int
2115 varcmp(const char *p, const char *q)
2116 {
2117         int c, d;
2118
2119         while ((c = *p) == (d = *q)) {
2120                 if (c == '\0' || c == '=')
2121                         goto out;
2122                 p++;
2123                 q++;
2124         }
2125         if (c == '=')
2126                 c = '\0';
2127         if (d == '=')
2128                 d = '\0';
2129  out:
2130         return c - d;
2131 }
2132
2133 /*
2134  * Find the appropriate entry in the hash table from the name.
2135  */
2136 static struct var **
2137 hashvar(const char *p)
2138 {
2139         unsigned hashval;
2140
2141         hashval = ((unsigned char) *p) << 4;
2142         while (*p && *p != '=')
2143                 hashval += (unsigned char) *p++;
2144         return &vartab[hashval % VTABSIZE];
2145 }
2146
2147 static int
2148 vpcmp(const void *a, const void *b)
2149 {
2150         return varcmp(*(const char **)a, *(const char **)b);
2151 }
2152
2153 /*
2154  * This routine initializes the builtin variables.
2155  */
2156 static void
2157 initvar(void)
2158 {
2159         struct var *vp;
2160         struct var *end;
2161         struct var **vpp;
2162
2163         /*
2164          * PS1 depends on uid
2165          */
2166 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2167         vps1.var_text = "PS1=\\w \\$ ";
2168 #else
2169         if (!geteuid())
2170                 vps1.var_text = "PS1=# ";
2171 #endif
2172         vp = varinit;
2173         end = vp + ARRAY_SIZE(varinit);
2174         do {
2175                 vpp = hashvar(vp->var_text);
2176                 vp->next = *vpp;
2177                 *vpp = vp;
2178         } while (++vp < end);
2179 }
2180
2181 static struct var **
2182 findvar(struct var **vpp, const char *name)
2183 {
2184         for (; *vpp; vpp = &(*vpp)->next) {
2185                 if (varcmp((*vpp)->var_text, name) == 0) {
2186                         break;
2187                 }
2188         }
2189         return vpp;
2190 }
2191
2192 /*
2193  * Find the value of a variable.  Returns NULL if not set.
2194  */
2195 static const char* FAST_FUNC
2196 lookupvar(const char *name)
2197 {
2198         struct var *v;
2199
2200         v = *findvar(hashvar(name), name);
2201         if (v) {
2202 #if ENABLE_ASH_RANDOM_SUPPORT
2203         /*
2204          * Dynamic variables are implemented roughly the same way they are
2205          * in bash. Namely, they're "special" so long as they aren't unset.
2206          * As soon as they're unset, they're no longer dynamic, and dynamic
2207          * lookup will no longer happen at that point. -- PFM.
2208          */
2209                 if (v->flags & VDYNAMIC)
2210                         v->var_func(NULL);
2211 #endif
2212                 if (!(v->flags & VUNSET))
2213                         return var_end(v->var_text);
2214         }
2215         return NULL;
2216 }
2217
2218 #if ENABLE_UNICODE_SUPPORT
2219 static void
2220 reinit_unicode_for_ash(void)
2221 {
2222         /* Unicode support should be activated even if LANG is set
2223          * _during_ shell execution, not only if it was set when
2224          * shell was started. Therefore, re-check LANG every time:
2225          */
2226         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2227          || ENABLE_UNICODE_USING_LOCALE
2228         ) {
2229                 const char *s = lookupvar("LC_ALL");
2230                 if (!s) s = lookupvar("LC_CTYPE");
2231                 if (!s) s = lookupvar("LANG");
2232                 reinit_unicode(s);
2233         }
2234 }
2235 #else
2236 # define reinit_unicode_for_ash() ((void)0)
2237 #endif
2238
2239 /*
2240  * Search the environment of a builtin command.
2241  */
2242 static ALWAYS_INLINE const char *
2243 bltinlookup(const char *name)
2244 {
2245         return lookupvar(name);
2246 }
2247
2248 /*
2249  * Same as setvar except that the variable and value are passed in
2250  * the first argument as name=value.  Since the first argument will
2251  * be actually stored in the table, it should not be a string that
2252  * will go away.
2253  * Called with interrupts off.
2254  */
2255 static struct var *
2256 setvareq(char *s, int flags)
2257 {
2258         struct var *vp, **vpp;
2259
2260         vpp = hashvar(s);
2261         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2262         vpp = findvar(vpp, s);
2263         vp = *vpp;
2264         if (vp) {
2265                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2266                         const char *n;
2267
2268                         if (flags & VNOSAVE)
2269                                 free(s);
2270                         n = vp->var_text;
2271                         exitstatus = 1;
2272                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2273                 }
2274
2275                 if (flags & VNOSET)
2276                         goto out;
2277
2278                 if (vp->var_func && !(flags & VNOFUNC))
2279                         vp->var_func(var_end(s));
2280
2281                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2282                         free((char*)vp->var_text);
2283
2284                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2285                         *vpp = vp->next;
2286                         free(vp);
2287  out_free:
2288                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2289                                 free(s);
2290                         goto out;
2291                 }
2292
2293                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2294         } else {
2295                 /* variable s is not found */
2296                 if (flags & VNOSET)
2297                         goto out;
2298                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2299                         goto out_free;
2300                 vp = ckzalloc(sizeof(*vp));
2301                 vp->next = *vpp;
2302                 /*vp->func = NULL; - ckzalloc did it */
2303                 *vpp = vp;
2304         }
2305         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2306                 s = ckstrdup(s);
2307         vp->var_text = s;
2308         vp->flags = flags;
2309
2310  out:
2311         return vp;
2312 }
2313
2314 /*
2315  * Set the value of a variable.  The flags argument is ored with the
2316  * flags of the variable.  If val is NULL, the variable is unset.
2317  */
2318 static struct var *
2319 setvar(const char *name, const char *val, int flags)
2320 {
2321         const char *q;
2322         char *p;
2323         char *nameeq;
2324         size_t namelen;
2325         size_t vallen;
2326         struct var *vp;
2327
2328         q = endofname(name);
2329         p = strchrnul(q, '=');
2330         namelen = p - name;
2331         if (!namelen || p != q)
2332                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2333         vallen = 0;
2334         if (val == NULL) {
2335                 flags |= VUNSET;
2336         } else {
2337                 vallen = strlen(val);
2338         }
2339
2340         INT_OFF;
2341         nameeq = ckmalloc(namelen + vallen + 2);
2342         p = mempcpy(nameeq, name, namelen);
2343         if (val) {
2344                 *p++ = '=';
2345                 p = mempcpy(p, val, vallen);
2346         }
2347         *p = '\0';
2348         vp = setvareq(nameeq, flags | VNOSAVE);
2349         INT_ON;
2350
2351         return vp;
2352 }
2353
2354 static void FAST_FUNC
2355 setvar0(const char *name, const char *val)
2356 {
2357         setvar(name, val, 0);
2358 }
2359
2360 /*
2361  * Unset the specified variable.
2362  */
2363 static void
2364 unsetvar(const char *s)
2365 {
2366         setvar(s, NULL, 0);
2367 }
2368
2369 /*
2370  * Process a linked list of variable assignments.
2371  */
2372 static void
2373 listsetvar(struct strlist *list_set_var, int flags)
2374 {
2375         struct strlist *lp = list_set_var;
2376
2377         if (!lp)
2378                 return;
2379         INT_OFF;
2380         do {
2381                 setvareq(lp->text, flags);
2382                 lp = lp->next;
2383         } while (lp);
2384         INT_ON;
2385 }
2386
2387 /*
2388  * Generate a list of variables satisfying the given conditions.
2389  */
2390 static char **
2391 listvars(int on, int off, char ***end)
2392 {
2393         struct var **vpp;
2394         struct var *vp;
2395         char **ep;
2396         int mask;
2397
2398         STARTSTACKSTR(ep);
2399         vpp = vartab;
2400         mask = on | off;
2401         do {
2402                 for (vp = *vpp; vp; vp = vp->next) {
2403                         if ((vp->flags & mask) == on) {
2404                                 if (ep == stackstrend())
2405                                         ep = growstackstr();
2406                                 *ep++ = (char*)vp->var_text;
2407                         }
2408                 }
2409         } while (++vpp < vartab + VTABSIZE);
2410         if (ep == stackstrend())
2411                 ep = growstackstr();
2412         if (end)
2413                 *end = ep;
2414         *ep++ = NULL;
2415         return grabstackstr(ep);
2416 }
2417
2418
2419 /* ============ Path search helper
2420  *
2421  * The variable path (passed by reference) should be set to the start
2422  * of the path before the first call; path_advance will update
2423  * this value as it proceeds.  Successive calls to path_advance will return
2424  * the possible path expansions in sequence.  If an option (indicated by
2425  * a percent sign) appears in the path entry then the global variable
2426  * pathopt will be set to point to it; otherwise pathopt will be set to
2427  * NULL.
2428  */
2429 static const char *pathopt;     /* set by path_advance */
2430
2431 static char *
2432 path_advance(const char **path, const char *name)
2433 {
2434         const char *p;
2435         char *q;
2436         const char *start;
2437         size_t len;
2438
2439         if (*path == NULL)
2440                 return NULL;
2441         start = *path;
2442         for (p = start; *p && *p != ':' && *p != '%'; p++)
2443                 continue;
2444         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2445         while (stackblocksize() < len)
2446                 growstackblock();
2447         q = stackblock();
2448         if (p != start) {
2449                 q = mempcpy(q, start, p - start);
2450                 *q++ = '/';
2451         }
2452         strcpy(q, name);
2453         pathopt = NULL;
2454         if (*p == '%') {
2455                 pathopt = ++p;
2456                 while (*p && *p != ':')
2457                         p++;
2458         }
2459         if (*p == ':')
2460                 *path = p + 1;
2461         else
2462                 *path = NULL;
2463         return stalloc(len);
2464 }
2465
2466
2467 /* ============ Prompt */
2468
2469 static smallint doprompt;                   /* if set, prompt the user */
2470 static smallint needprompt;                 /* true if interactive and at start of line */
2471
2472 #if ENABLE_FEATURE_EDITING
2473 static line_input_t *line_input_state;
2474 static const char *cmdedit_prompt;
2475 static void
2476 putprompt(const char *s)
2477 {
2478         if (ENABLE_ASH_EXPAND_PRMT) {
2479                 free((char*)cmdedit_prompt);
2480                 cmdedit_prompt = ckstrdup(s);
2481                 return;
2482         }
2483         cmdedit_prompt = s;
2484 }
2485 #else
2486 static void
2487 putprompt(const char *s)
2488 {
2489         out2str(s);
2490 }
2491 #endif
2492
2493 /* expandstr() needs parsing machinery, so it is far away ahead... */
2494 static const char *expandstr(const char *ps, int syntax_type);
2495 /* Values for syntax param */
2496 #define BASESYNTAX 0    /* not in quotes */
2497 #define DQSYNTAX   1    /* in double quotes */
2498 #define SQSYNTAX   2    /* in single quotes */
2499 #define ARISYNTAX  3    /* in arithmetic */
2500 #if ENABLE_ASH_EXPAND_PRMT
2501 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2502 #endif
2503 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2504
2505 /*
2506  * called by editline -- any expansions to the prompt should be added here.
2507  */
2508 static void
2509 setprompt_if(smallint do_set, int whichprompt)
2510 {
2511         const char *prompt;
2512         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2513
2514         if (!do_set)
2515                 return;
2516
2517         needprompt = 0;
2518
2519         switch (whichprompt) {
2520         case 1:
2521                 prompt = ps1val();
2522                 break;
2523         case 2:
2524                 prompt = ps2val();
2525                 break;
2526         default:                        /* 0 */
2527                 prompt = nullstr;
2528         }
2529 #if ENABLE_ASH_EXPAND_PRMT
2530         pushstackmark(&smark, stackblocksize());
2531         putprompt(expandstr(prompt, PSSYNTAX));
2532         popstackmark(&smark);
2533 #else
2534         putprompt(prompt);
2535 #endif
2536 }
2537
2538
2539 /* ============ The cd and pwd commands */
2540
2541 #define CD_PHYSICAL 1
2542 #define CD_PRINT 2
2543
2544 static int
2545 cdopt(void)
2546 {
2547         int flags = 0;
2548         int i, j;
2549
2550         j = 'L';
2551         while ((i = nextopt("LP")) != '\0') {
2552                 if (i != j) {
2553                         flags ^= CD_PHYSICAL;
2554                         j = i;
2555                 }
2556         }
2557
2558         return flags;
2559 }
2560
2561 /*
2562  * Update curdir (the name of the current directory) in response to a
2563  * cd command.
2564  */
2565 static const char *
2566 updatepwd(const char *dir)
2567 {
2568         char *new;
2569         char *p;
2570         char *cdcomppath;
2571         const char *lim;
2572
2573         cdcomppath = sstrdup(dir);
2574         STARTSTACKSTR(new);
2575         if (*dir != '/') {
2576                 if (curdir == nullstr)
2577                         return 0;
2578                 new = stack_putstr(curdir, new);
2579         }
2580         new = makestrspace(strlen(dir) + 2, new);
2581         lim = (char *)stackblock() + 1;
2582         if (*dir != '/') {
2583                 if (new[-1] != '/')
2584                         USTPUTC('/', new);
2585                 if (new > lim && *lim == '/')
2586                         lim++;
2587         } else {
2588                 USTPUTC('/', new);
2589                 cdcomppath++;
2590                 if (dir[1] == '/' && dir[2] != '/') {
2591                         USTPUTC('/', new);
2592                         cdcomppath++;
2593                         lim++;
2594                 }
2595         }
2596         p = strtok(cdcomppath, "/");
2597         while (p) {
2598                 switch (*p) {
2599                 case '.':
2600                         if (p[1] == '.' && p[2] == '\0') {
2601                                 while (new > lim) {
2602                                         STUNPUTC(new);
2603                                         if (new[-1] == '/')
2604                                                 break;
2605                                 }
2606                                 break;
2607                         }
2608                         if (p[1] == '\0')
2609                                 break;
2610                         /* fall through */
2611                 default:
2612                         new = stack_putstr(p, new);
2613                         USTPUTC('/', new);
2614                 }
2615                 p = strtok(NULL, "/");
2616         }
2617         if (new > lim)
2618                 STUNPUTC(new);
2619         *new = 0;
2620         return stackblock();
2621 }
2622
2623 /*
2624  * Find out what the current directory is. If we already know the current
2625  * directory, this routine returns immediately.
2626  */
2627 static char *
2628 getpwd(void)
2629 {
2630         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2631         return dir ? dir : nullstr;
2632 }
2633
2634 static void
2635 setpwd(const char *val, int setold)
2636 {
2637         char *oldcur, *dir;
2638
2639         oldcur = dir = curdir;
2640
2641         if (setold) {
2642                 setvar("OLDPWD", oldcur, VEXPORT);
2643         }
2644         INT_OFF;
2645         if (physdir != nullstr) {
2646                 if (physdir != oldcur)
2647                         free(physdir);
2648                 physdir = nullstr;
2649         }
2650         if (oldcur == val || !val) {
2651                 char *s = getpwd();
2652                 physdir = s;
2653                 if (!val)
2654                         dir = s;
2655         } else
2656                 dir = ckstrdup(val);
2657         if (oldcur != dir && oldcur != nullstr) {
2658                 free(oldcur);
2659         }
2660         curdir = dir;
2661         INT_ON;
2662         setvar("PWD", dir, VEXPORT);
2663 }
2664
2665 static void hashcd(void);
2666
2667 /*
2668  * Actually do the chdir.  We also call hashcd to let other routines
2669  * know that the current directory has changed.
2670  */
2671 static int
2672 docd(const char *dest, int flags)
2673 {
2674         const char *dir = NULL;
2675         int err;
2676
2677         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2678
2679         INT_OFF;
2680         if (!(flags & CD_PHYSICAL)) {
2681                 dir = updatepwd(dest);
2682                 if (dir)
2683                         dest = dir;
2684         }
2685         err = chdir(dest);
2686         if (err)
2687                 goto out;
2688         setpwd(dir, 1);
2689         hashcd();
2690  out:
2691         INT_ON;
2692         return err;
2693 }
2694
2695 static int FAST_FUNC
2696 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2697 {
2698         const char *dest;
2699         const char *path;
2700         const char *p;
2701         char c;
2702         struct stat statb;
2703         int flags;
2704
2705         flags = cdopt();
2706         dest = *argptr;
2707         if (!dest)
2708                 dest = bltinlookup("HOME");
2709         else if (LONE_DASH(dest)) {
2710                 dest = bltinlookup("OLDPWD");
2711                 flags |= CD_PRINT;
2712         }
2713         if (!dest)
2714                 dest = nullstr;
2715         if (*dest == '/')
2716                 goto step6;
2717         if (*dest == '.') {
2718                 c = dest[1];
2719  dotdot:
2720                 switch (c) {
2721                 case '\0':
2722                 case '/':
2723                         goto step6;
2724                 case '.':
2725                         c = dest[2];
2726                         if (c != '.')
2727                                 goto dotdot;
2728                 }
2729         }
2730         if (!*dest)
2731                 dest = ".";
2732         path = bltinlookup("CDPATH");
2733         while (path) {
2734                 c = *path;
2735                 p = path_advance(&path, dest);
2736                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2737                         if (c && c != ':')
2738                                 flags |= CD_PRINT;
2739  docd:
2740                         if (!docd(p, flags))
2741                                 goto out;
2742                         goto err;
2743                 }
2744         }
2745
2746  step6:
2747         p = dest;
2748         goto docd;
2749
2750  err:
2751         ash_msg_and_raise_perror("can't cd to %s", dest);
2752         /* NOTREACHED */
2753  out:
2754         if (flags & CD_PRINT)
2755                 out1fmt("%s\n", curdir);
2756         return 0;
2757 }
2758
2759 static int FAST_FUNC
2760 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2761 {
2762         int flags;
2763         const char *dir = curdir;
2764
2765         flags = cdopt();
2766         if (flags) {
2767                 if (physdir == nullstr)
2768                         setpwd(dir, 0);
2769                 dir = physdir;
2770         }
2771         out1fmt("%s\n", dir);
2772         return 0;
2773 }
2774
2775
2776 /* ============ ... */
2777
2778
2779 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2780
2781 /* Syntax classes */
2782 #define CWORD     0             /* character is nothing special */
2783 #define CNL       1             /* newline character */
2784 #define CBACK     2             /* a backslash character */
2785 #define CSQUOTE   3             /* single quote */
2786 #define CDQUOTE   4             /* double quote */
2787 #define CENDQUOTE 5             /* a terminating quote */
2788 #define CBQUOTE   6             /* backwards single quote */
2789 #define CVAR      7             /* a dollar sign */
2790 #define CENDVAR   8             /* a '}' character */
2791 #define CLP       9             /* a left paren in arithmetic */
2792 #define CRP      10             /* a right paren in arithmetic */
2793 #define CENDFILE 11             /* end of file */
2794 #define CCTL     12             /* like CWORD, except it must be escaped */
2795 #define CSPCL    13             /* these terminate a word */
2796 #define CIGN     14             /* character should be ignored */
2797
2798 #define PEOF     256
2799 #if ENABLE_ASH_ALIAS
2800 # define PEOA    257
2801 #endif
2802
2803 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2804
2805 #if ENABLE_FEATURE_SH_MATH
2806 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2807 #else
2808 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2809 #endif
2810 static const uint16_t S_I_T[] ALIGN2 = {
2811 #if ENABLE_ASH_ALIAS
2812         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2813 #endif
2814         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2815         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2816         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2817         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2818         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2819         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2820         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2821         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2822         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2823         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2824         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2825 #if !USE_SIT_FUNCTION
2826         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2827         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2828         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2829 #endif
2830 #undef SIT_ITEM
2831 };
2832 /* Constants below must match table above */
2833 enum {
2834 #if ENABLE_ASH_ALIAS
2835         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2836 #endif
2837         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2838         CNL_CNL_CNL_CNL                    , /*  2 */
2839         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2840         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2841         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2842         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2843         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2844         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2845         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2846         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2847         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2848         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2849         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2850         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2851 };
2852
2853 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2854  * caller must ensure proper cast on it if c is *char_ptr!
2855  */
2856 #if USE_SIT_FUNCTION
2857
2858 static int
2859 SIT(int c, int syntax)
2860 {
2861         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2862         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2863         /*
2864          * This causes '/' to be prepended with CTLESC in dquoted string,
2865          * making "./file"* treated incorrectly because we feed
2866          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2867          * The "homegrown" glob implementation is okay with that,
2868          * but glibc one isn't. With '/' always treated as CWORD,
2869          * both work fine.
2870          */
2871 # if ENABLE_ASH_ALIAS
2872         static const uint8_t syntax_index_table[] ALIGN1 = {
2873                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2874                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2875                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2876                 11, 3                           /* "}~" */
2877         };
2878 # else
2879         static const uint8_t syntax_index_table[] ALIGN1 = {
2880                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2881                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2882                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2883                 10, 2                           /* "}~" */
2884         };
2885 # endif
2886         const char *s;
2887         int indx;
2888
2889         if (c == PEOF)
2890                 return CENDFILE;
2891 # if ENABLE_ASH_ALIAS
2892         if (c == PEOA)
2893                 indx = 0;
2894         else
2895 # endif
2896         {
2897                 /* Cast is purely for paranoia here,
2898                  * just in case someone passed signed char to us */
2899                 if ((unsigned char)c >= CTL_FIRST
2900                  && (unsigned char)c <= CTL_LAST
2901                 ) {
2902                         return CCTL;
2903                 }
2904                 s = strchrnul(spec_symbls, c);
2905                 if (*s == '\0')
2906                         return CWORD;
2907                 indx = syntax_index_table[s - spec_symbls];
2908         }
2909         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2910 }
2911
2912 #else   /* !USE_SIT_FUNCTION */
2913
2914 static const uint8_t syntax_index_table[] ALIGN1 = {
2915         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2916         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2918         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2919         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2921         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2922         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2923         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2924         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2925         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2926         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2927         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2944         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2945         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2946         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2947         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2948         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2949         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2950         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2951         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2953         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2954         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2955         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2956         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2957         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2958         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2959         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2961         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2962         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2963 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2964         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2976         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2977         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2978         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2979         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2980         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2981         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3006         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3009         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3010         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3011         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3012         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3013         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3014         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3015         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3016         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3037         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3038         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3039         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3040         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3041         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3042         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3043         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3044         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3045         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3046         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3047         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3048         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3049         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3050         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3051         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3052         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3053         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3054         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3173         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3174 # if ENABLE_ASH_ALIAS
3175         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3176 # endif
3177 };
3178
3179 #if 1
3180 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3181 #else /* debug version, caught one signed char bug */
3182 # define SIT(c, syntax) \
3183         ({ \
3184                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3185                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3186                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3187                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3188                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3189         })
3190 #endif
3191
3192 #endif  /* !USE_SIT_FUNCTION */
3193
3194
3195 /* ============ Alias handling */
3196
3197 #if ENABLE_ASH_ALIAS
3198
3199 #define ALIASINUSE 1
3200 #define ALIASDEAD  2
3201
3202 struct alias {
3203         struct alias *next;
3204         char *name;
3205         char *val;
3206         int flag;
3207 };
3208
3209
3210 static struct alias **atab; // [ATABSIZE];
3211 #define INIT_G_alias() do { \
3212         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3213 } while (0)
3214
3215
3216 static struct alias **
3217 __lookupalias(const char *name)
3218 {
3219         unsigned int hashval;
3220         struct alias **app;
3221         const char *p;
3222         unsigned int ch;
3223
3224         p = name;
3225
3226         ch = (unsigned char)*p;
3227         hashval = ch << 4;
3228         while (ch) {
3229                 hashval += ch;
3230                 ch = (unsigned char)*++p;
3231         }
3232         app = &atab[hashval % ATABSIZE];
3233
3234         for (; *app; app = &(*app)->next) {
3235                 if (strcmp(name, (*app)->name) == 0) {
3236                         break;
3237                 }
3238         }
3239
3240         return app;
3241 }
3242
3243 static struct alias *
3244 lookupalias(const char *name, int check)
3245 {
3246         struct alias *ap = *__lookupalias(name);
3247
3248         if (check && ap && (ap->flag & ALIASINUSE))
3249                 return NULL;
3250         return ap;
3251 }
3252
3253 static struct alias *
3254 freealias(struct alias *ap)
3255 {
3256         struct alias *next;
3257
3258         if (ap->flag & ALIASINUSE) {
3259                 ap->flag |= ALIASDEAD;
3260                 return ap;
3261         }
3262
3263         next = ap->next;
3264         free(ap->name);
3265         free(ap->val);
3266         free(ap);
3267         return next;
3268 }
3269
3270 static void
3271 setalias(const char *name, const char *val)
3272 {
3273         struct alias *ap, **app;
3274
3275         app = __lookupalias(name);
3276         ap = *app;
3277         INT_OFF;
3278         if (ap) {
3279                 if (!(ap->flag & ALIASINUSE)) {
3280                         free(ap->val);
3281                 }
3282                 ap->val = ckstrdup(val);
3283                 ap->flag &= ~ALIASDEAD;
3284         } else {
3285                 /* not found */
3286                 ap = ckzalloc(sizeof(struct alias));
3287                 ap->name = ckstrdup(name);
3288                 ap->val = ckstrdup(val);
3289                 /*ap->flag = 0; - ckzalloc did it */
3290                 /*ap->next = NULL;*/
3291                 *app = ap;
3292         }
3293         INT_ON;
3294 }
3295
3296 static int
3297 unalias(const char *name)
3298 {
3299         struct alias **app;
3300
3301         app = __lookupalias(name);
3302
3303         if (*app) {
3304                 INT_OFF;
3305                 *app = freealias(*app);
3306                 INT_ON;
3307                 return 0;
3308         }
3309
3310         return 1;
3311 }
3312
3313 static void
3314 rmaliases(void)
3315 {
3316         struct alias *ap, **app;
3317         int i;
3318
3319         INT_OFF;
3320         for (i = 0; i < ATABSIZE; i++) {
3321                 app = &atab[i];
3322                 for (ap = *app; ap; ap = *app) {
3323                         *app = freealias(*app);
3324                         if (ap == *app) {
3325                                 app = &ap->next;
3326                         }
3327                 }
3328         }
3329         INT_ON;
3330 }
3331
3332 static void
3333 printalias(const struct alias *ap)
3334 {
3335         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3336 }
3337
3338 /*
3339  * TODO - sort output
3340  */
3341 static int FAST_FUNC
3342 aliascmd(int argc UNUSED_PARAM, char **argv)
3343 {
3344         char *n, *v;
3345         int ret = 0;
3346         struct alias *ap;
3347
3348         if (!argv[1]) {
3349                 int i;
3350
3351                 for (i = 0; i < ATABSIZE; i++) {
3352                         for (ap = atab[i]; ap; ap = ap->next) {
3353                                 printalias(ap);
3354                         }
3355                 }
3356                 return 0;
3357         }
3358         while ((n = *++argv) != NULL) {
3359                 v = strchr(n+1, '=');
3360                 if (v == NULL) { /* n+1: funny ksh stuff */
3361                         ap = *__lookupalias(n);
3362                         if (ap == NULL) {
3363                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3364                                 ret = 1;
3365                         } else
3366                                 printalias(ap);
3367                 } else {
3368                         *v++ = '\0';
3369                         setalias(n, v);
3370                 }
3371         }
3372
3373         return ret;
3374 }
3375
3376 static int FAST_FUNC
3377 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3378 {
3379         int i;
3380
3381         while (nextopt("a") != '\0') {
3382                 rmaliases();
3383                 return 0;
3384         }
3385         for (i = 0; *argptr; argptr++) {
3386                 if (unalias(*argptr)) {
3387                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3388                         i = 1;
3389                 }
3390         }
3391
3392         return i;
3393 }
3394
3395 #endif /* ASH_ALIAS */
3396
3397
3398 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3399 #define FORK_FG    0
3400 #define FORK_BG    1
3401 #define FORK_NOJOB 2
3402
3403 /* mode flags for showjob(s) */
3404 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3405 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3406 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3407 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3408
3409 /*
3410  * A job structure contains information about a job.  A job is either a
3411  * single process or a set of processes contained in a pipeline.  In the
3412  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3413  * array of pids.
3414  */
3415 struct procstat {
3416         pid_t   ps_pid;         /* process id */
3417         int     ps_status;      /* last process status from wait() */
3418         char    *ps_cmd;        /* text of command being run */
3419 };
3420
3421 struct job {
3422         struct procstat ps0;    /* status of process */
3423         struct procstat *ps;    /* status or processes when more than one */
3424 #if JOBS
3425         int stopstatus;         /* status of a stopped job */
3426 #endif
3427         unsigned nprocs;        /* number of processes */
3428
3429 #define JOBRUNNING      0       /* at least one proc running */
3430 #define JOBSTOPPED      1       /* all procs are stopped */
3431 #define JOBDONE         2       /* all procs are completed */
3432         unsigned
3433                 state: 8,
3434 #if JOBS
3435                 sigint: 1,      /* job was killed by SIGINT */
3436                 jobctl: 1,      /* job running under job control */
3437 #endif
3438                 waited: 1,      /* true if this entry has been waited for */
3439                 used: 1,        /* true if this entry is in used */
3440                 changed: 1;     /* true if status has changed */
3441         struct job *prev_job;   /* previous job */
3442 };
3443
3444 static struct job *makejob(/*union node *,*/ int);
3445 static int forkshell(struct job *, union node *, int);
3446 static int waitforjob(struct job *);
3447
3448 #if !JOBS
3449 enum { doing_jobctl = 0 };
3450 #define setjobctl(on) do {} while (0)
3451 #else
3452 static smallint doing_jobctl; //references:8
3453 static void setjobctl(int);
3454 #endif
3455
3456 /*
3457  * Ignore a signal.
3458  */
3459 static void
3460 ignoresig(int signo)
3461 {
3462         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3463         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3464                 /* No, need to do it */
3465                 signal(signo, SIG_IGN);
3466         }
3467         sigmode[signo - 1] = S_HARD_IGN;
3468 }
3469
3470 /*
3471  * Only one usage site - in setsignal()
3472  */
3473 static void
3474 signal_handler(int signo)
3475 {
3476         if (signo == SIGCHLD) {
3477                 got_sigchld = 1;
3478                 if (!trap[SIGCHLD])
3479                         return;
3480         }
3481
3482         gotsig[signo - 1] = 1;
3483         pending_sig = signo;
3484
3485         if (signo == SIGINT && !trap[SIGINT]) {
3486                 if (!suppress_int) {
3487                         pending_sig = 0;
3488                         raise_interrupt(); /* does not return */
3489                 }
3490                 pending_int = 1;
3491         }
3492 }
3493
3494 /*
3495  * Set the signal handler for the specified signal.  The routine figures
3496  * out what it should be set to.
3497  */
3498 static void
3499 setsignal(int signo)
3500 {
3501         char *t;
3502         char cur_act, new_act;
3503         struct sigaction act;
3504
3505         t = trap[signo];
3506         new_act = S_DFL;
3507         if (t != NULL) { /* trap for this sig is set */
3508                 new_act = S_CATCH;
3509                 if (t[0] == '\0') /* trap is "": ignore this sig */
3510                         new_act = S_IGN;
3511         }
3512
3513         if (rootshell && new_act == S_DFL) {
3514                 switch (signo) {
3515                 case SIGINT:
3516                         if (iflag || minusc || sflag == 0)
3517                                 new_act = S_CATCH;
3518                         break;
3519                 case SIGQUIT:
3520 #if DEBUG
3521                         if (debug)
3522                                 break;
3523 #endif
3524                         /* man bash:
3525                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3526                          * commands run by bash have signal handlers
3527                          * set to the values inherited by the shell
3528                          * from its parent". */
3529                         new_act = S_IGN;
3530                         break;
3531                 case SIGTERM:
3532                         if (iflag)
3533                                 new_act = S_IGN;
3534                         break;
3535 #if JOBS
3536                 case SIGTSTP:
3537                 case SIGTTOU:
3538                         if (mflag)
3539                                 new_act = S_IGN;
3540                         break;
3541 #endif
3542                 }
3543         }
3544         /* if !rootshell, we reset SIGQUIT to DFL,
3545          * whereas we have to restore it to what shell got on entry.
3546          * This is handled by the fact that if signal was IGNored on entry,
3547          * then cur_act is S_HARD_IGN and we never change its sigaction
3548          * (see code below).
3549          */
3550
3551         if (signo == SIGCHLD)
3552                 new_act = S_CATCH;
3553
3554         t = &sigmode[signo - 1];
3555         cur_act = *t;
3556         if (cur_act == 0) {
3557                 /* current setting is not yet known */
3558                 if (sigaction(signo, NULL, &act)) {
3559                         /* pretend it worked; maybe we should give a warning,
3560                          * but other shells don't. We don't alter sigmode,
3561                          * so we retry every time.
3562                          * btw, in Linux it never fails. --vda */
3563                         return;
3564                 }
3565                 if (act.sa_handler == SIG_IGN) {
3566                         cur_act = S_HARD_IGN;
3567                         if (mflag
3568                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3569                         ) {
3570                                 cur_act = S_IGN;   /* don't hard ignore these */
3571                         }
3572                 }
3573                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3574                         /* installing SIG_DFL over SIG_DFL is a no-op */
3575                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3576                         *t = S_DFL;
3577                         return;
3578                 }
3579         }
3580         if (cur_act == S_HARD_IGN || cur_act == new_act)
3581                 return;
3582
3583         *t = new_act;
3584
3585         act.sa_handler = SIG_DFL;
3586         switch (new_act) {
3587         case S_CATCH:
3588                 act.sa_handler = signal_handler;
3589                 break;
3590         case S_IGN:
3591                 act.sa_handler = SIG_IGN;
3592                 break;
3593         }
3594         /* flags and mask matter only if !DFL and !IGN, but we do it
3595          * for all cases for more deterministic behavior:
3596          */
3597         act.sa_flags = 0; //TODO: why not SA_RESTART?
3598         sigfillset(&act.sa_mask);
3599
3600         sigaction_set(signo, &act);
3601 }
3602
3603 /* mode flags for set_curjob */
3604 #define CUR_DELETE 2
3605 #define CUR_RUNNING 1
3606 #define CUR_STOPPED 0
3607
3608 #if JOBS
3609 /* pgrp of shell on invocation */
3610 static int initialpgrp; //references:2
3611 static int ttyfd = -1; //5
3612 #endif
3613 /* array of jobs */
3614 static struct job *jobtab; //5
3615 /* size of array */
3616 static unsigned njobs; //4
3617 /* current job */
3618 static struct job *curjob; //lots
3619 /* number of presumed living untracked jobs */
3620 static int jobless; //4
3621
3622 #if 0
3623 /* Bash has a feature: it restores termios after a successful wait for
3624  * a foreground job which had at least one stopped or sigkilled member.
3625  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3626  * properly restoring tty state. Should we do this too?
3627  * A reproducer: ^Z an interactive python:
3628  *
3629  * # python
3630  * Python 2.7.12 (...)
3631  * >>> ^Z
3632  *      { python leaves tty in -icanon -echo state. We do survive that... }
3633  *  [1]+  Stopped                    python
3634  *      { ...however, next program (python #2) does not survive it well: }
3635  * # python
3636  * Python 2.7.12 (...)
3637  * >>> Traceback (most recent call last):
3638  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3639  *   File "<stdin>", line 1, in <module>
3640  * NameError: name 'qwerty' is not defined
3641  *
3642  * The implementation below is modeled on bash code and seems to work.
3643  * However, I'm not sure we should do this. For one: what if I'd fg
3644  * the stopped python instead? It'll be confused by "restored" tty state.
3645  */
3646 static struct termios shell_tty_info;
3647 static void
3648 get_tty_state(void)
3649 {
3650         if (rootshell && ttyfd >= 0)
3651                 tcgetattr(ttyfd, &shell_tty_info);
3652 }
3653 static void
3654 set_tty_state(void)
3655 {
3656         /* if (rootshell) - caller ensures this */
3657         if (ttyfd >= 0)
3658                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3659 }
3660 static int
3661 job_signal_status(struct job *jp)
3662 {
3663         int status;
3664         unsigned i;
3665         struct procstat *ps = jp->ps;
3666         for (i = 0; i < jp->nprocs; i++) {
3667                 status = ps[i].ps_status;
3668                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3669                         return status;
3670         }
3671         return 0;
3672 }
3673 static void
3674 restore_tty_if_stopped_or_signaled(struct job *jp)
3675 {
3676 //TODO: check what happens if we come from waitforjob() in expbackq()
3677         if (rootshell) {
3678                 int s = job_signal_status(jp);
3679                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3680                         set_tty_state();
3681         }
3682 }
3683 #else
3684 # define get_tty_state() ((void)0)
3685 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3686 #endif
3687
3688 static void
3689 set_curjob(struct job *jp, unsigned mode)
3690 {
3691         struct job *jp1;
3692         struct job **jpp, **curp;
3693
3694         /* first remove from list */
3695         jpp = curp = &curjob;
3696         while (1) {
3697                 jp1 = *jpp;
3698                 if (jp1 == jp)
3699                         break;
3700                 jpp = &jp1->prev_job;
3701         }
3702         *jpp = jp1->prev_job;
3703
3704         /* Then re-insert in correct position */
3705         jpp = curp;
3706         switch (mode) {
3707         default:
3708 #if DEBUG
3709                 abort();
3710 #endif
3711         case CUR_DELETE:
3712                 /* job being deleted */
3713                 break;
3714         case CUR_RUNNING:
3715                 /* newly created job or backgrounded job,
3716                  * put after all stopped jobs.
3717                  */
3718                 while (1) {
3719                         jp1 = *jpp;
3720 #if JOBS
3721                         if (!jp1 || jp1->state != JOBSTOPPED)
3722 #endif
3723                                 break;
3724                         jpp = &jp1->prev_job;
3725                 }
3726                 /* FALLTHROUGH */
3727 #if JOBS
3728         case CUR_STOPPED:
3729 #endif
3730                 /* newly stopped job - becomes curjob */
3731                 jp->prev_job = *jpp;
3732                 *jpp = jp;
3733                 break;
3734         }
3735 }
3736
3737 #if JOBS || DEBUG
3738 static int
3739 jobno(const struct job *jp)
3740 {
3741         return jp - jobtab + 1;
3742 }
3743 #endif
3744
3745 /*
3746  * Convert a job name to a job structure.
3747  */
3748 #if !JOBS
3749 #define getjob(name, getctl) getjob(name)
3750 #endif
3751 static struct job *
3752 getjob(const char *name, int getctl)
3753 {
3754         struct job *jp;
3755         struct job *found;
3756         const char *err_msg = "%s: no such job";
3757         unsigned num;
3758         int c;
3759         const char *p;
3760         char *(*match)(const char *, const char *);
3761
3762         jp = curjob;
3763         p = name;
3764         if (!p)
3765                 goto currentjob;
3766
3767         if (*p != '%')
3768                 goto err;
3769
3770         c = *++p;
3771         if (!c)
3772                 goto currentjob;
3773
3774         if (!p[1]) {
3775                 if (c == '+' || c == '%') {
3776  currentjob:
3777                         err_msg = "No current job";
3778                         goto check;
3779                 }
3780                 if (c == '-') {
3781                         if (jp)
3782                                 jp = jp->prev_job;
3783                         err_msg = "No previous job";
3784  check:
3785                         if (!jp)
3786                                 goto err;
3787                         goto gotit;
3788                 }
3789         }
3790
3791         if (is_number(p)) {
3792                 num = atoi(p);
3793                 if (num > 0 && num <= njobs) {
3794                         jp = jobtab + num - 1;
3795                         if (jp->used)
3796                                 goto gotit;
3797                         goto err;
3798                 }
3799         }
3800
3801         match = prefix;
3802         if (*p == '?') {
3803                 match = strstr;
3804                 p++;
3805         }
3806
3807         found = NULL;
3808         while (jp) {
3809                 if (match(jp->ps[0].ps_cmd, p)) {
3810                         if (found)
3811                                 goto err;
3812                         found = jp;
3813                         err_msg = "%s: ambiguous";
3814                 }
3815                 jp = jp->prev_job;
3816         }
3817         if (!found)
3818                 goto err;
3819         jp = found;
3820
3821  gotit:
3822 #if JOBS
3823         err_msg = "job %s not created under job control";
3824         if (getctl && jp->jobctl == 0)
3825                 goto err;
3826 #endif
3827         return jp;
3828  err:
3829         ash_msg_and_raise_error(err_msg, name);
3830 }
3831
3832 /*
3833  * Mark a job structure as unused.
3834  */
3835 static void
3836 freejob(struct job *jp)
3837 {
3838         struct procstat *ps;
3839         int i;
3840
3841         INT_OFF;
3842         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3843                 if (ps->ps_cmd != nullstr)
3844                         free(ps->ps_cmd);
3845         }
3846         if (jp->ps != &jp->ps0)
3847                 free(jp->ps);
3848         jp->used = 0;
3849         set_curjob(jp, CUR_DELETE);
3850         INT_ON;
3851 }
3852
3853 #if JOBS
3854 static void
3855 xtcsetpgrp(int fd, pid_t pgrp)
3856 {
3857         if (tcsetpgrp(fd, pgrp))
3858                 ash_msg_and_raise_perror("can't set tty process group");
3859 }
3860
3861 /*
3862  * Turn job control on and off.
3863  *
3864  * Note:  This code assumes that the third arg to ioctl is a character
3865  * pointer, which is true on Berkeley systems but not System V.  Since
3866  * System V doesn't have job control yet, this isn't a problem now.
3867  *
3868  * Called with interrupts off.
3869  */
3870 static void
3871 setjobctl(int on)
3872 {
3873         int fd;
3874         int pgrp;
3875
3876         if (on == doing_jobctl || rootshell == 0)
3877                 return;
3878         if (on) {
3879                 int ofd;
3880                 ofd = fd = open(_PATH_TTY, O_RDWR);
3881                 if (fd < 0) {
3882         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3883          * That sometimes helps to acquire controlling tty.
3884          * Obviously, a workaround for bugs when someone
3885          * failed to provide a controlling tty to bash! :) */
3886                         fd = 2;
3887                         while (!isatty(fd))
3888                                 if (--fd < 0)
3889                                         goto out;
3890                 }
3891                 /* fd is a tty at this point */
3892                 fd = fcntl(fd, F_DUPFD, 10);
3893                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3894                         close(ofd);
3895                 if (fd < 0)
3896                         goto out; /* F_DUPFD failed */
3897                 close_on_exec_on(fd);
3898                 while (1) { /* while we are in the background */
3899                         pgrp = tcgetpgrp(fd);
3900                         if (pgrp < 0) {
3901  out:
3902                                 ash_msg("can't access tty; job control turned off");
3903                                 mflag = on = 0;
3904                                 goto close;
3905                         }
3906                         if (pgrp == getpgrp())
3907                                 break;
3908                         killpg(0, SIGTTIN);
3909                 }
3910                 initialpgrp = pgrp;
3911
3912                 setsignal(SIGTSTP);
3913                 setsignal(SIGTTOU);
3914                 setsignal(SIGTTIN);
3915                 pgrp = rootpid;
3916                 setpgid(0, pgrp);
3917                 xtcsetpgrp(fd, pgrp);
3918         } else {
3919                 /* turning job control off */
3920                 fd = ttyfd;
3921                 pgrp = initialpgrp;
3922                 /* was xtcsetpgrp, but this can make exiting ash
3923                  * loop forever if pty is already deleted */
3924                 tcsetpgrp(fd, pgrp);
3925                 setpgid(0, pgrp);
3926                 setsignal(SIGTSTP);
3927                 setsignal(SIGTTOU);
3928                 setsignal(SIGTTIN);
3929  close:
3930                 if (fd >= 0)
3931                         close(fd);
3932                 fd = -1;
3933         }
3934         ttyfd = fd;
3935         doing_jobctl = on;
3936 }
3937
3938 static int FAST_FUNC
3939 killcmd(int argc, char **argv)
3940 {
3941         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3942                 int i = 1;
3943                 do {
3944                         if (argv[i][0] == '%') {
3945                                 /*
3946                                  * "kill %N" - job kill
3947                                  * Converting to pgrp / pid kill
3948                                  */
3949                                 struct job *jp;
3950                                 char *dst;
3951                                 int j, n;
3952
3953                                 jp = getjob(argv[i], 0);
3954                                 /*
3955                                  * In jobs started under job control, we signal
3956                                  * entire process group by kill -PGRP_ID.
3957                                  * This happens, f.e., in interactive shell.
3958                                  *
3959                                  * Otherwise, we signal each child via
3960                                  * kill PID1 PID2 PID3.
3961                                  * Testcases:
3962                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3963                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3964                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3965                                  */
3966                                 n = jp->nprocs; /* can't be 0 (I hope) */
3967                                 if (jp->jobctl)
3968                                         n = 1;
3969                                 dst = alloca(n * sizeof(int)*4);
3970                                 argv[i] = dst;
3971                                 for (j = 0; j < n; j++) {
3972                                         struct procstat *ps = &jp->ps[j];
3973                                         /* Skip non-running and not-stopped members
3974                                          * (i.e. dead members) of the job
3975                                          */
3976                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3977                                                 continue;
3978                                         /*
3979                                          * kill_main has matching code to expect
3980                                          * leading space. Needed to not confuse
3981                                          * negative pids with "kill -SIGNAL_NO" syntax
3982                                          */
3983                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3984                                 }
3985                                 *dst = '\0';
3986                         }
3987                 } while (argv[++i]);
3988         }
3989         return kill_main(argc, argv);
3990 }
3991
3992 static void
3993 showpipe(struct job *jp /*, FILE *out*/)
3994 {
3995         struct procstat *ps;
3996         struct procstat *psend;
3997
3998         psend = jp->ps + jp->nprocs;
3999         for (ps = jp->ps + 1; ps < psend; ps++)
4000                 printf(" | %s", ps->ps_cmd);
4001         newline_and_flush(stdout);
4002         flush_stdout_stderr();
4003 }
4004
4005
4006 static int
4007 restartjob(struct job *jp, int mode)
4008 {
4009         struct procstat *ps;
4010         int i;
4011         int status;
4012         pid_t pgid;
4013
4014         INT_OFF;
4015         if (jp->state == JOBDONE)
4016                 goto out;
4017         jp->state = JOBRUNNING;
4018         pgid = jp->ps[0].ps_pid;
4019         if (mode == FORK_FG) {
4020                 get_tty_state();
4021                 xtcsetpgrp(ttyfd, pgid);
4022         }
4023         killpg(pgid, SIGCONT);
4024         ps = jp->ps;
4025         i = jp->nprocs;
4026         do {
4027                 if (WIFSTOPPED(ps->ps_status)) {
4028                         ps->ps_status = -1;
4029                 }
4030                 ps++;
4031         } while (--i);
4032  out:
4033         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4034         INT_ON;
4035         return status;
4036 }
4037
4038 static int FAST_FUNC
4039 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4040 {
4041         struct job *jp;
4042         int mode;
4043         int retval;
4044
4045         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4046         nextopt(nullstr);
4047         argv = argptr;
4048         do {
4049                 jp = getjob(*argv, 1);
4050                 if (mode == FORK_BG) {
4051                         set_curjob(jp, CUR_RUNNING);
4052                         printf("[%d] ", jobno(jp));
4053                 }
4054                 out1str(jp->ps[0].ps_cmd);
4055                 showpipe(jp /*, stdout*/);
4056                 retval = restartjob(jp, mode);
4057         } while (*argv && *++argv);
4058         return retval;
4059 }
4060 #endif
4061
4062 static int
4063 sprint_status48(char *s, int status, int sigonly)
4064 {
4065         int col;
4066         int st;
4067
4068         col = 0;
4069         if (!WIFEXITED(status)) {
4070 #if JOBS
4071                 if (WIFSTOPPED(status))
4072                         st = WSTOPSIG(status);
4073                 else
4074 #endif
4075                         st = WTERMSIG(status);
4076                 if (sigonly) {
4077                         if (st == SIGINT || st == SIGPIPE)
4078                                 goto out;
4079 #if JOBS
4080                         if (WIFSTOPPED(status))
4081                                 goto out;
4082 #endif
4083                 }
4084                 st &= 0x7f;
4085 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4086                 col = fmtstr(s, 32, strsignal(st));
4087                 if (WCOREDUMP(status)) {
4088                         strcpy(s + col, " (core dumped)");
4089                         col += sizeof(" (core dumped)")-1;
4090                 }
4091         } else if (!sigonly) {
4092                 st = WEXITSTATUS(status);
4093                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4094         }
4095  out:
4096         return col;
4097 }
4098
4099 static int
4100 wait_block_or_sig(int *status)
4101 {
4102         int pid;
4103
4104         do {
4105                 sigset_t mask;
4106
4107                 /* Poll all children for changes in their state */
4108                 got_sigchld = 0;
4109                 /* if job control is active, accept stopped processes too */
4110                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4111                 if (pid != 0)
4112                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4113
4114                 /* Children exist, but none are ready. Sleep until interesting signal */
4115 #if 1
4116                 sigfillset(&mask);
4117                 sigprocmask(SIG_SETMASK, &mask, &mask);
4118                 while (!got_sigchld && !pending_sig)
4119                         sigsuspend(&mask);
4120                 sigprocmask(SIG_SETMASK, &mask, NULL);
4121 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4122                 while (!got_sigchld && !pending_sig)
4123                         pause();
4124 #endif
4125
4126                 /* If it was SIGCHLD, poll children again */
4127         } while (got_sigchld);
4128
4129         return pid;
4130 }
4131
4132 #define DOWAIT_NONBLOCK 0
4133 #define DOWAIT_BLOCK    1
4134 #define DOWAIT_BLOCK_OR_SIG 2
4135
4136 static int
4137 dowait(int block, struct job *job)
4138 {
4139         int pid;
4140         int status;
4141         struct job *jp;
4142         struct job *thisjob = NULL;
4143
4144         TRACE(("dowait(0x%x) called\n", block));
4145
4146         /* It's wrong to call waitpid() outside of INT_OFF region:
4147          * signal can arrive just after syscall return and handler can
4148          * longjmp away, losing stop/exit notification processing.
4149          * Thus, for "jobs" builtin, and for waiting for a fg job,
4150          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4151          *
4152          * However, for "wait" builtin it is wrong to simply call waitpid()
4153          * in INT_OFF region: "wait" needs to wait for any running job
4154          * to change state, but should exit on any trap too.
4155          * In INT_OFF region, a signal just before syscall entry can set
4156          * pending_sig variables, but we can't check them, and we would
4157          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4158          *
4159          * Because of this, we run inside INT_OFF, but use a special routine
4160          * which combines waitpid() and sigsuspend().
4161          * This is the reason why we need to have a handler for SIGCHLD:
4162          * SIG_DFL handler does not wake sigsuspend().
4163          */
4164         INT_OFF;
4165         if (block == DOWAIT_BLOCK_OR_SIG) {
4166                 pid = wait_block_or_sig(&status);
4167         } else {
4168                 int wait_flags = 0;
4169                 if (block == DOWAIT_NONBLOCK)
4170                         wait_flags = WNOHANG;
4171                 /* if job control is active, accept stopped processes too */
4172                 if (doing_jobctl)
4173                         wait_flags |= WUNTRACED;
4174                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4175                 pid = waitpid(-1, &status, wait_flags);
4176         }
4177         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4178                                 pid, status, errno, strerror(errno)));
4179         if (pid <= 0)
4180                 goto out;
4181
4182         thisjob = NULL;
4183         for (jp = curjob; jp; jp = jp->prev_job) {
4184                 int jobstate;
4185                 struct procstat *ps;
4186                 struct procstat *psend;
4187                 if (jp->state == JOBDONE)
4188                         continue;
4189                 jobstate = JOBDONE;
4190                 ps = jp->ps;
4191                 psend = ps + jp->nprocs;
4192                 do {
4193                         if (ps->ps_pid == pid) {
4194                                 TRACE(("Job %d: changing status of proc %d "
4195                                         "from 0x%x to 0x%x\n",
4196                                         jobno(jp), pid, ps->ps_status, status));
4197                                 ps->ps_status = status;
4198                                 thisjob = jp;
4199                         }
4200                         if (ps->ps_status == -1)
4201                                 jobstate = JOBRUNNING;
4202 #if JOBS
4203                         if (jobstate == JOBRUNNING)
4204                                 continue;
4205                         if (WIFSTOPPED(ps->ps_status)) {
4206                                 jp->stopstatus = ps->ps_status;
4207                                 jobstate = JOBSTOPPED;
4208                         }
4209 #endif
4210                 } while (++ps < psend);
4211                 if (!thisjob)
4212                         continue;
4213
4214                 /* Found the job where one of its processes changed its state.
4215                  * Is there at least one live and running process in this job? */
4216                 if (jobstate != JOBRUNNING) {
4217                         /* No. All live processes in the job are stopped
4218                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4219                          */
4220                         thisjob->changed = 1;
4221                         if (thisjob->state != jobstate) {
4222                                 TRACE(("Job %d: changing state from %d to %d\n",
4223                                         jobno(thisjob), thisjob->state, jobstate));
4224                                 thisjob->state = jobstate;
4225 #if JOBS
4226                                 if (jobstate == JOBSTOPPED)
4227                                         set_curjob(thisjob, CUR_STOPPED);
4228 #endif
4229                         }
4230                 }
4231                 goto out;
4232         }
4233         /* The process wasn't found in job list */
4234 #if JOBS
4235         if (!WIFSTOPPED(status))
4236                 jobless--;
4237 #endif
4238  out:
4239         INT_ON;
4240
4241         if (thisjob && thisjob == job) {
4242                 char s[48 + 1];
4243                 int len;
4244
4245                 len = sprint_status48(s, status, 1);
4246                 if (len) {
4247                         s[len] = '\n';
4248                         s[len + 1] = '\0';
4249                         out2str(s);
4250                 }
4251         }
4252         return pid;
4253 }
4254
4255 #if JOBS
4256 static void
4257 showjob(struct job *jp, int mode)
4258 {
4259         struct procstat *ps;
4260         struct procstat *psend;
4261         int col;
4262         int indent_col;
4263         char s[16 + 16 + 48];
4264         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4265
4266         ps = jp->ps;
4267
4268         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4269                 /* just output process (group) id of pipeline */
4270                 fprintf(out, "%d\n", ps->ps_pid);
4271                 return;
4272         }
4273
4274         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4275         indent_col = col;
4276
4277         if (jp == curjob)
4278                 s[col - 3] = '+';
4279         else if (curjob && jp == curjob->prev_job)
4280                 s[col - 3] = '-';
4281
4282         if (mode & SHOW_PIDS)
4283                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4284
4285         psend = ps + jp->nprocs;
4286
4287         if (jp->state == JOBRUNNING) {
4288                 strcpy(s + col, "Running");
4289                 col += sizeof("Running") - 1;
4290         } else {
4291                 int status = psend[-1].ps_status;
4292                 if (jp->state == JOBSTOPPED)
4293                         status = jp->stopstatus;
4294                 col += sprint_status48(s + col, status, 0);
4295         }
4296         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4297
4298         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4299          * or prints several "PID             | <cmdN>" lines,
4300          * depending on SHOW_PIDS bit.
4301          * We do not print status of individual processes
4302          * between PID and <cmdN>. bash does it, but not very well:
4303          * first line shows overall job status, not process status,
4304          * making it impossible to know 1st process status.
4305          */
4306         goto start;
4307         do {
4308                 /* for each process */
4309                 s[0] = '\0';
4310                 col = 33;
4311                 if (mode & SHOW_PIDS)
4312                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4313  start:
4314                 fprintf(out, "%s%*c%s%s",
4315                                 s,
4316                                 33 - col >= 0 ? 33 - col : 0, ' ',
4317                                 ps == jp->ps ? "" : "| ",
4318                                 ps->ps_cmd
4319                 );
4320         } while (++ps != psend);
4321         newline_and_flush(out);
4322
4323         jp->changed = 0;
4324
4325         if (jp->state == JOBDONE) {
4326                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4327                 freejob(jp);
4328         }
4329 }
4330
4331 /*
4332  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4333  * statuses have changed since the last call to showjobs.
4334  */
4335 static void
4336 showjobs(int mode)
4337 {
4338         struct job *jp;
4339
4340         TRACE(("showjobs(0x%x) called\n", mode));
4341
4342         /* Handle all finished jobs */
4343         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4344                 continue;
4345
4346         for (jp = curjob; jp; jp = jp->prev_job) {
4347                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4348                         showjob(jp, mode);
4349                 }
4350         }
4351 }
4352
4353 static int FAST_FUNC
4354 jobscmd(int argc UNUSED_PARAM, char **argv)
4355 {
4356         int mode, m;
4357
4358         mode = 0;
4359         while ((m = nextopt("lp")) != '\0') {
4360                 if (m == 'l')
4361                         mode |= SHOW_PIDS;
4362                 else
4363                         mode |= SHOW_ONLY_PGID;
4364         }
4365
4366         argv = argptr;
4367         if (*argv) {
4368                 do
4369                         showjob(getjob(*argv, 0), mode);
4370                 while (*++argv);
4371         } else {
4372                 showjobs(mode);
4373         }
4374
4375         return 0;
4376 }
4377 #endif /* JOBS */
4378
4379 /* Called only on finished or stopped jobs (no members are running) */
4380 static int
4381 getstatus(struct job *job)
4382 {
4383         int status;
4384         int retval;
4385         struct procstat *ps;
4386
4387         /* Fetch last member's status */
4388         ps = job->ps + job->nprocs - 1;
4389         status = ps->ps_status;
4390         if (pipefail) {
4391                 /* "set -o pipefail" mode: use last _nonzero_ status */
4392                 while (status == 0 && --ps >= job->ps)
4393                         status = ps->ps_status;
4394         }
4395
4396         retval = WEXITSTATUS(status);
4397         if (!WIFEXITED(status)) {
4398 #if JOBS
4399                 retval = WSTOPSIG(status);
4400                 if (!WIFSTOPPED(status))
4401 #endif
4402                 {
4403                         /* XXX: limits number of signals */
4404                         retval = WTERMSIG(status);
4405 #if JOBS
4406                         if (retval == SIGINT)
4407                                 job->sigint = 1;
4408 #endif
4409                 }
4410                 retval += 128;
4411         }
4412         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4413                 jobno(job), job->nprocs, status, retval));
4414         return retval;
4415 }
4416
4417 static int FAST_FUNC
4418 waitcmd(int argc UNUSED_PARAM, char **argv)
4419 {
4420         struct job *job;
4421         int retval;
4422         struct job *jp;
4423
4424         nextopt(nullstr);
4425         retval = 0;
4426
4427         argv = argptr;
4428         if (!*argv) {
4429                 /* wait for all jobs */
4430                 for (;;) {
4431                         jp = curjob;
4432                         while (1) {
4433                                 if (!jp) /* no running procs */
4434                                         goto ret;
4435                                 if (jp->state == JOBRUNNING)
4436                                         break;
4437                                 jp->waited = 1;
4438                                 jp = jp->prev_job;
4439                         }
4440         /* man bash:
4441          * "When bash is waiting for an asynchronous command via
4442          * the wait builtin, the reception of a signal for which a trap
4443          * has been set will cause the wait builtin to return immediately
4444          * with an exit status greater than 128, immediately after which
4445          * the trap is executed."
4446          */
4447                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4448         /* if child sends us a signal *and immediately exits*,
4449          * dowait() returns pid > 0. Check this case,
4450          * not "if (dowait() < 0)"!
4451          */
4452                         if (pending_sig)
4453                                 goto sigout;
4454                 }
4455         }
4456
4457         retval = 127;
4458         do {
4459                 if (**argv != '%') {
4460                         pid_t pid = number(*argv);
4461                         job = curjob;
4462                         while (1) {
4463                                 if (!job)
4464                                         goto repeat;
4465                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4466                                         break;
4467                                 job = job->prev_job;
4468                         }
4469                 } else {
4470                         job = getjob(*argv, 0);
4471                 }
4472                 /* loop until process terminated or stopped */
4473                 while (job->state == JOBRUNNING) {
4474                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4475                         if (pending_sig)
4476                                 goto sigout;
4477                 }
4478                 job->waited = 1;
4479                 retval = getstatus(job);
4480  repeat: ;
4481         } while (*++argv);
4482
4483  ret:
4484         return retval;
4485  sigout:
4486         retval = 128 + pending_sig;
4487         return retval;
4488 }
4489
4490 static struct job *
4491 growjobtab(void)
4492 {
4493         size_t len;
4494         ptrdiff_t offset;
4495         struct job *jp, *jq;
4496
4497         len = njobs * sizeof(*jp);
4498         jq = jobtab;
4499         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4500
4501         offset = (char *)jp - (char *)jq;
4502         if (offset) {
4503                 /* Relocate pointers */
4504                 size_t l = len;
4505
4506                 jq = (struct job *)((char *)jq + l);
4507                 while (l) {
4508                         l -= sizeof(*jp);
4509                         jq--;
4510 #define joff(p) ((struct job *)((char *)(p) + l))
4511 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4512                         if (joff(jp)->ps == &jq->ps0)
4513                                 jmove(joff(jp)->ps);
4514                         if (joff(jp)->prev_job)
4515                                 jmove(joff(jp)->prev_job);
4516                 }
4517                 if (curjob)
4518                         jmove(curjob);
4519 #undef joff
4520 #undef jmove
4521         }
4522
4523         njobs += 4;
4524         jobtab = jp;
4525         jp = (struct job *)((char *)jp + len);
4526         jq = jp + 3;
4527         do {
4528                 jq->used = 0;
4529         } while (--jq >= jp);
4530         return jp;
4531 }
4532
4533 /*
4534  * Return a new job structure.
4535  * Called with interrupts off.
4536  */
4537 static struct job *
4538 makejob(/*union node *node,*/ int nprocs)
4539 {
4540         int i;
4541         struct job *jp;
4542
4543         for (i = njobs, jp = jobtab; ; jp++) {
4544                 if (--i < 0) {
4545                         jp = growjobtab();
4546                         break;
4547                 }
4548                 if (jp->used == 0)
4549                         break;
4550                 if (jp->state != JOBDONE || !jp->waited)
4551                         continue;
4552 #if JOBS
4553                 if (doing_jobctl)
4554                         continue;
4555 #endif
4556                 freejob(jp);
4557                 break;
4558         }
4559         memset(jp, 0, sizeof(*jp));
4560 #if JOBS
4561         /* jp->jobctl is a bitfield.
4562          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4563         if (doing_jobctl)
4564                 jp->jobctl = 1;
4565 #endif
4566         jp->prev_job = curjob;
4567         curjob = jp;
4568         jp->used = 1;
4569         jp->ps = &jp->ps0;
4570         if (nprocs > 1) {
4571                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4572         }
4573         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4574                                 jobno(jp)));
4575         return jp;
4576 }
4577
4578 #if JOBS
4579 /*
4580  * Return a string identifying a command (to be printed by the
4581  * jobs command).
4582  */
4583 static char *cmdnextc;
4584
4585 static void
4586 cmdputs(const char *s)
4587 {
4588         static const char vstype[VSTYPE + 1][3] = {
4589                 "", "}", "-", "+", "?", "=",
4590                 "%", "%%", "#", "##"
4591                 IF_BASH_SUBSTR(, ":")
4592                 IF_BASH_PATTERN_SUBST(, "/", "//")
4593         };
4594
4595         const char *p, *str;
4596         char cc[2];
4597         char *nextc;
4598         unsigned char c;
4599         unsigned char subtype = 0;
4600         int quoted = 0;
4601
4602         cc[1] = '\0';
4603         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4604         p = s;
4605         while ((c = *p++) != '\0') {
4606                 str = NULL;
4607                 switch (c) {
4608                 case CTLESC:
4609                         c = *p++;
4610                         break;
4611                 case CTLVAR:
4612                         subtype = *p++;
4613                         if ((subtype & VSTYPE) == VSLENGTH)
4614                                 str = "${#";
4615                         else
4616                                 str = "${";
4617                         goto dostr;
4618                 case CTLENDVAR:
4619                         str = "\"}" + !(quoted & 1);
4620                         quoted >>= 1;
4621                         subtype = 0;
4622                         goto dostr;
4623                 case CTLBACKQ:
4624                         str = "$(...)";
4625                         goto dostr;
4626 #if ENABLE_FEATURE_SH_MATH
4627                 case CTLARI:
4628                         str = "$((";
4629                         goto dostr;
4630                 case CTLENDARI:
4631                         str = "))";
4632                         goto dostr;
4633 #endif
4634                 case CTLQUOTEMARK:
4635                         quoted ^= 1;
4636                         c = '"';
4637                         break;
4638                 case '=':
4639                         if (subtype == 0)
4640                                 break;
4641                         if ((subtype & VSTYPE) != VSNORMAL)
4642                                 quoted <<= 1;
4643                         str = vstype[subtype & VSTYPE];
4644                         if (subtype & VSNUL)
4645                                 c = ':';
4646                         else
4647                                 goto checkstr;
4648                         break;
4649                 case '\'':
4650                 case '\\':
4651                 case '"':
4652                 case '$':
4653                         /* These can only happen inside quotes */
4654                         cc[0] = c;
4655                         str = cc;
4656 //FIXME:
4657 // $ true $$ &
4658 // $ <cr>
4659 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4660                         c = '\\';
4661                         break;
4662                 default:
4663                         break;
4664                 }
4665                 USTPUTC(c, nextc);
4666  checkstr:
4667                 if (!str)
4668                         continue;
4669  dostr:
4670                 while ((c = *str++) != '\0') {
4671                         USTPUTC(c, nextc);
4672                 }
4673         } /* while *p++ not NUL */
4674
4675         if (quoted & 1) {
4676                 USTPUTC('"', nextc);
4677         }
4678         *nextc = 0;
4679         cmdnextc = nextc;
4680 }
4681
4682 /* cmdtxt() and cmdlist() call each other */
4683 static void cmdtxt(union node *n);
4684
4685 static void
4686 cmdlist(union node *np, int sep)
4687 {
4688         for (; np; np = np->narg.next) {
4689                 if (!sep)
4690                         cmdputs(" ");
4691                 cmdtxt(np);
4692                 if (sep && np->narg.next)
4693                         cmdputs(" ");
4694         }
4695 }
4696
4697 static void
4698 cmdtxt(union node *n)
4699 {
4700         union node *np;
4701         struct nodelist *lp;
4702         const char *p;
4703
4704         if (!n)
4705                 return;
4706         switch (n->type) {
4707         default:
4708 #if DEBUG
4709                 abort();
4710 #endif
4711         case NPIPE:
4712                 lp = n->npipe.cmdlist;
4713                 for (;;) {
4714                         cmdtxt(lp->n);
4715                         lp = lp->next;
4716                         if (!lp)
4717                                 break;
4718                         cmdputs(" | ");
4719                 }
4720                 break;
4721         case NSEMI:
4722                 p = "; ";
4723                 goto binop;
4724         case NAND:
4725                 p = " && ";
4726                 goto binop;
4727         case NOR:
4728                 p = " || ";
4729  binop:
4730                 cmdtxt(n->nbinary.ch1);
4731                 cmdputs(p);
4732                 n = n->nbinary.ch2;
4733                 goto donode;
4734         case NREDIR:
4735         case NBACKGND:
4736                 n = n->nredir.n;
4737                 goto donode;
4738         case NNOT:
4739                 cmdputs("!");
4740                 n = n->nnot.com;
4741  donode:
4742                 cmdtxt(n);
4743                 break;
4744         case NIF:
4745                 cmdputs("if ");
4746                 cmdtxt(n->nif.test);
4747                 cmdputs("; then ");
4748                 if (n->nif.elsepart) {
4749                         cmdtxt(n->nif.ifpart);
4750                         cmdputs("; else ");
4751                         n = n->nif.elsepart;
4752                 } else {
4753                         n = n->nif.ifpart;
4754                 }
4755                 p = "; fi";
4756                 goto dotail;
4757         case NSUBSHELL:
4758                 cmdputs("(");
4759                 n = n->nredir.n;
4760                 p = ")";
4761                 goto dotail;
4762         case NWHILE:
4763                 p = "while ";
4764                 goto until;
4765         case NUNTIL:
4766                 p = "until ";
4767  until:
4768                 cmdputs(p);
4769                 cmdtxt(n->nbinary.ch1);
4770                 n = n->nbinary.ch2;
4771                 p = "; done";
4772  dodo:
4773                 cmdputs("; do ");
4774  dotail:
4775                 cmdtxt(n);
4776                 goto dotail2;
4777         case NFOR:
4778                 cmdputs("for ");
4779                 cmdputs(n->nfor.var);
4780                 cmdputs(" in ");
4781                 cmdlist(n->nfor.args, 1);
4782                 n = n->nfor.body;
4783                 p = "; done";
4784                 goto dodo;
4785         case NDEFUN:
4786                 cmdputs(n->narg.text);
4787                 p = "() { ... }";
4788                 goto dotail2;
4789         case NCMD:
4790                 cmdlist(n->ncmd.args, 1);
4791                 cmdlist(n->ncmd.redirect, 0);
4792                 break;
4793         case NARG:
4794                 p = n->narg.text;
4795  dotail2:
4796                 cmdputs(p);
4797                 break;
4798         case NHERE:
4799         case NXHERE:
4800                 p = "<<...";
4801                 goto dotail2;
4802         case NCASE:
4803                 cmdputs("case ");
4804                 cmdputs(n->ncase.expr->narg.text);
4805                 cmdputs(" in ");
4806                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4807                         cmdtxt(np->nclist.pattern);
4808                         cmdputs(") ");
4809                         cmdtxt(np->nclist.body);
4810                         cmdputs(";; ");
4811                 }
4812                 p = "esac";
4813                 goto dotail2;
4814         case NTO:
4815                 p = ">";
4816                 goto redir;
4817         case NCLOBBER:
4818                 p = ">|";
4819                 goto redir;
4820         case NAPPEND:
4821                 p = ">>";
4822                 goto redir;
4823 #if BASH_REDIR_OUTPUT
4824         case NTO2:
4825 #endif
4826         case NTOFD:
4827                 p = ">&";
4828                 goto redir;
4829         case NFROM:
4830                 p = "<";
4831                 goto redir;
4832         case NFROMFD:
4833                 p = "<&";
4834                 goto redir;
4835         case NFROMTO:
4836                 p = "<>";
4837  redir:
4838                 cmdputs(utoa(n->nfile.fd));
4839                 cmdputs(p);
4840                 if (n->type == NTOFD || n->type == NFROMFD) {
4841                         if (n->ndup.dupfd >= 0)
4842                                 cmdputs(utoa(n->ndup.dupfd));
4843                         else
4844                                 cmdputs("-");
4845                         break;
4846                 }
4847                 n = n->nfile.fname;
4848                 goto donode;
4849         }
4850 }
4851
4852 static char *
4853 commandtext(union node *n)
4854 {
4855         char *name;
4856
4857         STARTSTACKSTR(cmdnextc);
4858         cmdtxt(n);
4859         name = stackblock();
4860         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4861         return ckstrdup(name);
4862 }
4863 #endif /* JOBS */
4864
4865 /*
4866  * Fork off a subshell.  If we are doing job control, give the subshell its
4867  * own process group.  Jp is a job structure that the job is to be added to.
4868  * N is the command that will be evaluated by the child.  Both jp and n may
4869  * be NULL.  The mode parameter can be one of the following:
4870  *      FORK_FG - Fork off a foreground process.
4871  *      FORK_BG - Fork off a background process.
4872  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4873  *                   process group even if job control is on.
4874  *
4875  * When job control is turned off, background processes have their standard
4876  * input redirected to /dev/null (except for the second and later processes
4877  * in a pipeline).
4878  *
4879  * Called with interrupts off.
4880  */
4881 /*
4882  * Clear traps on a fork.
4883  */
4884 static void
4885 clear_traps(void)
4886 {
4887         char **tp;
4888
4889         INT_OFF;
4890         for (tp = trap; tp < &trap[NSIG]; tp++) {
4891                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4892                         if (trap_ptr == trap)
4893                                 free(*tp);
4894                         /* else: it "belongs" to trap_ptr vector, don't free */
4895                         *tp = NULL;
4896                         if ((tp - trap) != 0)
4897                                 setsignal(tp - trap);
4898                 }
4899         }
4900         may_have_traps = 0;
4901         INT_ON;
4902 }
4903
4904 /* Lives far away from here, needed for forkchild */
4905 static void closescript(void);
4906
4907 /* Called after fork(), in child */
4908 /* jp and n are NULL when called by openhere() for heredoc support */
4909 static NOINLINE void
4910 forkchild(struct job *jp, union node *n, int mode)
4911 {
4912         int oldlvl;
4913
4914         TRACE(("Child shell %d\n", getpid()));
4915         oldlvl = shlvl;
4916         shlvl++;
4917
4918         /* man bash: "Non-builtin commands run by bash have signal handlers
4919          * set to the values inherited by the shell from its parent".
4920          * Do we do it correctly? */
4921
4922         closescript();
4923
4924         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4925          && n && n->type == NCMD        /* is it single cmd? */
4926         /* && n->ncmd.args->type == NARG - always true? */
4927          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4928          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4929         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4930         ) {
4931                 TRACE(("Trap hack\n"));
4932                 /* Awful hack for `trap` or $(trap).
4933                  *
4934                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4935                  * contains an example where "trap" is executed in a subshell:
4936                  *
4937                  * save_traps=$(trap)
4938                  * ...
4939                  * eval "$save_traps"
4940                  *
4941                  * Standard does not say that "trap" in subshell shall print
4942                  * parent shell's traps. It only says that its output
4943                  * must have suitable form, but then, in the above example
4944                  * (which is not supposed to be normative), it implies that.
4945                  *
4946                  * bash (and probably other shell) does implement it
4947                  * (traps are reset to defaults, but "trap" still shows them),
4948                  * but as a result, "trap" logic is hopelessly messed up:
4949                  *
4950                  * # trap
4951                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4952                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4953                  * # true | trap   <--- trap is in subshell - no output (ditto)
4954                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4955                  * trap -- 'echo Ho' SIGWINCH
4956                  * # echo `(trap)`         <--- in subshell in subshell - output
4957                  * trap -- 'echo Ho' SIGWINCH
4958                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4959                  * trap -- 'echo Ho' SIGWINCH
4960                  *
4961                  * The rules when to forget and when to not forget traps
4962                  * get really complex and nonsensical.
4963                  *
4964                  * Our solution: ONLY bare $(trap) or `trap` is special.
4965                  */
4966                 /* Save trap handler strings for trap builtin to print */
4967                 trap_ptr = xmemdup(trap, sizeof(trap));
4968                 /* Fall through into clearing traps */
4969         }
4970         clear_traps();
4971 #if JOBS
4972         /* do job control only in root shell */
4973         doing_jobctl = 0;
4974         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4975                 pid_t pgrp;
4976
4977                 if (jp->nprocs == 0)
4978                         pgrp = getpid();
4979                 else
4980                         pgrp = jp->ps[0].ps_pid;
4981                 /* this can fail because we are doing it in the parent also */
4982                 setpgid(0, pgrp);
4983                 if (mode == FORK_FG)
4984                         xtcsetpgrp(ttyfd, pgrp);
4985                 setsignal(SIGTSTP);
4986                 setsignal(SIGTTOU);
4987         } else
4988 #endif
4989         if (mode == FORK_BG) {
4990                 /* man bash: "When job control is not in effect,
4991                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4992                 ignoresig(SIGINT);
4993                 ignoresig(SIGQUIT);
4994                 if (jp->nprocs == 0) {
4995                         close(0);
4996                         if (open(bb_dev_null, O_RDONLY) != 0)
4997                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4998                 }
4999         }
5000         if (oldlvl == 0) {
5001                 if (iflag) { /* why if iflag only? */
5002                         setsignal(SIGINT);
5003                         setsignal(SIGTERM);
5004                 }
5005                 /* man bash:
5006                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5007                  * commands run by bash have signal handlers
5008                  * set to the values inherited by the shell
5009                  * from its parent".
5010                  * Take care of the second rule: */
5011                 setsignal(SIGQUIT);
5012         }
5013 #if JOBS
5014         if (n && n->type == NCMD
5015          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5016         ) {
5017                 TRACE(("Job hack\n"));
5018                 /* "jobs": we do not want to clear job list for it,
5019                  * instead we remove only _its_ own_ job from job list.
5020                  * This makes "jobs .... | cat" more useful.
5021                  */
5022                 freejob(curjob);
5023                 return;
5024         }
5025 #endif
5026         for (jp = curjob; jp; jp = jp->prev_job)
5027                 freejob(jp);
5028         jobless = 0;
5029 }
5030
5031 /* Called after fork(), in parent */
5032 #if !JOBS
5033 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5034 #endif
5035 static void
5036 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5037 {
5038         TRACE(("In parent shell: child = %d\n", pid));
5039         if (!jp) {
5040                 /* jp is NULL when called by openhere() for heredoc support */
5041                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5042                         continue;
5043                 jobless++;
5044                 return;
5045         }
5046 #if JOBS
5047         if (mode != FORK_NOJOB && jp->jobctl) {
5048                 int pgrp;
5049
5050                 if (jp->nprocs == 0)
5051                         pgrp = pid;
5052                 else
5053                         pgrp = jp->ps[0].ps_pid;
5054                 /* This can fail because we are doing it in the child also */
5055                 setpgid(pid, pgrp);
5056         }
5057 #endif
5058         if (mode == FORK_BG) {
5059                 backgndpid = pid;               /* set $! */
5060                 set_curjob(jp, CUR_RUNNING);
5061         }
5062         if (jp) {
5063                 struct procstat *ps = &jp->ps[jp->nprocs++];
5064                 ps->ps_pid = pid;
5065                 ps->ps_status = -1;
5066                 ps->ps_cmd = nullstr;
5067 #if JOBS
5068                 if (doing_jobctl && n)
5069                         ps->ps_cmd = commandtext(n);
5070 #endif
5071         }
5072 }
5073
5074 /* jp and n are NULL when called by openhere() for heredoc support */
5075 static int
5076 forkshell(struct job *jp, union node *n, int mode)
5077 {
5078         int pid;
5079
5080         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5081         pid = fork();
5082         if (pid < 0) {
5083                 TRACE(("Fork failed, errno=%d", errno));
5084                 if (jp)
5085                         freejob(jp);
5086                 ash_msg_and_raise_error("can't fork");
5087         }
5088         if (pid == 0) {
5089                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5090                 forkchild(jp, n, mode);
5091         } else {
5092                 forkparent(jp, n, mode, pid);
5093         }
5094         return pid;
5095 }
5096
5097 /*
5098  * Wait for job to finish.
5099  *
5100  * Under job control we have the problem that while a child process
5101  * is running interrupts generated by the user are sent to the child
5102  * but not to the shell.  This means that an infinite loop started by
5103  * an interactive user may be hard to kill.  With job control turned off,
5104  * an interactive user may place an interactive program inside a loop.
5105  * If the interactive program catches interrupts, the user doesn't want
5106  * these interrupts to also abort the loop.  The approach we take here
5107  * is to have the shell ignore interrupt signals while waiting for a
5108  * foreground process to terminate, and then send itself an interrupt
5109  * signal if the child process was terminated by an interrupt signal.
5110  * Unfortunately, some programs want to do a bit of cleanup and then
5111  * exit on interrupt; unless these processes terminate themselves by
5112  * sending a signal to themselves (instead of calling exit) they will
5113  * confuse this approach.
5114  *
5115  * Called with interrupts off.
5116  */
5117 static int
5118 waitforjob(struct job *jp)
5119 {
5120         int st;
5121
5122         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5123
5124         INT_OFF;
5125         while (jp->state == JOBRUNNING) {
5126                 /* In non-interactive shells, we _can_ get
5127                  * a keyboard signal here and be EINTRed,
5128                  * but we just loop back, waiting for command to complete.
5129                  *
5130                  * man bash:
5131                  * "If bash is waiting for a command to complete and receives
5132                  * a signal for which a trap has been set, the trap
5133                  * will not be executed until the command completes."
5134                  *
5135                  * Reality is that even if trap is not set, bash
5136                  * will not act on the signal until command completes.
5137                  * Try this. sleep5intoff.c:
5138                  * #include <signal.h>
5139                  * #include <unistd.h>
5140                  * int main() {
5141                  *         sigset_t set;
5142                  *         sigemptyset(&set);
5143                  *         sigaddset(&set, SIGINT);
5144                  *         sigaddset(&set, SIGQUIT);
5145                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5146                  *         sleep(5);
5147                  *         return 0;
5148                  * }
5149                  * $ bash -c './sleep5intoff; echo hi'
5150                  * ^C^C^C^C <--- pressing ^C once a second
5151                  * $ _
5152                  * $ bash -c './sleep5intoff; echo hi'
5153                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5154                  * $ _
5155                  */
5156                 dowait(DOWAIT_BLOCK, jp);
5157         }
5158         INT_ON;
5159
5160         st = getstatus(jp);
5161 #if JOBS
5162         if (jp->jobctl) {
5163                 xtcsetpgrp(ttyfd, rootpid);
5164                 restore_tty_if_stopped_or_signaled(jp);
5165
5166                 /*
5167                  * This is truly gross.
5168                  * If we're doing job control, then we did a TIOCSPGRP which
5169                  * caused us (the shell) to no longer be in the controlling
5170                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5171                  * intuit from the subprocess exit status whether a SIGINT
5172                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5173                  */
5174                 if (jp->sigint) /* TODO: do the same with all signals */
5175                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5176         }
5177         if (jp->state == JOBDONE)
5178 #endif
5179                 freejob(jp);
5180         return st;
5181 }
5182
5183 /*
5184  * return 1 if there are stopped jobs, otherwise 0
5185  */
5186 static int
5187 stoppedjobs(void)
5188 {
5189         struct job *jp;
5190         int retval;
5191
5192         retval = 0;
5193         if (job_warning)
5194                 goto out;
5195         jp = curjob;
5196         if (jp && jp->state == JOBSTOPPED) {
5197                 out2str("You have stopped jobs.\n");
5198                 job_warning = 2;
5199                 retval++;
5200         }
5201  out:
5202         return retval;
5203 }
5204
5205
5206 /*
5207  * Code for dealing with input/output redirection.
5208  */
5209
5210 #undef EMPTY
5211 #undef CLOSED
5212 #define EMPTY -2                /* marks an unused slot in redirtab */
5213 #define CLOSED -1               /* marks a slot of previously-closed fd */
5214
5215 /*
5216  * Handle here documents.  Normally we fork off a process to write the
5217  * data to a pipe.  If the document is short, we can stuff the data in
5218  * the pipe without forking.
5219  */
5220 /* openhere needs this forward reference */
5221 static void expandhere(union node *arg, int fd);
5222 static int
5223 openhere(union node *redir)
5224 {
5225         int pip[2];
5226         size_t len = 0;
5227
5228         if (pipe(pip) < 0)
5229                 ash_msg_and_raise_error("pipe call failed");
5230         if (redir->type == NHERE) {
5231                 len = strlen(redir->nhere.doc->narg.text);
5232                 if (len <= PIPE_BUF) {
5233                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5234                         goto out;
5235                 }
5236         }
5237         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5238                 /* child */
5239                 close(pip[0]);
5240                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5241                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5242                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5243                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5244                 signal(SIGPIPE, SIG_DFL);
5245                 if (redir->type == NHERE)
5246                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5247                 else /* NXHERE */
5248                         expandhere(redir->nhere.doc, pip[1]);
5249                 _exit(EXIT_SUCCESS);
5250         }
5251  out:
5252         close(pip[1]);
5253         return pip[0];
5254 }
5255
5256 static int
5257 openredirect(union node *redir)
5258 {
5259         struct stat sb;
5260         char *fname;
5261         int f;
5262
5263         switch (redir->nfile.type) {
5264 /* Can't happen, our single caller does this itself */
5265 //      case NTOFD:
5266 //      case NFROMFD:
5267 //              return -1;
5268         case NHERE:
5269         case NXHERE:
5270                 return openhere(redir);
5271         }
5272
5273         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5274          * allocated space. Do it only when we know it is safe.
5275          */
5276         fname = redir->nfile.expfname;
5277
5278         switch (redir->nfile.type) {
5279         default:
5280 #if DEBUG
5281                 abort();
5282 #endif
5283         case NFROM:
5284                 f = open(fname, O_RDONLY);
5285                 if (f < 0)
5286                         goto eopen;
5287                 break;
5288         case NFROMTO:
5289                 f = open(fname, O_RDWR|O_CREAT, 0666);
5290                 if (f < 0)
5291                         goto ecreate;
5292                 break;
5293         case NTO:
5294 #if BASH_REDIR_OUTPUT
5295         case NTO2:
5296 #endif
5297                 /* Take care of noclobber mode. */
5298                 if (Cflag) {
5299                         if (stat(fname, &sb) < 0) {
5300                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5301                                 if (f < 0)
5302                                         goto ecreate;
5303                         } else if (!S_ISREG(sb.st_mode)) {
5304                                 f = open(fname, O_WRONLY, 0666);
5305                                 if (f < 0)
5306                                         goto ecreate;
5307                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5308                                         close(f);
5309                                         errno = EEXIST;
5310                                         goto ecreate;
5311                                 }
5312                         } else {
5313                                 errno = EEXIST;
5314                                 goto ecreate;
5315                         }
5316                         break;
5317                 }
5318                 /* FALLTHROUGH */
5319         case NCLOBBER:
5320                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5321                 if (f < 0)
5322                         goto ecreate;
5323                 break;
5324         case NAPPEND:
5325                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5326                 if (f < 0)
5327                         goto ecreate;
5328                 break;
5329         }
5330
5331         return f;
5332  ecreate:
5333         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5334  eopen:
5335         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5336 }
5337
5338 /*
5339  * Copy a file descriptor to be >= 10. Throws exception on error.
5340  */
5341 static int
5342 savefd(int from)
5343 {
5344         int newfd;
5345         int err;
5346
5347         newfd = fcntl(from, F_DUPFD, 10);
5348         err = newfd < 0 ? errno : 0;
5349         if (err != EBADF) {
5350                 if (err)
5351                         ash_msg_and_raise_perror("%d", from);
5352                 close(from);
5353                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5354         }
5355
5356         return newfd;
5357 }
5358 static int
5359 dup2_or_raise(int from, int to)
5360 {
5361         int newfd;
5362
5363         newfd = (from != to) ? dup2(from, to) : to;
5364         if (newfd < 0) {
5365                 /* Happens when source fd is not open: try "echo >&99" */
5366                 ash_msg_and_raise_perror("%d", from);
5367         }
5368         return newfd;
5369 }
5370 static int
5371 fcntl_F_DUPFD(int fd, int avoid_fd)
5372 {
5373         int newfd;
5374  repeat:
5375         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5376         if (newfd < 0) {
5377                 if (errno == EBUSY)
5378                         goto repeat;
5379                 if (errno == EINTR)
5380                         goto repeat;
5381         }
5382         return newfd;
5383 }
5384 static int
5385 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5386 {
5387         int newfd;
5388  repeat:
5389         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5390         if (newfd < 0) {
5391                 if (errno == EBUSY)
5392                         goto repeat;
5393                 if (errno == EINTR)
5394                         goto repeat;
5395                 /* fd was not open? */
5396                 if (errno == EBADF)
5397                         return fd;
5398                 ash_msg_and_raise_perror("%d", newfd);
5399         }
5400         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5401         close(fd);
5402         return newfd;
5403 }
5404
5405 /* Struct def and variable are moved down to the first usage site */
5406 struct squirrel {
5407         int orig_fd;
5408         int moved_to;
5409 };
5410 struct redirtab {
5411         struct redirtab *next;
5412         int pair_count;
5413         struct squirrel two_fd[];
5414 };
5415 #define redirlist (G_var.redirlist)
5416
5417 static void
5418 add_squirrel_closed(struct redirtab *sq, int fd)
5419 {
5420         int i;
5421
5422         if (!sq)
5423                 return;
5424
5425         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5426                 /* If we collide with an already moved fd... */
5427                 if (fd == sq->two_fd[i].orig_fd) {
5428                         /* Examples:
5429                          * "echo 3>FILE 3>&- 3>FILE"
5430                          * "echo 3>&- 3>FILE"
5431                          * No need for last redirect to insert
5432                          * another "need to close 3" indicator.
5433                          */
5434                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5435                         return;
5436                 }
5437         }
5438         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5439         sq->two_fd[i].orig_fd = fd;
5440         sq->two_fd[i].moved_to = CLOSED;
5441 }
5442
5443 static int
5444 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5445 {
5446         int i, new_fd;
5447
5448         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5449                 avoid_fd = 9;
5450
5451 #if JOBS
5452         if (fd == ttyfd) {
5453                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5454                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5455                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5456                 return 1; /* "we closed fd" */
5457         }
5458 #endif
5459         /* Are we called from redirect(0)? E.g. redirect
5460          * in a forked child. No need to save fds,
5461          * we aren't going to use them anymore, ok to trash.
5462          */
5463         if (!sq)
5464                 return 0;
5465
5466         /* If this one of script's fds? */
5467         if (fd != 0) {
5468                 struct parsefile *pf = g_parsefile;
5469                 while (pf) {
5470                         /* We skip fd == 0 case because of the following:
5471                          * $ ash  # running ash interactively
5472                          * $ . ./script.sh
5473                          * and in script.sh: "exec 9>&0".
5474                          * Even though top-level pf_fd _is_ 0,
5475                          * it's still ok to use it: "read" builtin uses it,
5476                          * why should we cripple "exec" builtin?
5477                          */
5478                         if (fd == pf->pf_fd) {
5479                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5480                                 return 1; /* "we closed fd" */
5481                         }
5482                         pf = pf->prev;
5483                 }
5484         }
5485
5486         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5487
5488         /* First: do we collide with some already moved fds? */
5489         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5490                 /* If we collide with an already moved fd... */
5491                 if (fd == sq->two_fd[i].moved_to) {
5492                         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5493                         sq->two_fd[i].moved_to = new_fd;
5494                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5495                         if (new_fd < 0) /* what? */
5496                                 xfunc_die();
5497                         return 0; /* "we did not close fd" */
5498                 }
5499                 if (fd == sq->two_fd[i].orig_fd) {
5500                         /* Example: echo Hello >/dev/null 1>&2 */
5501                         TRACE(("redirect_fd %d: already moved\n", fd));
5502                         return 0; /* "we did not close fd" */
5503                 }
5504         }
5505
5506         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5507         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5508         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5509         if (new_fd < 0) {
5510                 if (errno != EBADF)
5511                         xfunc_die();
5512                 /* new_fd = CLOSED; - already is -1 */
5513         }
5514         sq->two_fd[i].moved_to = new_fd;
5515         sq->two_fd[i].orig_fd = fd;
5516
5517         /* if we move stderr, let "set -x" code know */
5518         if (fd == preverrout_fd)
5519                 preverrout_fd = new_fd;
5520
5521         return 0; /* "we did not close fd" */
5522 }
5523
5524 static int
5525 internally_opened_fd(int fd, struct redirtab *sq)
5526 {
5527         int i;
5528 #if JOBS
5529         if (fd == ttyfd)
5530                 return 1;
5531 #endif
5532         /* If this one of script's fds? */
5533         if (fd != 0) {
5534                 struct parsefile *pf = g_parsefile;
5535                 while (pf) {
5536                         if (fd == pf->pf_fd)
5537                                 return 1;
5538                         pf = pf->prev;
5539                 }
5540         }
5541
5542         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5543                 if (fd == sq->two_fd[i].moved_to)
5544                         return 1;
5545         }
5546         return 0;
5547 }
5548
5549 /*
5550  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5551  * old file descriptors are stashed away so that the redirection can be
5552  * undone by calling popredir.
5553  */
5554 /* flags passed to redirect */
5555 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5556 static void
5557 redirect(union node *redir, int flags)
5558 {
5559         struct redirtab *sv;
5560
5561         if (!redir)
5562                 return;
5563
5564         sv = NULL;
5565         INT_OFF;
5566         if (flags & REDIR_PUSH)
5567                 sv = redirlist;
5568         do {
5569                 int fd;
5570                 int newfd;
5571                 int close_fd;
5572                 int closed;
5573
5574                 fd = redir->nfile.fd;
5575                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5576                         //bb_error_msg("doing %d > %d", fd, newfd);
5577                         newfd = redir->ndup.dupfd;
5578                         close_fd = -1;
5579                 } else {
5580                         newfd = openredirect(redir); /* always >= 0 */
5581                         if (fd == newfd) {
5582                                 /* open() gave us precisely the fd we wanted.
5583                                  * This means that this fd was not busy
5584                                  * (not opened to anywhere).
5585                                  * Remember to close it on restore:
5586                                  */
5587                                 add_squirrel_closed(sv, fd);
5588                                 continue;
5589                         }
5590                         close_fd = newfd;
5591                 }
5592
5593                 if (fd == newfd)
5594                         continue;
5595
5596                 /* if "N>FILE": move newfd to fd */
5597                 /* if "N>&M": dup newfd to fd */
5598                 /* if "N>&-": close fd (newfd is -1) */
5599
5600  IF_BASH_REDIR_OUTPUT(redirect_more:)
5601
5602                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5603                 if (newfd == -1) {
5604                         /* "N>&-" means "close me" */
5605                         if (!closed) {
5606                                 /* ^^^ optimization: saving may already
5607                                  * have closed it. If not... */
5608                                 close(fd);
5609                         }
5610                 } else {
5611                         /* if newfd is a script fd or saved fd, simulate EBADF */
5612                         if (internally_opened_fd(newfd, sv)) {
5613                                 errno = EBADF;
5614                                 ash_msg_and_raise_perror("%d", newfd);
5615                         }
5616                         dup2_or_raise(newfd, fd);
5617                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5618                                 close(close_fd);
5619 #if BASH_REDIR_OUTPUT
5620                         if (redir->nfile.type == NTO2 && fd == 1) {
5621                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5622                                 fd = 2;
5623                                 newfd = 1;
5624                                 close_fd = -1;
5625                                 goto redirect_more;
5626                         }
5627 #endif
5628                 }
5629         } while ((redir = redir->nfile.next) != NULL);
5630         INT_ON;
5631
5632 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5633 #define REDIR_SAVEFD2 0
5634         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5635         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5636         // not only for calls with flags containing REDIR_SAVEFD2.
5637         // We do this unconditionally (see save_fd_on_redirect()).
5638         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5639         //      preverrout_fd = copied_fd2;
5640 }
5641
5642 static int
5643 redirectsafe(union node *redir, int flags)
5644 {
5645         int err;
5646         volatile int saveint;
5647         struct jmploc *volatile savehandler = exception_handler;
5648         struct jmploc jmploc;
5649
5650         SAVE_INT(saveint);
5651         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5652         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5653         if (!err) {
5654                 exception_handler = &jmploc;
5655                 redirect(redir, flags);
5656         }
5657         exception_handler = savehandler;
5658         if (err && exception_type != EXERROR)
5659                 longjmp(exception_handler->loc, 1);
5660         RESTORE_INT(saveint);
5661         return err;
5662 }
5663
5664 static struct redirtab*
5665 pushredir(union node *redir)
5666 {
5667         struct redirtab *sv;
5668         int i;
5669
5670         if (!redir)
5671                 return redirlist;
5672
5673         i = 0;
5674         do {
5675                 i++;
5676 #if BASH_REDIR_OUTPUT
5677                 if (redir->nfile.type == NTO2)
5678                         i++;
5679 #endif
5680                 redir = redir->nfile.next;
5681         } while (redir);
5682
5683         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5684         sv->pair_count = i;
5685         while (--i >= 0)
5686                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5687         sv->next = redirlist;
5688         redirlist = sv;
5689         return sv->next;
5690 }
5691
5692 /*
5693  * Undo the effects of the last redirection.
5694  */
5695 static void
5696 popredir(int drop)
5697 {
5698         struct redirtab *rp;
5699         int i;
5700
5701         if (redirlist == NULL)
5702                 return;
5703         INT_OFF;
5704         rp = redirlist;
5705         for (i = 0; i < rp->pair_count; i++) {
5706                 int fd = rp->two_fd[i].orig_fd;
5707                 int copy = rp->two_fd[i].moved_to;
5708                 if (copy == CLOSED) {
5709                         if (!drop)
5710                                 close(fd);
5711                         continue;
5712                 }
5713                 if (copy != EMPTY) {
5714                         if (!drop) {
5715                                 /*close(fd);*/
5716                                 dup2_or_raise(copy, fd);
5717                         }
5718                         close(copy);
5719                 }
5720         }
5721         redirlist = rp->next;
5722         free(rp);
5723         INT_ON;
5724 }
5725
5726 static void
5727 unwindredir(struct redirtab *stop)
5728 {
5729         while (redirlist != stop)
5730                 popredir(/*drop:*/ 0);
5731 }
5732
5733
5734 /* ============ Routines to expand arguments to commands
5735  *
5736  * We have to deal with backquotes, shell variables, and file metacharacters.
5737  */
5738
5739 #if ENABLE_FEATURE_SH_MATH
5740 static arith_t
5741 ash_arith(const char *s)
5742 {
5743         arith_state_t math_state;
5744         arith_t result;
5745
5746         math_state.lookupvar = lookupvar;
5747         math_state.setvar    = setvar0;
5748         //math_state.endofname = endofname;
5749
5750         INT_OFF;
5751         result = arith(&math_state, s);
5752         if (math_state.errmsg)
5753                 ash_msg_and_raise_error(math_state.errmsg);
5754         INT_ON;
5755
5756         return result;
5757 }
5758 #endif
5759
5760 /*
5761  * expandarg flags
5762  */
5763 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5764 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5765 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5766 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5767 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5768  * POSIX says for this case:
5769  *  Pathname expansion shall not be performed on the word by a
5770  *  non-interactive shell; an interactive shell may perform it, but shall
5771  *  do so only when the expansion would result in one word.
5772  * Currently, our code complies to the above rule by never globbing
5773  * redirection filenames.
5774  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5775  * (this means that on a typical Linux distro, bash almost always
5776  * performs globbing, and thus diverges from what we do).
5777  */
5778 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5779 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5780 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5781 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5782 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5783 /*
5784  * rmescape() flags
5785  */
5786 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5787 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5788 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5789 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5790 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5791
5792 /* Add CTLESC when necessary. */
5793 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5794 /* Do not skip NUL characters. */
5795 #define QUOTES_KEEPNUL EXP_TILDE
5796
5797 /*
5798  * Structure specifying which parts of the string should be searched
5799  * for IFS characters.
5800  */
5801 struct ifsregion {
5802         struct ifsregion *next; /* next region in list */
5803         int begoff;             /* offset of start of region */
5804         int endoff;             /* offset of end of region */
5805         int nulonly;            /* search for nul bytes only */
5806 };
5807
5808 struct arglist {
5809         struct strlist *list;
5810         struct strlist **lastp;
5811 };
5812
5813 /* output of current string */
5814 static char *expdest;
5815 /* list of back quote expressions */
5816 static struct nodelist *argbackq;
5817 /* first struct in list of ifs regions */
5818 static struct ifsregion ifsfirst;
5819 /* last struct in list */
5820 static struct ifsregion *ifslastp;
5821 /* holds expanded arg list */
5822 static struct arglist exparg;
5823
5824 /*
5825  * Our own itoa().
5826  * cvtnum() is used even if math support is off (to prepare $? values and such).
5827  */
5828 static int
5829 cvtnum(arith_t num)
5830 {
5831         int len;
5832
5833         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5834         len = sizeof(arith_t) * 3;
5835         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5836         if (sizeof(arith_t) < 4) len += 2;
5837
5838         expdest = makestrspace(len, expdest);
5839         len = fmtstr(expdest, len, ARITH_FMT, num);
5840         STADJUST(len, expdest);
5841         return len;
5842 }
5843
5844 /*
5845  * Break the argument string into pieces based upon IFS and add the
5846  * strings to the argument list.  The regions of the string to be
5847  * searched for IFS characters have been stored by recordregion.
5848  */
5849 static void
5850 ifsbreakup(char *string, struct arglist *arglist)
5851 {
5852         struct ifsregion *ifsp;
5853         struct strlist *sp;
5854         char *start;
5855         char *p;
5856         char *q;
5857         const char *ifs, *realifs;
5858         int ifsspc;
5859         int nulonly;
5860
5861         start = string;
5862         if (ifslastp != NULL) {
5863                 ifsspc = 0;
5864                 nulonly = 0;
5865                 realifs = ifsset() ? ifsval() : defifs;
5866                 ifsp = &ifsfirst;
5867                 do {
5868                         p = string + ifsp->begoff;
5869                         nulonly = ifsp->nulonly;
5870                         ifs = nulonly ? nullstr : realifs;
5871                         ifsspc = 0;
5872                         while (p < string + ifsp->endoff) {
5873                                 q = p;
5874                                 if ((unsigned char)*p == CTLESC)
5875                                         p++;
5876                                 if (!strchr(ifs, *p)) {
5877                                         p++;
5878                                         continue;
5879                                 }
5880                                 if (!nulonly)
5881                                         ifsspc = (strchr(defifs, *p) != NULL);
5882                                 /* Ignore IFS whitespace at start */
5883                                 if (q == start && ifsspc) {
5884                                         p++;
5885                                         start = p;
5886                                         continue;
5887                                 }
5888                                 *q = '\0';
5889                                 sp = stzalloc(sizeof(*sp));
5890                                 sp->text = start;
5891                                 *arglist->lastp = sp;
5892                                 arglist->lastp = &sp->next;
5893                                 p++;
5894                                 if (!nulonly) {
5895                                         for (;;) {
5896                                                 if (p >= string + ifsp->endoff) {
5897                                                         break;
5898                                                 }
5899                                                 q = p;
5900                                                 if ((unsigned char)*p == CTLESC)
5901                                                         p++;
5902                                                 if (strchr(ifs, *p) == NULL) {
5903                                                         p = q;
5904                                                         break;
5905                                                 }
5906                                                 if (strchr(defifs, *p) == NULL) {
5907                                                         if (ifsspc) {
5908                                                                 p++;
5909                                                                 ifsspc = 0;
5910                                                         } else {
5911                                                                 p = q;
5912                                                                 break;
5913                                                         }
5914                                                 } else
5915                                                         p++;
5916                                         }
5917                                 }
5918                                 start = p;
5919                         } /* while */
5920                         ifsp = ifsp->next;
5921                 } while (ifsp != NULL);
5922                 if (nulonly)
5923                         goto add;
5924         }
5925
5926         if (!*start)
5927                 return;
5928
5929  add:
5930         sp = stzalloc(sizeof(*sp));
5931         sp->text = start;
5932         *arglist->lastp = sp;
5933         arglist->lastp = &sp->next;
5934 }
5935
5936 static void
5937 ifsfree(void)
5938 {
5939         struct ifsregion *p = ifsfirst.next;
5940
5941         if (!p)
5942                 goto out;
5943
5944         INT_OFF;
5945         do {
5946                 struct ifsregion *ifsp;
5947                 ifsp = p->next;
5948                 free(p);
5949                 p = ifsp;
5950         } while (p);
5951         ifsfirst.next = NULL;
5952         INT_ON;
5953  out:
5954         ifslastp = NULL;
5955 }
5956
5957 static size_t
5958 esclen(const char *start, const char *p)
5959 {
5960         size_t esc = 0;
5961
5962         while (p > start && (unsigned char)*--p == CTLESC) {
5963                 esc++;
5964         }
5965         return esc;
5966 }
5967
5968 /*
5969  * Remove any CTLESC characters from a string.
5970  */
5971 static char *
5972 rmescapes(char *str, int flag)
5973 {
5974         static const char qchars[] ALIGN1 = {
5975                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5976
5977         char *p, *q, *r;
5978         unsigned inquotes;
5979         unsigned protect_against_glob;
5980         unsigned globbing;
5981         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5982
5983         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5984         if (!p)
5985                 return str;
5986
5987         q = p;
5988         r = str;
5989         if (flag & RMESCAPE_ALLOC) {
5990                 size_t len = p - str;
5991                 size_t fulllen = len + strlen(p) + 1;
5992
5993                 if (flag & RMESCAPE_GROW) {
5994                         int strloc = str - (char *)stackblock();
5995                         r = makestrspace(fulllen, expdest);
5996                         /* p and str may be invalidated by makestrspace */
5997                         str = (char *)stackblock() + strloc;
5998                         p = str + len;
5999                 } else if (flag & RMESCAPE_HEAP) {
6000                         r = ckmalloc(fulllen);
6001                 } else {
6002                         r = stalloc(fulllen);
6003                 }
6004                 q = r;
6005                 if (len > 0) {
6006                         q = (char *)mempcpy(q, str, len);
6007                 }
6008         }
6009
6010         inquotes = 0;
6011         globbing = flag & RMESCAPE_GLOB;
6012         protect_against_glob = globbing;
6013         while (*p) {
6014                 if ((unsigned char)*p == CTLQUOTEMARK) {
6015 // Note: both inquotes and protect_against_glob only affect whether
6016 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6017                         inquotes = ~inquotes;
6018                         p++;
6019                         protect_against_glob = globbing;
6020                         continue;
6021                 }
6022                 if ((unsigned char)*p == CTLESC) {
6023                         p++;
6024 #if DEBUG
6025                         if (*p == '\0')
6026                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6027 #endif
6028                         if (protect_against_glob) {
6029                                 /*
6030                                  * We used to trust glob() and fnmatch() to eat
6031                                  * superfluous escapes (\z where z has no
6032                                  * special meaning anyway). But this causes
6033                                  * bugs such as string of one greek letter rho
6034                                  * (unicode-encoded as two bytes "cf,81")
6035                                  * getting encoded as "cf,CTLESC,81"
6036                                  * and here, converted to "cf,\,81" -
6037                                  * which does not go well with some flavors
6038                                  * of fnmatch() in unicode locales
6039                                  * (for example, glibc <= 2.22).
6040                                  *
6041                                  * Lets add "\" only on the chars which need it.
6042                                  * Testcases for less obvious chars are shown.
6043                                  */
6044                                 if (*p == '*'
6045                                  || *p == '?'
6046                                  || *p == '['
6047                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6048                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6049                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6050                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6051                                 /* Some libc support [^negate], that's why "^" also needs love */
6052                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6053                                 ) {
6054                                         *q++ = '\\';
6055                                 }
6056                         }
6057                 } else if (*p == '\\' && !inquotes) {
6058                         /* naked back slash */
6059                         protect_against_glob = 0;
6060                         goto copy;
6061                 }
6062 #if BASH_PATTERN_SUBST
6063                 else if (*p == '/' && slash) {
6064                         /* stop handling globbing and mark location of slash */
6065                         globbing = slash = 0;
6066                         *p = CTLESC;
6067                 }
6068 #endif
6069                 protect_against_glob = globbing;
6070  copy:
6071                 *q++ = *p++;
6072         }
6073         *q = '\0';
6074         if (flag & RMESCAPE_GROW) {
6075                 expdest = r;
6076                 STADJUST(q - r + 1, expdest);
6077         }
6078         return r;
6079 }
6080 #define pmatch(a, b) !fnmatch((a), (b), 0)
6081
6082 /*
6083  * Prepare a pattern for a expmeta (internal glob(3)) call.
6084  *
6085  * Returns an stalloced string.
6086  */
6087 static char *
6088 preglob(const char *pattern, int flag)
6089 {
6090         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
6091 }
6092
6093 /*
6094  * Put a string on the stack.
6095  */
6096 static void
6097 memtodest(const char *p, size_t len, int syntax, int quotes)
6098 {
6099         char *q;
6100
6101         if (!len)
6102                 return;
6103
6104         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6105
6106         do {
6107                 unsigned char c = *p++;
6108                 if (c) {
6109                         if (quotes & QUOTES_ESC) {
6110                                 int n = SIT(c, syntax);
6111                                 if (n == CCTL
6112                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6113                                      && n == CBACK
6114                                     )
6115                                 ) {
6116                                         USTPUTC(CTLESC, q);
6117                                 }
6118                         }
6119                 } else if (!(quotes & QUOTES_KEEPNUL))
6120                         continue;
6121                 USTPUTC(c, q);
6122         } while (--len);
6123
6124         expdest = q;
6125 }
6126
6127 static size_t
6128 strtodest(const char *p, int syntax, int quotes)
6129 {
6130         size_t len = strlen(p);
6131         memtodest(p, len, syntax, quotes);
6132         return len;
6133 }
6134
6135 /*
6136  * Record the fact that we have to scan this region of the
6137  * string for IFS characters.
6138  */
6139 static void
6140 recordregion(int start, int end, int nulonly)
6141 {
6142         struct ifsregion *ifsp;
6143
6144         if (ifslastp == NULL) {
6145                 ifsp = &ifsfirst;
6146         } else {
6147                 INT_OFF;
6148                 ifsp = ckzalloc(sizeof(*ifsp));
6149                 /*ifsp->next = NULL; - ckzalloc did it */
6150                 ifslastp->next = ifsp;
6151                 INT_ON;
6152         }
6153         ifslastp = ifsp;
6154         ifslastp->begoff = start;
6155         ifslastp->endoff = end;
6156         ifslastp->nulonly = nulonly;
6157 }
6158
6159 static void
6160 removerecordregions(int endoff)
6161 {
6162         if (ifslastp == NULL)
6163                 return;
6164
6165         if (ifsfirst.endoff > endoff) {
6166                 while (ifsfirst.next) {
6167                         struct ifsregion *ifsp;
6168                         INT_OFF;
6169                         ifsp = ifsfirst.next->next;
6170                         free(ifsfirst.next);
6171                         ifsfirst.next = ifsp;
6172                         INT_ON;
6173                 }
6174                 if (ifsfirst.begoff > endoff) {
6175                         ifslastp = NULL;
6176                 } else {
6177                         ifslastp = &ifsfirst;
6178                         ifsfirst.endoff = endoff;
6179                 }
6180                 return;
6181         }
6182
6183         ifslastp = &ifsfirst;
6184         while (ifslastp->next && ifslastp->next->begoff < endoff)
6185                 ifslastp = ifslastp->next;
6186         while (ifslastp->next) {
6187                 struct ifsregion *ifsp;
6188                 INT_OFF;
6189                 ifsp = ifslastp->next->next;
6190                 free(ifslastp->next);
6191                 ifslastp->next = ifsp;
6192                 INT_ON;
6193         }
6194         if (ifslastp->endoff > endoff)
6195                 ifslastp->endoff = endoff;
6196 }
6197
6198 static char *
6199 exptilde(char *startp, char *p, int flags)
6200 {
6201         unsigned char c;
6202         char *name;
6203         struct passwd *pw;
6204         const char *home;
6205         int quotes = flags & QUOTES_ESC;
6206
6207         name = p + 1;
6208
6209         while ((c = *++p) != '\0') {
6210                 switch (c) {
6211                 case CTLESC:
6212                         return startp;
6213                 case CTLQUOTEMARK:
6214                         return startp;
6215                 case ':':
6216                         if (flags & EXP_VARTILDE)
6217                                 goto done;
6218                         break;
6219                 case '/':
6220                 case CTLENDVAR:
6221                         goto done;
6222                 }
6223         }
6224  done:
6225         *p = '\0';
6226         if (*name == '\0') {
6227                 home = lookupvar("HOME");
6228         } else {
6229                 pw = getpwnam(name);
6230                 if (pw == NULL)
6231                         goto lose;
6232                 home = pw->pw_dir;
6233         }
6234         if (!home || !*home)
6235                 goto lose;
6236         *p = c;
6237         strtodest(home, SQSYNTAX, quotes);
6238         return p;
6239  lose:
6240         *p = c;
6241         return startp;
6242 }
6243
6244 /*
6245  * Execute a command inside back quotes.  If it's a builtin command, we
6246  * want to save its output in a block obtained from malloc.  Otherwise
6247  * we fork off a subprocess and get the output of the command via a pipe.
6248  * Should be called with interrupts off.
6249  */
6250 struct backcmd {                /* result of evalbackcmd */
6251         int fd;                 /* file descriptor to read from */
6252         int nleft;              /* number of chars in buffer */
6253         char *buf;              /* buffer */
6254         struct job *jp;         /* job structure for command */
6255 };
6256
6257 /* These forward decls are needed to use "eval" code for backticks handling: */
6258 /* flags in argument to evaltree */
6259 #define EV_EXIT    01           /* exit after evaluating tree */
6260 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6261 static int evaltree(union node *, int);
6262
6263 /* An evaltree() which is known to never return.
6264  * Used to use an alias:
6265  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6266  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6267  */
6268 static ALWAYS_INLINE NORETURN void
6269 evaltreenr(union node *n, int flags)
6270 {
6271         evaltree(n, flags);
6272         bb_unreachable(abort());
6273         /* NOTREACHED */
6274 }
6275
6276 static void FAST_FUNC
6277 evalbackcmd(union node *n, struct backcmd *result)
6278 {
6279         int pip[2];
6280         struct job *jp;
6281
6282         result->fd = -1;
6283         result->buf = NULL;
6284         result->nleft = 0;
6285         result->jp = NULL;
6286         if (n == NULL) {
6287                 goto out;
6288         }
6289
6290         if (pipe(pip) < 0)
6291                 ash_msg_and_raise_error("pipe call failed");
6292         jp = makejob(/*n,*/ 1);
6293         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6294                 /* child */
6295                 FORCE_INT_ON;
6296                 close(pip[0]);
6297                 if (pip[1] != 1) {
6298                         /*close(1);*/
6299                         dup2_or_raise(pip[1], 1);
6300                         close(pip[1]);
6301                 }
6302 /* TODO: eflag clearing makes the following not abort:
6303  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6304  * which is what bash does (unless it is in POSIX mode).
6305  * dash deleted "eflag = 0" line in the commit
6306  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6307  *  [EVAL] Don't clear eflag in evalbackcmd
6308  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6309  */
6310                 eflag = 0;
6311                 ifsfree();
6312                 evaltreenr(n, EV_EXIT);
6313                 /* NOTREACHED */
6314         }
6315         /* parent */
6316         close(pip[1]);
6317         result->fd = pip[0];
6318         result->jp = jp;
6319
6320  out:
6321         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6322                 result->fd, result->buf, result->nleft, result->jp));
6323 }
6324
6325 /*
6326  * Expand stuff in backwards quotes.
6327  */
6328 static void
6329 expbackq(union node *cmd, int flag)
6330 {
6331         struct backcmd in;
6332         int i;
6333         char buf[128];
6334         char *p;
6335         char *dest;
6336         int startloc;
6337         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6338         struct stackmark smark;
6339
6340         INT_OFF;
6341         startloc = expdest - (char *)stackblock();
6342         pushstackmark(&smark, startloc);
6343         evalbackcmd(cmd, &in);
6344         popstackmark(&smark);
6345
6346         p = in.buf;
6347         i = in.nleft;
6348         if (i == 0)
6349                 goto read;
6350         for (;;) {
6351                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6352  read:
6353                 if (in.fd < 0)
6354                         break;
6355                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6356                 TRACE(("expbackq: read returns %d\n", i));
6357                 if (i <= 0)
6358                         break;
6359                 p = buf;
6360         }
6361
6362         free(in.buf);
6363         if (in.fd >= 0) {
6364                 close(in.fd);
6365                 back_exitstatus = waitforjob(in.jp);
6366         }
6367         INT_ON;
6368
6369         /* Eat all trailing newlines */
6370         dest = expdest;
6371         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6372                 STUNPUTC(dest);
6373         expdest = dest;
6374
6375         if (!(flag & EXP_QUOTED))
6376                 recordregion(startloc, dest - (char *)stackblock(), 0);
6377         TRACE(("evalbackq: size:%d:'%.*s'\n",
6378                 (int)((dest - (char *)stackblock()) - startloc),
6379                 (int)((dest - (char *)stackblock()) - startloc),
6380                 stackblock() + startloc));
6381 }
6382
6383 #if ENABLE_FEATURE_SH_MATH
6384 /*
6385  * Expand arithmetic expression.  Backup to start of expression,
6386  * evaluate, place result in (backed up) result, adjust string position.
6387  */
6388 static void
6389 expari(int flag)
6390 {
6391         char *p, *start;
6392         int begoff;
6393         int len;
6394
6395         /* ifsfree(); */
6396
6397         /*
6398          * This routine is slightly over-complicated for
6399          * efficiency.  Next we scan backwards looking for the
6400          * start of arithmetic.
6401          */
6402         start = stackblock();
6403         p = expdest - 1;
6404         *p = '\0';
6405         p--;
6406         while (1) {
6407                 int esc;
6408
6409                 while ((unsigned char)*p != CTLARI) {
6410                         p--;
6411 #if DEBUG
6412                         if (p < start) {
6413                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6414                         }
6415 #endif
6416                 }
6417
6418                 esc = esclen(start, p);
6419                 if (!(esc % 2)) {
6420                         break;
6421                 }
6422
6423                 p -= esc + 1;
6424         }
6425
6426         begoff = p - start;
6427
6428         removerecordregions(begoff);
6429
6430         expdest = p;
6431
6432         if (flag & QUOTES_ESC)
6433                 rmescapes(p + 1, 0);
6434
6435         len = cvtnum(ash_arith(p + 1));
6436
6437         if (!(flag & EXP_QUOTED))
6438                 recordregion(begoff, begoff + len, 0);
6439 }
6440 #endif
6441
6442 /* argstr needs it */
6443 static char *evalvar(char *p, int flags);
6444
6445 /*
6446  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6447  * characters to allow for further processing.  Otherwise treat
6448  * $@ like $* since no splitting will be performed.
6449  */
6450 static void
6451 argstr(char *p, int flags)
6452 {
6453         static const char spclchars[] ALIGN1 = {
6454                 '=',
6455                 ':',
6456                 CTLQUOTEMARK,
6457                 CTLENDVAR,
6458                 CTLESC,
6459                 CTLVAR,
6460                 CTLBACKQ,
6461 #if ENABLE_FEATURE_SH_MATH
6462                 CTLENDARI,
6463 #endif
6464                 '\0'
6465         };
6466         const char *reject = spclchars;
6467         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6468         int inquotes;
6469         size_t length;
6470         int startloc;
6471
6472         if (!(flags & EXP_VARTILDE)) {
6473                 reject += 2;
6474         } else if (flags & EXP_VARTILDE2) {
6475                 reject++;
6476         }
6477         inquotes = 0;
6478         length = 0;
6479         if (flags & EXP_TILDE) {
6480                 char *q;
6481
6482                 flags &= ~EXP_TILDE;
6483  tilde:
6484                 q = p;
6485                 if (*q == '~')
6486                         p = exptilde(p, q, flags);
6487         }
6488  start:
6489         startloc = expdest - (char *)stackblock();
6490         for (;;) {
6491                 unsigned char c;
6492
6493                 length += strcspn(p + length, reject);
6494                 c = p[length];
6495                 if (c) {
6496                         if (!(c & 0x80)
6497                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6498                         ) {
6499                                 /* c == '=' || c == ':' || c == CTLENDARI */
6500                                 length++;
6501                         }
6502                 }
6503                 if (length > 0) {
6504                         int newloc;
6505                         expdest = stack_nputstr(p, length, expdest);
6506                         newloc = expdest - (char *)stackblock();
6507                         if (breakall && !inquotes && newloc > startloc) {
6508                                 recordregion(startloc, newloc, 0);
6509                         }
6510                         startloc = newloc;
6511                 }
6512                 p += length + 1;
6513                 length = 0;
6514
6515                 switch (c) {
6516                 case '\0':
6517                         goto breakloop;
6518                 case '=':
6519                         if (flags & EXP_VARTILDE2) {
6520                                 p--;
6521                                 continue;
6522                         }
6523                         flags |= EXP_VARTILDE2;
6524                         reject++;
6525                         /* fall through */
6526                 case ':':
6527                         /*
6528                          * sort of a hack - expand tildes in variable
6529                          * assignments (after the first '=' and after ':'s).
6530                          */
6531                         if (*--p == '~') {
6532                                 goto tilde;
6533                         }
6534                         continue;
6535                 }
6536
6537                 switch (c) {
6538                 case CTLENDVAR: /* ??? */
6539                         goto breakloop;
6540                 case CTLQUOTEMARK:
6541                         inquotes ^= EXP_QUOTED;
6542                         /* "$@" syntax adherence hack */
6543                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6544                                 p = evalvar(p + 1, flags | inquotes) + 1;
6545                                 goto start;
6546                         }
6547  addquote:
6548                         if (flags & QUOTES_ESC) {
6549                                 p--;
6550                                 length++;
6551                                 startloc++;
6552                         }
6553                         break;
6554                 case CTLESC:
6555                         startloc++;
6556                         length++;
6557
6558                         /*
6559                          * Quoted parameter expansion pattern: remove quote
6560                          * unless inside inner quotes or we have a literal
6561                          * backslash.
6562                          */
6563                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6564                             EXP_QPAT && *p != '\\')
6565                                 break;
6566
6567                         goto addquote;
6568                 case CTLVAR:
6569                         TRACE(("argstr: evalvar('%s')\n", p));
6570                         p = evalvar(p, flags | inquotes);
6571                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6572                         goto start;
6573                 case CTLBACKQ:
6574                         expbackq(argbackq->n, flags | inquotes);
6575                         argbackq = argbackq->next;
6576                         goto start;
6577 #if ENABLE_FEATURE_SH_MATH
6578                 case CTLENDARI:
6579                         p--;
6580                         expari(flags | inquotes);
6581                         goto start;
6582 #endif
6583                 }
6584         }
6585  breakloop: ;
6586 }
6587
6588 static char *
6589 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6590                 char *pattern, int quotes, int zero)
6591 {
6592         char *loc, *loc2;
6593         char c;
6594
6595         loc = startp;
6596         loc2 = rmesc;
6597         do {
6598                 int match;
6599                 const char *s = loc2;
6600
6601                 c = *loc2;
6602                 if (zero) {
6603                         *loc2 = '\0';
6604                         s = rmesc;
6605                 }
6606                 match = pmatch(pattern, s);
6607
6608                 *loc2 = c;
6609                 if (match)
6610                         return loc;
6611                 if (quotes && (unsigned char)*loc == CTLESC)
6612                         loc++;
6613                 loc++;
6614                 loc2++;
6615         } while (c);
6616         return NULL;
6617 }
6618
6619 static char *
6620 scanright(char *startp, char *rmesc, char *rmescend,
6621                 char *pattern, int quotes, int match_at_start)
6622 {
6623 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6624         int try2optimize = match_at_start;
6625 #endif
6626         int esc = 0;
6627         char *loc;
6628         char *loc2;
6629
6630         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6631          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6632          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6633          * Logic:
6634          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6635          * and on each iteration they go back two/one char until they reach the beginning.
6636          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6637          */
6638         /* TODO: document in what other circumstances we are called. */
6639
6640         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6641                 int match;
6642                 char c = *loc2;
6643                 const char *s = loc2;
6644                 if (match_at_start) {
6645                         *loc2 = '\0';
6646                         s = rmesc;
6647                 }
6648                 match = pmatch(pattern, s);
6649                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6650                 *loc2 = c;
6651                 if (match)
6652                         return loc;
6653 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6654                 if (try2optimize) {
6655                         /* Maybe we can optimize this:
6656                          * if pattern ends with unescaped *, we can avoid checking
6657                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6658                          * it won't match truncated "raw_value_of_" strings too.
6659                          */
6660                         unsigned plen = strlen(pattern);
6661                         /* Does it end with "*"? */
6662                         if (plen != 0 && pattern[--plen] == '*') {
6663                                 /* "xxxx*" is not escaped */
6664                                 /* "xxx\*" is escaped */
6665                                 /* "xx\\*" is not escaped */
6666                                 /* "x\\\*" is escaped */
6667                                 int slashes = 0;
6668                                 while (plen != 0 && pattern[--plen] == '\\')
6669                                         slashes++;
6670                                 if (!(slashes & 1))
6671                                         break; /* ends with unescaped "*" */
6672                         }
6673                         try2optimize = 0;
6674                 }
6675 #endif
6676                 loc--;
6677                 if (quotes) {
6678                         if (--esc < 0) {
6679                                 esc = esclen(startp, loc);
6680                         }
6681                         if (esc % 2) {
6682                                 esc--;
6683                                 loc--;
6684                         }
6685                 }
6686         }
6687         return NULL;
6688 }
6689
6690 static void varunset(const char *, const char *, const char *, int) NORETURN;
6691 static void
6692 varunset(const char *end, const char *var, const char *umsg, int varflags)
6693 {
6694         const char *msg;
6695         const char *tail;
6696
6697         tail = nullstr;
6698         msg = "parameter not set";
6699         if (umsg) {
6700                 if ((unsigned char)*end == CTLENDVAR) {
6701                         if (varflags & VSNUL)
6702                                 tail = " or null";
6703                 } else {
6704                         msg = umsg;
6705                 }
6706         }
6707         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6708 }
6709
6710 static const char *
6711 subevalvar(char *p, char *varname, int strloc, int subtype,
6712                 int startloc, int varflags, int flag)
6713 {
6714         struct nodelist *saveargbackq = argbackq;
6715         int quotes = flag & QUOTES_ESC;
6716         char *startp;
6717         char *loc;
6718         char *rmesc, *rmescend;
6719         char *str;
6720         int amount, resetloc;
6721         IF_BASH_PATTERN_SUBST(int workloc;)
6722         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6723         int zero;
6724         char *(*scan)(char*, char*, char*, char*, int, int);
6725
6726         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6727         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6728
6729         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6730                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6731         );
6732         STPUTC('\0', expdest);
6733         argbackq = saveargbackq;
6734         startp = (char *)stackblock() + startloc;
6735
6736         switch (subtype) {
6737         case VSASSIGN:
6738                 setvar0(varname, startp);
6739                 amount = startp - expdest;
6740                 STADJUST(amount, expdest);
6741                 return startp;
6742
6743         case VSQUESTION:
6744                 varunset(p, varname, startp, varflags);
6745                 /* NOTREACHED */
6746
6747 #if BASH_SUBSTR
6748         case VSSUBSTR: {
6749                 int pos, len, orig_len;
6750                 char *colon;
6751
6752                 loc = str = stackblock() + strloc;
6753
6754 # if !ENABLE_FEATURE_SH_MATH
6755 #  define ash_arith number
6756 # endif
6757                 /* Read POS in ${var:POS:LEN} */
6758                 colon = strchr(loc, ':');
6759                 if (colon) *colon = '\0';
6760                 pos = ash_arith(loc);
6761                 if (colon) *colon = ':';
6762
6763                 /* Read LEN in ${var:POS:LEN} */
6764                 len = str - startp - 1;
6765                 /* *loc != '\0', guaranteed by parser */
6766                 if (quotes) {
6767                         char *ptr;
6768
6769                         /* Adjust the length by the number of escapes */
6770                         for (ptr = startp; ptr < (str - 1); ptr++) {
6771                                 if ((unsigned char)*ptr == CTLESC) {
6772                                         len--;
6773                                         ptr++;
6774                                 }
6775                         }
6776                 }
6777                 orig_len = len;
6778                 if (*loc++ == ':') {
6779                         /* ${var::LEN} */
6780                         len = ash_arith(loc);
6781                 } else {
6782                         /* Skip POS in ${var:POS:LEN} */
6783                         len = orig_len;
6784                         while (*loc && *loc != ':') {
6785                                 loc++;
6786                         }
6787                         if (*loc++ == ':') {
6788                                 len = ash_arith(loc);
6789                         }
6790                 }
6791 #  undef ash_arith
6792
6793                 if (pos < 0) {
6794                         /* ${VAR:$((-n)):l} starts n chars from the end */
6795                         pos = orig_len + pos;
6796                 }
6797                 if ((unsigned)pos >= orig_len) {
6798                         /* apart from obvious ${VAR:999999:l},
6799                          * covers ${VAR:$((-9999999)):l} - result is ""
6800                          * (bash compat)
6801                          */
6802                         pos = 0;
6803                         len = 0;
6804                 }
6805                 if (len < 0) {
6806                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6807                         len = (orig_len - pos) + len;
6808                 }
6809                 if ((unsigned)len > (orig_len - pos))
6810                         len = orig_len - pos;
6811
6812                 for (str = startp; pos; str++, pos--) {
6813                         if (quotes && (unsigned char)*str == CTLESC)
6814                                 str++;
6815                 }
6816                 for (loc = startp; len; len--) {
6817                         if (quotes && (unsigned char)*str == CTLESC)
6818                                 *loc++ = *str++;
6819                         *loc++ = *str++;
6820                 }
6821                 *loc = '\0';
6822                 amount = loc - expdest;
6823                 STADJUST(amount, expdest);
6824                 return loc;
6825         }
6826 #endif /* BASH_SUBSTR */
6827         }
6828
6829         resetloc = expdest - (char *)stackblock();
6830
6831 #if BASH_PATTERN_SUBST
6832         /* We'll comeback here if we grow the stack while handling
6833          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6834          * stack will need rebasing, and we'll need to remove our work
6835          * areas each time
6836          */
6837  restart:
6838 #endif
6839
6840         amount = expdest - ((char *)stackblock() + resetloc);
6841         STADJUST(-amount, expdest);
6842         startp = (char *)stackblock() + startloc;
6843
6844         rmesc = startp;
6845         rmescend = (char *)stackblock() + strloc;
6846         if (quotes) {
6847                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6848                 if (rmesc != startp) {
6849                         rmescend = expdest;
6850                         startp = (char *)stackblock() + startloc;
6851                 }
6852         }
6853         rmescend--;
6854         str = (char *)stackblock() + strloc;
6855         /*
6856          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6857          * The result is a_\_z_c (not a\_\_z_c)!
6858          *
6859          * The search pattern and replace string treat backslashes differently!
6860          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6861          * and string.  It's only used on the first call.
6862          */
6863         preglob(str, IF_BASH_PATTERN_SUBST(
6864                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6865                         RMESCAPE_SLASH : ) 0);
6866
6867 #if BASH_PATTERN_SUBST
6868         workloc = expdest - (char *)stackblock();
6869         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6870                 int len;
6871                 char *idx, *end;
6872
6873                 if (!repl) {
6874                         repl = strchr(str, CTLESC);
6875                         if (repl)
6876                                 *repl++ = '\0';
6877                         else
6878                                 repl = nullstr;
6879                 }
6880                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6881
6882                 /* If there's no pattern to match, return the expansion unmolested */
6883                 if (str[0] == '\0')
6884                         return NULL;
6885
6886                 len = 0;
6887                 idx = startp;
6888                 end = str - 1;
6889                 while (idx < end) {
6890  try_to_match:
6891                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6892                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6893                         if (!loc) {
6894                                 /* No match, advance */
6895                                 char *restart_detect = stackblock();
6896  skip_matching:
6897                                 STPUTC(*idx, expdest);
6898                                 if (quotes && (unsigned char)*idx == CTLESC) {
6899                                         idx++;
6900                                         len++;
6901                                         STPUTC(*idx, expdest);
6902                                 }
6903                                 if (stackblock() != restart_detect)
6904                                         goto restart;
6905                                 idx++;
6906                                 len++;
6907                                 rmesc++;
6908                                 /* continue; - prone to quadratic behavior, smarter code: */
6909                                 if (idx >= end)
6910                                         break;
6911                                 if (str[0] == '*') {
6912                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6913                                          * it would never match "ong_string" etc, no point in trying.
6914                                          */
6915                                         goto skip_matching;
6916                                 }
6917                                 goto try_to_match;
6918                         }
6919
6920                         if (subtype == VSREPLACEALL) {
6921                                 while (idx < loc) {
6922                                         if (quotes && (unsigned char)*idx == CTLESC)
6923                                                 idx++;
6924                                         idx++;
6925                                         rmesc++;
6926                                 }
6927                         } else {
6928                                 idx = loc;
6929                         }
6930
6931                         //bb_error_msg("repl:'%s'", repl);
6932                         for (loc = (char*)repl; *loc; loc++) {
6933                                 char *restart_detect = stackblock();
6934                                 if (quotes && *loc == '\\') {
6935                                         STPUTC(CTLESC, expdest);
6936                                         len++;
6937                                 }
6938                                 STPUTC(*loc, expdest);
6939                                 if (stackblock() != restart_detect)
6940                                         goto restart;
6941                                 len++;
6942                         }
6943
6944                         if (subtype == VSREPLACE) {
6945                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6946                                 while (*idx) {
6947                                         char *restart_detect = stackblock();
6948                                         STPUTC(*idx, expdest);
6949                                         if (stackblock() != restart_detect)
6950                                                 goto restart;
6951                                         len++;
6952                                         idx++;
6953                                 }
6954                                 break;
6955                         }
6956                 }
6957
6958                 /* We've put the replaced text into a buffer at workloc, now
6959                  * move it to the right place and adjust the stack.
6960                  */
6961                 STPUTC('\0', expdest);
6962                 startp = (char *)stackblock() + startloc;
6963                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6964                 //bb_error_msg("startp:'%s'", startp);
6965                 amount = expdest - (startp + len);
6966                 STADJUST(-amount, expdest);
6967                 return startp;
6968         }
6969 #endif /* BASH_PATTERN_SUBST */
6970
6971         subtype -= VSTRIMRIGHT;
6972 #if DEBUG
6973         if (subtype < 0 || subtype > 7)
6974                 abort();
6975 #endif
6976         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6977         zero = subtype >> 1;
6978         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6979         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6980
6981         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6982         if (loc) {
6983                 if (zero) {
6984                         memmove(startp, loc, str - loc);
6985                         loc = startp + (str - loc) - 1;
6986                 }
6987                 *loc = '\0';
6988                 amount = loc - expdest;
6989                 STADJUST(amount, expdest);
6990         }
6991         return loc;
6992 }
6993
6994 /*
6995  * Add the value of a specialized variable to the stack string.
6996  * name parameter (examples):
6997  * ash -c 'echo $1'      name:'1='
6998  * ash -c 'echo $qwe'    name:'qwe='
6999  * ash -c 'echo $$'      name:'$='
7000  * ash -c 'echo ${$}'    name:'$='
7001  * ash -c 'echo ${$##q}' name:'$=q'
7002  * ash -c 'echo ${#$}'   name:'$='
7003  * note: examples with bad shell syntax:
7004  * ash -c 'echo ${#$1}'  name:'$=1'
7005  * ash -c 'echo ${#1#}'  name:'1=#'
7006  */
7007 static NOINLINE ssize_t
7008 varvalue(char *name, int varflags, int flags, int *quotedp)
7009 {
7010         const char *p;
7011         int num;
7012         int i;
7013         ssize_t len = 0;
7014         int sep;
7015         int quoted = *quotedp;
7016         int subtype = varflags & VSTYPE;
7017         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7018         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7019         int syntax;
7020
7021         sep = (flags & EXP_FULL) << CHAR_BIT;
7022         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7023
7024         switch (*name) {
7025         case '$':
7026                 num = rootpid;
7027                 goto numvar;
7028         case '?':
7029                 num = exitstatus;
7030                 goto numvar;
7031         case '#':
7032                 num = shellparam.nparam;
7033                 goto numvar;
7034         case '!':
7035                 num = backgndpid;
7036                 if (num == 0)
7037                         return -1;
7038  numvar:
7039                 len = cvtnum(num);
7040                 goto check_1char_name;
7041         case '-':
7042                 expdest = makestrspace(NOPTS, expdest);
7043                 for (i = NOPTS - 1; i >= 0; i--) {
7044                         if (optlist[i]) {
7045                                 USTPUTC(optletters(i), expdest);
7046                                 len++;
7047                         }
7048                 }
7049  check_1char_name:
7050 #if 0
7051                 /* handles cases similar to ${#$1} */
7052                 if (name[2] != '\0')
7053                         raise_error_syntax("bad substitution");
7054 #endif
7055                 break;
7056         case '@':
7057                 if (quoted && sep)
7058                         goto param;
7059                 /* fall through */
7060         case '*': {
7061                 char **ap;
7062                 char sepc;
7063
7064                 if (quoted)
7065                         sep = 0;
7066                 sep |= ifsset() ? ifsval()[0] : ' ';
7067  param:
7068                 sepc = sep;
7069                 *quotedp = !sepc;
7070                 ap = shellparam.p;
7071                 if (!ap)
7072                         return -1;
7073                 while ((p = *ap++) != NULL) {
7074                         len += strtodest(p, syntax, quotes);
7075
7076                         if (*ap && sep) {
7077                                 len++;
7078                                 memtodest(&sepc, 1, syntax, quotes);
7079                         }
7080                 }
7081                 break;
7082         } /* case '*' */
7083         case '0':
7084         case '1':
7085         case '2':
7086         case '3':
7087         case '4':
7088         case '5':
7089         case '6':
7090         case '7':
7091         case '8':
7092         case '9':
7093                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7094                 if (num < 0 || num > shellparam.nparam)
7095                         return -1;
7096                 p = num ? shellparam.p[num - 1] : arg0;
7097                 goto value;
7098         default:
7099                 /* NB: name has form "VAR=..." */
7100                 p = lookupvar(name);
7101  value:
7102                 if (!p)
7103                         return -1;
7104
7105                 len = strtodest(p, syntax, quotes);
7106 #if ENABLE_UNICODE_SUPPORT
7107                 if (subtype == VSLENGTH && len > 0) {
7108                         reinit_unicode_for_ash();
7109                         if (unicode_status == UNICODE_ON) {
7110                                 STADJUST(-len, expdest);
7111                                 discard = 0;
7112                                 len = unicode_strlen(p);
7113                         }
7114                 }
7115 #endif
7116                 break;
7117         }
7118
7119         if (discard)
7120                 STADJUST(-len, expdest);
7121         return len;
7122 }
7123
7124 /*
7125  * Expand a variable, and return a pointer to the next character in the
7126  * input string.
7127  */
7128 static char *
7129 evalvar(char *p, int flag)
7130 {
7131         char varflags;
7132         char subtype;
7133         int quoted;
7134         char easy;
7135         char *var;
7136         int patloc;
7137         int startloc;
7138         ssize_t varlen;
7139
7140         varflags = (unsigned char) *p++;
7141         subtype = varflags & VSTYPE;
7142
7143         if (!subtype)
7144                 raise_error_syntax("bad substitution");
7145
7146         quoted = flag & EXP_QUOTED;
7147         var = p;
7148         easy = (!quoted || (*var == '@' && shellparam.nparam));
7149         startloc = expdest - (char *)stackblock();
7150         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7151
7152  again:
7153         varlen = varvalue(var, varflags, flag, &quoted);
7154         if (varflags & VSNUL)
7155                 varlen--;
7156
7157         if (subtype == VSPLUS) {
7158                 varlen = -1 - varlen;
7159                 goto vsplus;
7160         }
7161
7162         if (subtype == VSMINUS) {
7163  vsplus:
7164                 if (varlen < 0) {
7165                         argstr(
7166                                 p,
7167                                 flag | EXP_TILDE | EXP_WORD
7168                         );
7169                         goto end;
7170                 }
7171                 goto record;
7172         }
7173
7174         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7175                 if (varlen >= 0)
7176                         goto record;
7177
7178                 subevalvar(p, var, 0, subtype, startloc, varflags,
7179                            flag & ~QUOTES_ESC);
7180                 varflags &= ~VSNUL;
7181                 /*
7182                  * Remove any recorded regions beyond
7183                  * start of variable
7184                  */
7185                 removerecordregions(startloc);
7186                 goto again;
7187         }
7188
7189         if (varlen < 0 && uflag)
7190                 varunset(p, var, 0, 0);
7191
7192         if (subtype == VSLENGTH) {
7193                 cvtnum(varlen > 0 ? varlen : 0);
7194                 goto record;
7195         }
7196
7197         if (subtype == VSNORMAL) {
7198  record:
7199                 if (!easy)
7200                         goto end;
7201                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7202                 goto end;
7203         }
7204
7205 #if DEBUG
7206         switch (subtype) {
7207         case VSTRIMLEFT:
7208         case VSTRIMLEFTMAX:
7209         case VSTRIMRIGHT:
7210         case VSTRIMRIGHTMAX:
7211 #if BASH_SUBSTR
7212         case VSSUBSTR:
7213 #endif
7214 #if BASH_PATTERN_SUBST
7215         case VSREPLACE:
7216         case VSREPLACEALL:
7217 #endif
7218                 break;
7219         default:
7220                 abort();
7221         }
7222 #endif
7223
7224         if (varlen >= 0) {
7225                 /*
7226                  * Terminate the string and start recording the pattern
7227                  * right after it
7228                  */
7229                 STPUTC('\0', expdest);
7230                 patloc = expdest - (char *)stackblock();
7231                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7232                                 startloc, varflags, flag)) {
7233                         int amount = expdest - (
7234                                 (char *)stackblock() + patloc - 1
7235                         );
7236                         STADJUST(-amount, expdest);
7237                 }
7238                 /* Remove any recorded regions beyond start of variable */
7239                 removerecordregions(startloc);
7240                 goto record;
7241         }
7242
7243  end:
7244         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7245                 int nesting = 1;
7246                 for (;;) {
7247                         unsigned char c = *p++;
7248                         if (c == CTLESC)
7249                                 p++;
7250                         else if (c == CTLBACKQ) {
7251                                 if (varlen >= 0)
7252                                         argbackq = argbackq->next;
7253                         } else if (c == CTLVAR) {
7254                                 if ((*p++ & VSTYPE) != VSNORMAL)
7255                                         nesting++;
7256                         } else if (c == CTLENDVAR) {
7257                                 if (--nesting == 0)
7258                                         break;
7259                         }
7260                 }
7261         }
7262         return p;
7263 }
7264
7265 /*
7266  * Add a file name to the list.
7267  */
7268 static void
7269 addfname(const char *name)
7270 {
7271         struct strlist *sp;
7272
7273         sp = stzalloc(sizeof(*sp));
7274         sp->text = sstrdup(name);
7275         *exparg.lastp = sp;
7276         exparg.lastp = &sp->next;
7277 }
7278
7279 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7280 static int
7281 hasmeta(const char *p)
7282 {
7283         static const char chars[] ALIGN1 = {
7284                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7285         };
7286
7287         for (;;) {
7288                 p = strpbrk(p, chars);
7289                 if (!p)
7290                         break;
7291                 switch ((unsigned char) *p) {
7292                 case CTLQUOTEMARK:
7293                         for (;;) {
7294                                 p++;
7295                                 if (*p == CTLQUOTEMARK)
7296                                         break;
7297                                 if (*p == CTLESC)
7298                                         p++;
7299                                 if (*p == '\0') /* huh? */
7300                                         return 0;
7301                         }
7302                         break;
7303                 case '\\':
7304                 case CTLESC:
7305                         p++;
7306                         if (*p == '\0')
7307                                 return 0;
7308                         break;
7309                 case '[':
7310                         if (!strchr(p + 1, ']')) {
7311                                 /* It's not a properly closed [] pattern,
7312                                  * but other metas may follow. Continue checking.
7313                                  * my[file* _is_ globbed by bash
7314                                  * and matches filenames like "my[file1".
7315                                  */
7316                                 break;
7317                         }
7318                         /* fallthrough */
7319                 default:
7320                 /* case '*': */
7321                 /* case '?': */
7322                         return 1;
7323                 }
7324                 p++;
7325         }
7326
7327         return 0;
7328 }
7329
7330 /* If we want to use glob() from libc... */
7331 #if !ENABLE_ASH_INTERNAL_GLOB
7332
7333 /* Add the result of glob() to the list */
7334 static void
7335 addglob(const glob_t *pglob)
7336 {
7337         char **p = pglob->gl_pathv;
7338
7339         do {
7340                 addfname(*p);
7341         } while (*++p);
7342 }
7343 static void
7344 expandmeta(struct strlist *str /*, int flag*/)
7345 {
7346         /* TODO - EXP_REDIR */
7347
7348         while (str) {
7349                 char *p;
7350                 glob_t pglob;
7351                 int i;
7352
7353                 if (fflag)
7354                         goto nometa;
7355
7356                 if (!hasmeta(str->text))
7357                         goto nometa;
7358
7359                 INT_OFF;
7360                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7361 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7362 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7363 //
7364 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7365 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7366 // Which means you need to unescape the string, right? Not so fast:
7367 // if there _is_ a file named "file\?" (with backslash), it is returned
7368 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7369 // You DON'T KNOW by looking at the result whether you need to unescape it.
7370 //
7371 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7372 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7373 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7374 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7375 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7376 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7377                 i = glob(p, 0, NULL, &pglob);
7378                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7379                 if (p != str->text)
7380                         free(p);
7381                 switch (i) {
7382                 case 0:
7383 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7384                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7385                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7386                                 goto nometa2;
7387 #endif
7388                         addglob(&pglob);
7389                         globfree(&pglob);
7390                         INT_ON;
7391                         break;
7392                 case GLOB_NOMATCH:
7393  //nometa2:
7394                         globfree(&pglob);
7395                         INT_ON;
7396  nometa:
7397                         *exparg.lastp = str;
7398                         rmescapes(str->text, 0);
7399                         exparg.lastp = &str->next;
7400                         break;
7401                 default:        /* GLOB_NOSPACE */
7402                         globfree(&pglob);
7403                         INT_ON;
7404                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7405                 }
7406                 str = str->next;
7407         }
7408 }
7409
7410 #else
7411 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7412
7413 /*
7414  * Do metacharacter (i.e. *, ?, [...]) expansion.
7415  */
7416 static void
7417 expmeta(char *expdir, char *enddir, char *name)
7418 {
7419         char *p;
7420         const char *cp;
7421         char *start;
7422         char *endname;
7423         int metaflag;
7424         struct stat statb;
7425         DIR *dirp;
7426         struct dirent *dp;
7427         int atend;
7428         int matchdot;
7429         int esc;
7430
7431         metaflag = 0;
7432         start = name;
7433         for (p = name; esc = 0, *p; p += esc + 1) {
7434                 if (*p == '*' || *p == '?')
7435                         metaflag = 1;
7436                 else if (*p == '[') {
7437                         char *q = p + 1;
7438                         if (*q == '!')
7439                                 q++;
7440                         for (;;) {
7441                                 if (*q == '\\')
7442                                         q++;
7443                                 if (*q == '/' || *q == '\0')
7444                                         break;
7445                                 if (*++q == ']') {
7446                                         metaflag = 1;
7447                                         break;
7448                                 }
7449                         }
7450                 } else {
7451                         if (*p == '\\')
7452                                 esc++;
7453                         if (p[esc] == '/') {
7454                                 if (metaflag)
7455                                         break;
7456                                 start = p + esc + 1;
7457                         }
7458                 }
7459         }
7460         if (metaflag == 0) {    /* we've reached the end of the file name */
7461                 if (enddir != expdir)
7462                         metaflag++;
7463                 p = name;
7464                 do {
7465                         if (*p == '\\')
7466                                 p++;
7467                         *enddir++ = *p;
7468                 } while (*p++);
7469                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7470                         addfname(expdir);
7471                 return;
7472         }
7473         endname = p;
7474         if (name < start) {
7475                 p = name;
7476                 do {
7477                         if (*p == '\\')
7478                                 p++;
7479                         *enddir++ = *p++;
7480                 } while (p < start);
7481         }
7482         if (enddir == expdir) {
7483                 cp = ".";
7484         } else if (enddir == expdir + 1 && *expdir == '/') {
7485                 cp = "/";
7486         } else {
7487                 cp = expdir;
7488                 enddir[-1] = '\0';
7489         }
7490         dirp = opendir(cp);
7491         if (dirp == NULL)
7492                 return;
7493         if (enddir != expdir)
7494                 enddir[-1] = '/';
7495         if (*endname == 0) {
7496                 atend = 1;
7497         } else {
7498                 atend = 0;
7499                 *endname = '\0';
7500                 endname += esc + 1;
7501         }
7502         matchdot = 0;
7503         p = start;
7504         if (*p == '\\')
7505                 p++;
7506         if (*p == '.')
7507                 matchdot++;
7508         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7509                 if (dp->d_name[0] == '.' && !matchdot)
7510                         continue;
7511                 if (pmatch(start, dp->d_name)) {
7512                         if (atend) {
7513                                 strcpy(enddir, dp->d_name);
7514                                 addfname(expdir);
7515                         } else {
7516                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7517                                         continue;
7518                                 p[-1] = '/';
7519                                 expmeta(expdir, p, endname);
7520                         }
7521                 }
7522         }
7523         closedir(dirp);
7524         if (!atend)
7525                 endname[-esc - 1] = esc ? '\\' : '/';
7526 }
7527
7528 static struct strlist *
7529 msort(struct strlist *list, int len)
7530 {
7531         struct strlist *p, *q = NULL;
7532         struct strlist **lpp;
7533         int half;
7534         int n;
7535
7536         if (len <= 1)
7537                 return list;
7538         half = len >> 1;
7539         p = list;
7540         for (n = half; --n >= 0;) {
7541                 q = p;
7542                 p = p->next;
7543         }
7544         q->next = NULL;                 /* terminate first half of list */
7545         q = msort(list, half);          /* sort first half of list */
7546         p = msort(p, len - half);               /* sort second half */
7547         lpp = &list;
7548         for (;;) {
7549 #if ENABLE_LOCALE_SUPPORT
7550                 if (strcoll(p->text, q->text) < 0)
7551 #else
7552                 if (strcmp(p->text, q->text) < 0)
7553 #endif
7554                                                 {
7555                         *lpp = p;
7556                         lpp = &p->next;
7557                         p = *lpp;
7558                         if (p == NULL) {
7559                                 *lpp = q;
7560                                 break;
7561                         }
7562                 } else {
7563                         *lpp = q;
7564                         lpp = &q->next;
7565                         q = *lpp;
7566                         if (q == NULL) {
7567                                 *lpp = p;
7568                                 break;
7569                         }
7570                 }
7571         }
7572         return list;
7573 }
7574
7575 /*
7576  * Sort the results of file name expansion.  It calculates the number of
7577  * strings to sort and then calls msort (short for merge sort) to do the
7578  * work.
7579  */
7580 static struct strlist *
7581 expsort(struct strlist *str)
7582 {
7583         int len;
7584         struct strlist *sp;
7585
7586         len = 0;
7587         for (sp = str; sp; sp = sp->next)
7588                 len++;
7589         return msort(str, len);
7590 }
7591
7592 static void
7593 expandmeta(struct strlist *str /*, int flag*/)
7594 {
7595         /* TODO - EXP_REDIR */
7596
7597         while (str) {
7598                 char *expdir;
7599                 struct strlist **savelastp;
7600                 struct strlist *sp;
7601                 char *p;
7602
7603                 if (fflag)
7604                         goto nometa;
7605                 if (!hasmeta(str->text))
7606                         goto nometa;
7607                 savelastp = exparg.lastp;
7608
7609                 INT_OFF;
7610                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7611                 {
7612                         int i = strlen(str->text);
7613 //BUGGY estimation of how long expanded name can be
7614                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7615                 }
7616                 expmeta(expdir, expdir, p);
7617                 free(expdir);
7618                 if (p != str->text)
7619                         free(p);
7620                 INT_ON;
7621                 if (exparg.lastp == savelastp) {
7622                         /*
7623                          * no matches
7624                          */
7625  nometa:
7626                         *exparg.lastp = str;
7627                         rmescapes(str->text, 0);
7628                         exparg.lastp = &str->next;
7629                 } else {
7630                         *exparg.lastp = NULL;
7631                         *savelastp = sp = expsort(*savelastp);
7632                         while (sp->next != NULL)
7633                                 sp = sp->next;
7634                         exparg.lastp = &sp->next;
7635                 }
7636                 str = str->next;
7637         }
7638 }
7639 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7640
7641 /*
7642  * Perform variable substitution and command substitution on an argument,
7643  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7644  * perform splitting and file name expansion.  When arglist is NULL, perform
7645  * here document expansion.
7646  */
7647 static void
7648 expandarg(union node *arg, struct arglist *arglist, int flag)
7649 {
7650         struct strlist *sp;
7651         char *p;
7652
7653         argbackq = arg->narg.backquote;
7654         STARTSTACKSTR(expdest);
7655         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7656         argstr(arg->narg.text, flag);
7657         p = _STPUTC('\0', expdest);
7658         expdest = p - 1;
7659         if (arglist == NULL) {
7660                 /* here document expanded */
7661                 goto out;
7662         }
7663         p = grabstackstr(p);
7664         TRACE(("expandarg: p:'%s'\n", p));
7665         exparg.lastp = &exparg.list;
7666         /*
7667          * TODO - EXP_REDIR
7668          */
7669         if (flag & EXP_FULL) {
7670                 ifsbreakup(p, &exparg);
7671                 *exparg.lastp = NULL;
7672                 exparg.lastp = &exparg.list;
7673                 expandmeta(exparg.list /*, flag*/);
7674         } else {
7675                 sp = stzalloc(sizeof(*sp));
7676                 sp->text = p;
7677                 *exparg.lastp = sp;
7678                 exparg.lastp = &sp->next;
7679         }
7680         *exparg.lastp = NULL;
7681         if (exparg.list) {
7682                 *arglist->lastp = exparg.list;
7683                 arglist->lastp = exparg.lastp;
7684         }
7685
7686  out:
7687         ifsfree();
7688 }
7689
7690 /*
7691  * Expand shell variables and backquotes inside a here document.
7692  */
7693 static void
7694 expandhere(union node *arg, int fd)
7695 {
7696         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7697         full_write(fd, stackblock(), expdest - (char *)stackblock());
7698 }
7699
7700 /*
7701  * Returns true if the pattern matches the string.
7702  */
7703 static int
7704 patmatch(char *pattern, const char *string)
7705 {
7706         char *p = preglob(pattern, 0);
7707         int r = pmatch(p, string);
7708         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7709         return r;
7710 }
7711
7712 /*
7713  * See if a pattern matches in a case statement.
7714  */
7715 static int
7716 casematch(union node *pattern, char *val)
7717 {
7718         struct stackmark smark;
7719         int result;
7720
7721         setstackmark(&smark);
7722         argbackq = pattern->narg.backquote;
7723         STARTSTACKSTR(expdest);
7724         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7725         STACKSTRNUL(expdest);
7726         ifsfree();
7727         result = patmatch(stackblock(), val);
7728         popstackmark(&smark);
7729         return result;
7730 }
7731
7732
7733 /* ============ find_command */
7734
7735 struct builtincmd {
7736         const char *name;
7737         int (*builtin)(int, char **) FAST_FUNC;
7738         /* unsigned flags; */
7739 };
7740 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7741 /* "regular" builtins always take precedence over commands,
7742  * regardless of PATH=....%builtin... position */
7743 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7744 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7745
7746 struct cmdentry {
7747         smallint cmdtype;       /* CMDxxx */
7748         union param {
7749                 int index;
7750                 /* index >= 0 for commands without path (slashes) */
7751                 /* (TODO: what exactly does the value mean? PATH position?) */
7752                 /* index == -1 for commands with slashes */
7753                 /* index == (-2 - applet_no) for NOFORK applets */
7754                 const struct builtincmd *cmd;
7755                 struct funcnode *func;
7756         } u;
7757 };
7758 /* values of cmdtype */
7759 #define CMDUNKNOWN      -1      /* no entry in table for command */
7760 #define CMDNORMAL       0       /* command is an executable program */
7761 #define CMDFUNCTION     1       /* command is a shell function */
7762 #define CMDBUILTIN      2       /* command is a shell builtin */
7763
7764 /* action to find_command() */
7765 #define DO_ERR          0x01    /* prints errors */
7766 #define DO_ABS          0x02    /* checks absolute paths */
7767 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7768 #define DO_ALTPATH      0x08    /* using alternate path */
7769 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7770
7771 static void find_command(char *, struct cmdentry *, int, const char *);
7772
7773
7774 /* ============ Hashing commands */
7775
7776 /*
7777  * When commands are first encountered, they are entered in a hash table.
7778  * This ensures that a full path search will not have to be done for them
7779  * on each invocation.
7780  *
7781  * We should investigate converting to a linear search, even though that
7782  * would make the command name "hash" a misnomer.
7783  */
7784
7785 struct tblentry {
7786         struct tblentry *next;  /* next entry in hash chain */
7787         union param param;      /* definition of builtin function */
7788         smallint cmdtype;       /* CMDxxx */
7789         char rehash;            /* if set, cd done since entry created */
7790         char cmdname[1];        /* name of command */
7791 };
7792
7793 static struct tblentry **cmdtable;
7794 #define INIT_G_cmdtable() do { \
7795         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7796 } while (0)
7797
7798 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7799
7800
7801 static void
7802 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7803 {
7804 #if ENABLE_FEATURE_SH_STANDALONE
7805         if (applet_no >= 0) {
7806                 if (APPLET_IS_NOEXEC(applet_no)) {
7807                         clearenv();
7808                         while (*envp)
7809                                 putenv(*envp++);
7810                         popredir(/*drop:*/ 1);
7811                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7812                 }
7813                 /* re-exec ourselves with the new arguments */
7814                 execve(bb_busybox_exec_path, argv, envp);
7815                 /* If they called chroot or otherwise made the binary no longer
7816                  * executable, fall through */
7817         }
7818 #endif
7819
7820  repeat:
7821 #ifdef SYSV
7822         do {
7823                 execve(cmd, argv, envp);
7824         } while (errno == EINTR);
7825 #else
7826         execve(cmd, argv, envp);
7827 #endif
7828         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7829                 /* Run "cmd" as a shell script:
7830                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7831                  * "If the execve() function fails with ENOEXEC, the shell
7832                  * shall execute a command equivalent to having a shell invoked
7833                  * with the command name as its first operand,
7834                  * with any remaining arguments passed to the new shell"
7835                  *
7836                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7837                  * just call ourselves.
7838                  *
7839                  * Note that bash reads ~80 chars of the file, and if it sees
7840                  * a zero byte before it sees newline, it doesn't try to
7841                  * interpret it, but fails with "cannot execute binary file"
7842                  * message and exit code 126. For one, this prevents attempts
7843                  * to interpret foreign ELF binaries as shell scripts.
7844                  */
7845                 argv[0] = (char*) cmd;
7846                 cmd = bb_busybox_exec_path;
7847                 /* NB: this is only possible because all callers of shellexec()
7848                  * ensure that the argv[-1] slot exists!
7849                  */
7850                 argv--;
7851                 argv[0] = (char*) "ash";
7852                 goto repeat;
7853         }
7854 }
7855
7856 /*
7857  * Exec a program.  Never returns.  If you change this routine, you may
7858  * have to change the find_command routine as well.
7859  * argv[-1] must exist and be writable! See tryexec() for why.
7860  */
7861 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7862 static void shellexec(char *prog, char **argv, const char *path, int idx)
7863 {
7864         char *cmdname;
7865         int e;
7866         char **envp;
7867         int exerrno;
7868         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7869
7870         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7871         if (strchr(prog, '/') != NULL
7872 #if ENABLE_FEATURE_SH_STANDALONE
7873          || (applet_no = find_applet_by_name(prog)) >= 0
7874 #endif
7875         ) {
7876                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7877                 if (applet_no >= 0) {
7878                         /* We tried execing ourself, but it didn't work.
7879                          * Maybe /proc/self/exe doesn't exist?
7880                          * Try $PATH search.
7881                          */
7882                         goto try_PATH;
7883                 }
7884                 e = errno;
7885         } else {
7886  try_PATH:
7887                 e = ENOENT;
7888                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7889                         if (--idx < 0 && pathopt == NULL) {
7890                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7891                                 if (errno != ENOENT && errno != ENOTDIR)
7892                                         e = errno;
7893                         }
7894                         stunalloc(cmdname);
7895                 }
7896         }
7897
7898         /* Map to POSIX errors */
7899         switch (e) {
7900         case EACCES:
7901                 exerrno = 126;
7902                 break;
7903         case ENOENT:
7904                 exerrno = 127;
7905                 break;
7906         default:
7907                 exerrno = 2;
7908                 break;
7909         }
7910         exitstatus = exerrno;
7911         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7912                 prog, e, suppress_int));
7913         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7914         /* NOTREACHED */
7915 }
7916
7917 static void
7918 printentry(struct tblentry *cmdp)
7919 {
7920         int idx;
7921         const char *path;
7922         char *name;
7923
7924         idx = cmdp->param.index;
7925         path = pathval();
7926         do {
7927                 name = path_advance(&path, cmdp->cmdname);
7928                 stunalloc(name);
7929         } while (--idx >= 0);
7930         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7931 }
7932
7933 /*
7934  * Clear out command entries.  The argument specifies the first entry in
7935  * PATH which has changed.
7936  */
7937 static void
7938 clearcmdentry(int firstchange)
7939 {
7940         struct tblentry **tblp;
7941         struct tblentry **pp;
7942         struct tblentry *cmdp;
7943
7944         INT_OFF;
7945         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7946                 pp = tblp;
7947                 while ((cmdp = *pp) != NULL) {
7948                         if ((cmdp->cmdtype == CMDNORMAL &&
7949                              cmdp->param.index >= firstchange)
7950                          || (cmdp->cmdtype == CMDBUILTIN &&
7951                              builtinloc >= firstchange)
7952                         ) {
7953                                 *pp = cmdp->next;
7954                                 free(cmdp);
7955                         } else {
7956                                 pp = &cmdp->next;
7957                         }
7958                 }
7959         }
7960         INT_ON;
7961 }
7962
7963 /*
7964  * Locate a command in the command hash table.  If "add" is nonzero,
7965  * add the command to the table if it is not already present.  The
7966  * variable "lastcmdentry" is set to point to the address of the link
7967  * pointing to the entry, so that delete_cmd_entry can delete the
7968  * entry.
7969  *
7970  * Interrupts must be off if called with add != 0.
7971  */
7972 static struct tblentry **lastcmdentry;
7973
7974 static struct tblentry *
7975 cmdlookup(const char *name, int add)
7976 {
7977         unsigned int hashval;
7978         const char *p;
7979         struct tblentry *cmdp;
7980         struct tblentry **pp;
7981
7982         p = name;
7983         hashval = (unsigned char)*p << 4;
7984         while (*p)
7985                 hashval += (unsigned char)*p++;
7986         hashval &= 0x7FFF;
7987         pp = &cmdtable[hashval % CMDTABLESIZE];
7988         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7989                 if (strcmp(cmdp->cmdname, name) == 0)
7990                         break;
7991                 pp = &cmdp->next;
7992         }
7993         if (add && cmdp == NULL) {
7994                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7995                                 + strlen(name)
7996                                 /* + 1 - already done because
7997                                  * tblentry::cmdname is char[1] */);
7998                 /*cmdp->next = NULL; - ckzalloc did it */
7999                 cmdp->cmdtype = CMDUNKNOWN;
8000                 strcpy(cmdp->cmdname, name);
8001         }
8002         lastcmdentry = pp;
8003         return cmdp;
8004 }
8005
8006 /*
8007  * Delete the command entry returned on the last lookup.
8008  */
8009 static void
8010 delete_cmd_entry(void)
8011 {
8012         struct tblentry *cmdp;
8013
8014         INT_OFF;
8015         cmdp = *lastcmdentry;
8016         *lastcmdentry = cmdp->next;
8017         if (cmdp->cmdtype == CMDFUNCTION)
8018                 freefunc(cmdp->param.func);
8019         free(cmdp);
8020         INT_ON;
8021 }
8022
8023 /*
8024  * Add a new command entry, replacing any existing command entry for
8025  * the same name - except special builtins.
8026  */
8027 static void
8028 addcmdentry(char *name, struct cmdentry *entry)
8029 {
8030         struct tblentry *cmdp;
8031
8032         cmdp = cmdlookup(name, 1);
8033         if (cmdp->cmdtype == CMDFUNCTION) {
8034                 freefunc(cmdp->param.func);
8035         }
8036         cmdp->cmdtype = entry->cmdtype;
8037         cmdp->param = entry->u;
8038         cmdp->rehash = 0;
8039 }
8040
8041 static int FAST_FUNC
8042 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8043 {
8044         struct tblentry **pp;
8045         struct tblentry *cmdp;
8046         int c;
8047         struct cmdentry entry;
8048         char *name;
8049
8050         if (nextopt("r") != '\0') {
8051                 clearcmdentry(0);
8052                 return 0;
8053         }
8054
8055         if (*argptr == NULL) {
8056                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8057                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8058                                 if (cmdp->cmdtype == CMDNORMAL)
8059                                         printentry(cmdp);
8060                         }
8061                 }
8062                 return 0;
8063         }
8064
8065         c = 0;
8066         while ((name = *argptr) != NULL) {
8067                 cmdp = cmdlookup(name, 0);
8068                 if (cmdp != NULL
8069                  && (cmdp->cmdtype == CMDNORMAL
8070                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8071                 ) {
8072                         delete_cmd_entry();
8073                 }
8074                 find_command(name, &entry, DO_ERR, pathval());
8075                 if (entry.cmdtype == CMDUNKNOWN)
8076                         c = 1;
8077                 argptr++;
8078         }
8079         return c;
8080 }
8081
8082 /*
8083  * Called when a cd is done.  Marks all commands so the next time they
8084  * are executed they will be rehashed.
8085  */
8086 static void
8087 hashcd(void)
8088 {
8089         struct tblentry **pp;
8090         struct tblentry *cmdp;
8091
8092         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8093                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8094                         if (cmdp->cmdtype == CMDNORMAL
8095                          || (cmdp->cmdtype == CMDBUILTIN
8096                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8097                              && builtinloc > 0)
8098                         ) {
8099                                 cmdp->rehash = 1;
8100                         }
8101                 }
8102         }
8103 }
8104
8105 /*
8106  * Fix command hash table when PATH changed.
8107  * Called before PATH is changed.  The argument is the new value of PATH;
8108  * pathval() still returns the old value at this point.
8109  * Called with interrupts off.
8110  */
8111 static void FAST_FUNC
8112 changepath(const char *new)
8113 {
8114         const char *old;
8115         int firstchange;
8116         int idx;
8117         int idx_bltin;
8118
8119         old = pathval();
8120         firstchange = 9999;     /* assume no change */
8121         idx = 0;
8122         idx_bltin = -1;
8123         for (;;) {
8124                 if (*old != *new) {
8125                         firstchange = idx;
8126                         if ((*old == '\0' && *new == ':')
8127                          || (*old == ':' && *new == '\0')
8128                         ) {
8129                                 firstchange++;
8130                         }
8131                         old = new;      /* ignore subsequent differences */
8132                 }
8133                 if (*new == '\0')
8134                         break;
8135                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8136                         idx_bltin = idx;
8137                 if (*new == ':')
8138                         idx++;
8139                 new++;
8140                 old++;
8141         }
8142         if (builtinloc < 0 && idx_bltin >= 0)
8143                 builtinloc = idx_bltin;             /* zap builtins */
8144         if (builtinloc >= 0 && idx_bltin < 0)
8145                 firstchange = 0;
8146         clearcmdentry(firstchange);
8147         builtinloc = idx_bltin;
8148 }
8149 enum {
8150         TEOF,
8151         TNL,
8152         TREDIR,
8153         TWORD,
8154         TSEMI,
8155         TBACKGND,
8156         TAND,
8157         TOR,
8158         TPIPE,
8159         TLP,
8160         TRP,
8161         TENDCASE,
8162         TENDBQUOTE,
8163         TNOT,
8164         TCASE,
8165         TDO,
8166         TDONE,
8167         TELIF,
8168         TELSE,
8169         TESAC,
8170         TFI,
8171         TFOR,
8172 #if BASH_FUNCTION
8173         TFUNCTION,
8174 #endif
8175         TIF,
8176         TIN,
8177         TTHEN,
8178         TUNTIL,
8179         TWHILE,
8180         TBEGIN,
8181         TEND
8182 };
8183 typedef smallint token_id_t;
8184
8185 /* Nth bit indicates if token marks the end of a list */
8186 enum {
8187         tokendlist = 0
8188         /*  0 */ | (1u << TEOF)
8189         /*  1 */ | (0u << TNL)
8190         /*  2 */ | (0u << TREDIR)
8191         /*  3 */ | (0u << TWORD)
8192         /*  4 */ | (0u << TSEMI)
8193         /*  5 */ | (0u << TBACKGND)
8194         /*  6 */ | (0u << TAND)
8195         /*  7 */ | (0u << TOR)
8196         /*  8 */ | (0u << TPIPE)
8197         /*  9 */ | (0u << TLP)
8198         /* 10 */ | (1u << TRP)
8199         /* 11 */ | (1u << TENDCASE)
8200         /* 12 */ | (1u << TENDBQUOTE)
8201         /* 13 */ | (0u << TNOT)
8202         /* 14 */ | (0u << TCASE)
8203         /* 15 */ | (1u << TDO)
8204         /* 16 */ | (1u << TDONE)
8205         /* 17 */ | (1u << TELIF)
8206         /* 18 */ | (1u << TELSE)
8207         /* 19 */ | (1u << TESAC)
8208         /* 20 */ | (1u << TFI)
8209         /* 21 */ | (0u << TFOR)
8210 #if BASH_FUNCTION
8211         /* 22 */ | (0u << TFUNCTION)
8212 #endif
8213         /* 23 */ | (0u << TIF)
8214         /* 24 */ | (0u << TIN)
8215         /* 25 */ | (1u << TTHEN)
8216         /* 26 */ | (0u << TUNTIL)
8217         /* 27 */ | (0u << TWHILE)
8218         /* 28 */ | (0u << TBEGIN)
8219         /* 29 */ | (1u << TEND)
8220         , /* thus far 29 bits used */
8221 };
8222
8223 static const char *const tokname_array[] = {
8224         "end of file",
8225         "newline",
8226         "redirection",
8227         "word",
8228         ";",
8229         "&",
8230         "&&",
8231         "||",
8232         "|",
8233         "(",
8234         ")",
8235         ";;",
8236         "`",
8237 #define KWDOFFSET 13
8238         /* the following are keywords */
8239         "!",
8240         "case",
8241         "do",
8242         "done",
8243         "elif",
8244         "else",
8245         "esac",
8246         "fi",
8247         "for",
8248 #if BASH_FUNCTION
8249         "function",
8250 #endif
8251         "if",
8252         "in",
8253         "then",
8254         "until",
8255         "while",
8256         "{",
8257         "}",
8258 };
8259
8260 /* Wrapper around strcmp for qsort/bsearch/... */
8261 static int
8262 pstrcmp(const void *a, const void *b)
8263 {
8264         return strcmp((char*)a, *(char**)b);
8265 }
8266
8267 static const char *const *
8268 findkwd(const char *s)
8269 {
8270         return bsearch(s, tokname_array + KWDOFFSET,
8271                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8272                         sizeof(tokname_array[0]), pstrcmp);
8273 }
8274
8275 /*
8276  * Locate and print what a word is...
8277  */
8278 static int
8279 describe_command(char *command, const char *path, int describe_command_verbose)
8280 {
8281         struct cmdentry entry;
8282 #if ENABLE_ASH_ALIAS
8283         const struct alias *ap;
8284 #endif
8285
8286         path = path ? path : pathval();
8287
8288         if (describe_command_verbose) {
8289                 out1str(command);
8290         }
8291
8292         /* First look at the keywords */
8293         if (findkwd(command)) {
8294                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8295                 goto out;
8296         }
8297
8298 #if ENABLE_ASH_ALIAS
8299         /* Then look at the aliases */
8300         ap = lookupalias(command, 0);
8301         if (ap != NULL) {
8302                 if (!describe_command_verbose) {
8303                         out1str("alias ");
8304                         printalias(ap);
8305                         return 0;
8306                 }
8307                 out1fmt(" is an alias for %s", ap->val);
8308                 goto out;
8309         }
8310 #endif
8311         /* Brute force */
8312         find_command(command, &entry, DO_ABS, path);
8313
8314         switch (entry.cmdtype) {
8315         case CMDNORMAL: {
8316                 int j = entry.u.index;
8317                 char *p;
8318                 if (j < 0) {
8319                         p = command;
8320                 } else {
8321                         do {
8322                                 p = path_advance(&path, command);
8323                                 stunalloc(p);
8324                         } while (--j >= 0);
8325                 }
8326                 if (describe_command_verbose) {
8327                         out1fmt(" is %s", p);
8328                 } else {
8329                         out1str(p);
8330                 }
8331                 break;
8332         }
8333
8334         case CMDFUNCTION:
8335                 if (describe_command_verbose) {
8336                         out1str(" is a shell function");
8337                 } else {
8338                         out1str(command);
8339                 }
8340                 break;
8341
8342         case CMDBUILTIN:
8343                 if (describe_command_verbose) {
8344                         out1fmt(" is a %sshell builtin",
8345                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8346                                         "special " : nullstr
8347                         );
8348                 } else {
8349                         out1str(command);
8350                 }
8351                 break;
8352
8353         default:
8354                 if (describe_command_verbose) {
8355                         out1str(": not found\n");
8356                 }
8357                 return 127;
8358         }
8359  out:
8360         out1str("\n");
8361         return 0;
8362 }
8363
8364 static int FAST_FUNC
8365 typecmd(int argc UNUSED_PARAM, char **argv)
8366 {
8367         int i = 1;
8368         int err = 0;
8369         int verbose = 1;
8370
8371         /* type -p ... ? (we don't bother checking for 'p') */
8372         if (argv[1] && argv[1][0] == '-') {
8373                 i++;
8374                 verbose = 0;
8375         }
8376         while (argv[i]) {
8377                 err |= describe_command(argv[i++], NULL, verbose);
8378         }
8379         return err;
8380 }
8381
8382 #if ENABLE_ASH_CMDCMD
8383 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8384 static char **
8385 parse_command_args(char **argv, const char **path)
8386 {
8387         char *cp, c;
8388
8389         for (;;) {
8390                 cp = *++argv;
8391                 if (!cp)
8392                         return NULL;
8393                 if (*cp++ != '-')
8394                         break;
8395                 c = *cp++;
8396                 if (!c)
8397                         break;
8398                 if (c == '-' && !*cp) {
8399                         if (!*++argv)
8400                                 return NULL;
8401                         break;
8402                 }
8403                 do {
8404                         switch (c) {
8405                         case 'p':
8406                                 *path = bb_default_path;
8407                                 break;
8408                         default:
8409                                 /* run 'typecmd' for other options */
8410                                 return NULL;
8411                         }
8412                         c = *cp++;
8413                 } while (c);
8414         }
8415         return argv;
8416 }
8417
8418 static int FAST_FUNC
8419 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8420 {
8421         char *cmd;
8422         int c;
8423         enum {
8424                 VERIFY_BRIEF = 1,
8425                 VERIFY_VERBOSE = 2,
8426         } verify = 0;
8427         const char *path = NULL;
8428
8429         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8430          * never reaches this function.
8431          */
8432
8433         while ((c = nextopt("pvV")) != '\0')
8434                 if (c == 'V')
8435                         verify |= VERIFY_VERBOSE;
8436                 else if (c == 'v')
8437                         /*verify |= VERIFY_BRIEF*/;
8438 #if DEBUG
8439                 else if (c != 'p')
8440                         abort();
8441 #endif
8442                 else
8443                         path = bb_default_path;
8444
8445         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8446         cmd = *argptr;
8447         if (/*verify && */ cmd)
8448                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8449
8450         return 0;
8451 }
8452 #endif
8453
8454
8455 /*static int funcblocksize;     // size of structures in function */
8456 /*static int funcstringsize;    // size of strings in node */
8457 static void *funcblock;         /* block to allocate function from */
8458 static char *funcstring_end;    /* end of block to allocate strings from */
8459
8460 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8461         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8462         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8463         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8464         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8465         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8466         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8467         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8468         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8469         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8470         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8471         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8472         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8473         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8474         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8475         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8476         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8477         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8478 #if BASH_REDIR_OUTPUT
8479         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8480 #endif
8481         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8482         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8483         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8484         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8485         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8486         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8487         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8488         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8489         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8490 };
8491
8492 static int calcsize(int funcblocksize, union node *n);
8493
8494 static int
8495 sizenodelist(int funcblocksize, struct nodelist *lp)
8496 {
8497         while (lp) {
8498                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8499                 funcblocksize = calcsize(funcblocksize, lp->n);
8500                 lp = lp->next;
8501         }
8502         return funcblocksize;
8503 }
8504
8505 static int
8506 calcsize(int funcblocksize, union node *n)
8507 {
8508         if (n == NULL)
8509                 return funcblocksize;
8510         funcblocksize += nodesize[n->type];
8511         switch (n->type) {
8512         case NCMD:
8513                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8514                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8515                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8516                 break;
8517         case NPIPE:
8518                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8519                 break;
8520         case NREDIR:
8521         case NBACKGND:
8522         case NSUBSHELL:
8523                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8524                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8525                 break;
8526         case NAND:
8527         case NOR:
8528         case NSEMI:
8529         case NWHILE:
8530         case NUNTIL:
8531                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8532                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8533                 break;
8534         case NIF:
8535                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8536                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8537                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8538                 break;
8539         case NFOR:
8540                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8541                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8542                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8543                 break;
8544         case NCASE:
8545                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8546                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8547                 break;
8548         case NCLIST:
8549                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8550                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8551                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8552                 break;
8553         case NDEFUN:
8554         case NARG:
8555                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8556                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8557                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8558                 break;
8559         case NTO:
8560 #if BASH_REDIR_OUTPUT
8561         case NTO2:
8562 #endif
8563         case NCLOBBER:
8564         case NFROM:
8565         case NFROMTO:
8566         case NAPPEND:
8567                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8568                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8569                 break;
8570         case NTOFD:
8571         case NFROMFD:
8572                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8573                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8574         break;
8575         case NHERE:
8576         case NXHERE:
8577                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8578                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8579                 break;
8580         case NNOT:
8581                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8582                 break;
8583         };
8584         return funcblocksize;
8585 }
8586
8587 static char *
8588 nodeckstrdup(char *s)
8589 {
8590         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8591         return strcpy(funcstring_end, s);
8592 }
8593
8594 static union node *copynode(union node *);
8595
8596 static struct nodelist *
8597 copynodelist(struct nodelist *lp)
8598 {
8599         struct nodelist *start;
8600         struct nodelist **lpp;
8601
8602         lpp = &start;
8603         while (lp) {
8604                 *lpp = funcblock;
8605                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8606                 (*lpp)->n = copynode(lp->n);
8607                 lp = lp->next;
8608                 lpp = &(*lpp)->next;
8609         }
8610         *lpp = NULL;
8611         return start;
8612 }
8613
8614 static union node *
8615 copynode(union node *n)
8616 {
8617         union node *new;
8618
8619         if (n == NULL)
8620                 return NULL;
8621         new = funcblock;
8622         funcblock = (char *) funcblock + nodesize[n->type];
8623
8624         switch (n->type) {
8625         case NCMD:
8626                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8627                 new->ncmd.args = copynode(n->ncmd.args);
8628                 new->ncmd.assign = copynode(n->ncmd.assign);
8629                 break;
8630         case NPIPE:
8631                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8632                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8633                 break;
8634         case NREDIR:
8635         case NBACKGND:
8636         case NSUBSHELL:
8637                 new->nredir.redirect = copynode(n->nredir.redirect);
8638                 new->nredir.n = copynode(n->nredir.n);
8639                 break;
8640         case NAND:
8641         case NOR:
8642         case NSEMI:
8643         case NWHILE:
8644         case NUNTIL:
8645                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8646                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8647                 break;
8648         case NIF:
8649                 new->nif.elsepart = copynode(n->nif.elsepart);
8650                 new->nif.ifpart = copynode(n->nif.ifpart);
8651                 new->nif.test = copynode(n->nif.test);
8652                 break;
8653         case NFOR:
8654                 new->nfor.var = nodeckstrdup(n->nfor.var);
8655                 new->nfor.body = copynode(n->nfor.body);
8656                 new->nfor.args = copynode(n->nfor.args);
8657                 break;
8658         case NCASE:
8659                 new->ncase.cases = copynode(n->ncase.cases);
8660                 new->ncase.expr = copynode(n->ncase.expr);
8661                 break;
8662         case NCLIST:
8663                 new->nclist.body = copynode(n->nclist.body);
8664                 new->nclist.pattern = copynode(n->nclist.pattern);
8665                 new->nclist.next = copynode(n->nclist.next);
8666                 break;
8667         case NDEFUN:
8668         case NARG:
8669                 new->narg.backquote = copynodelist(n->narg.backquote);
8670                 new->narg.text = nodeckstrdup(n->narg.text);
8671                 new->narg.next = copynode(n->narg.next);
8672                 break;
8673         case NTO:
8674 #if BASH_REDIR_OUTPUT
8675         case NTO2:
8676 #endif
8677         case NCLOBBER:
8678         case NFROM:
8679         case NFROMTO:
8680         case NAPPEND:
8681                 new->nfile.fname = copynode(n->nfile.fname);
8682                 new->nfile.fd = n->nfile.fd;
8683                 new->nfile.next = copynode(n->nfile.next);
8684                 break;
8685         case NTOFD:
8686         case NFROMFD:
8687                 new->ndup.vname = copynode(n->ndup.vname);
8688                 new->ndup.dupfd = n->ndup.dupfd;
8689                 new->ndup.fd = n->ndup.fd;
8690                 new->ndup.next = copynode(n->ndup.next);
8691                 break;
8692         case NHERE:
8693         case NXHERE:
8694                 new->nhere.doc = copynode(n->nhere.doc);
8695                 new->nhere.fd = n->nhere.fd;
8696                 new->nhere.next = copynode(n->nhere.next);
8697                 break;
8698         case NNOT:
8699                 new->nnot.com = copynode(n->nnot.com);
8700                 break;
8701         };
8702         new->type = n->type;
8703         return new;
8704 }
8705
8706 /*
8707  * Make a copy of a parse tree.
8708  */
8709 static struct funcnode *
8710 copyfunc(union node *n)
8711 {
8712         struct funcnode *f;
8713         size_t blocksize;
8714
8715         /*funcstringsize = 0;*/
8716         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8717         f = ckzalloc(blocksize /* + funcstringsize */);
8718         funcblock = (char *) f + offsetof(struct funcnode, n);
8719         funcstring_end = (char *) f + blocksize;
8720         copynode(n);
8721         /* f->count = 0; - ckzalloc did it */
8722         return f;
8723 }
8724
8725 /*
8726  * Define a shell function.
8727  */
8728 static void
8729 defun(union node *func)
8730 {
8731         struct cmdentry entry;
8732
8733         INT_OFF;
8734         entry.cmdtype = CMDFUNCTION;
8735         entry.u.func = copyfunc(func);
8736         addcmdentry(func->narg.text, &entry);
8737         INT_ON;
8738 }
8739
8740 /* Reasons for skipping commands (see comment on breakcmd routine) */
8741 #define SKIPBREAK      (1 << 0)
8742 #define SKIPCONT       (1 << 1)
8743 #define SKIPFUNC       (1 << 2)
8744 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8745 static int skipcount;           /* number of levels to skip */
8746 static int funcnest;            /* depth of function calls */
8747 static int loopnest;            /* current loop nesting level */
8748
8749 /* Forward decl way out to parsing code - dotrap needs it */
8750 static int evalstring(char *s, int flags);
8751
8752 /* Called to execute a trap.
8753  * Single callsite - at the end of evaltree().
8754  * If we return non-zero, evaltree raises EXEXIT exception.
8755  *
8756  * Perhaps we should avoid entering new trap handlers
8757  * while we are executing a trap handler. [is it a TODO?]
8758  */
8759 static void
8760 dotrap(void)
8761 {
8762         uint8_t *g;
8763         int sig;
8764         uint8_t last_status;
8765
8766         if (!pending_sig)
8767                 return;
8768
8769         last_status = exitstatus;
8770         pending_sig = 0;
8771         barrier();
8772
8773         TRACE(("dotrap entered\n"));
8774         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8775                 char *p;
8776
8777                 if (!*g)
8778                         continue;
8779
8780                 if (evalskip) {
8781                         pending_sig = sig;
8782                         break;
8783                 }
8784
8785                 p = trap[sig];
8786                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8787                  * don't upset it by resetting gotsig[SIGINT-1] */
8788                 if (sig == SIGINT && !p)
8789                         continue;
8790
8791                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8792                 *g = 0;
8793                 if (!p)
8794                         continue;
8795                 evalstring(p, 0);
8796         }
8797         exitstatus = last_status;
8798         TRACE(("dotrap returns\n"));
8799 }
8800
8801 /* forward declarations - evaluation is fairly recursive business... */
8802 static int evalloop(union node *, int);
8803 static int evalfor(union node *, int);
8804 static int evalcase(union node *, int);
8805 static int evalsubshell(union node *, int);
8806 static void expredir(union node *);
8807 static int evalpipe(union node *, int);
8808 static int evalcommand(union node *, int);
8809 static int evalbltin(const struct builtincmd *, int, char **, int);
8810 static void prehash(union node *);
8811
8812 /*
8813  * Evaluate a parse tree.  The value is left in the global variable
8814  * exitstatus.
8815  */
8816 static int
8817 evaltree(union node *n, int flags)
8818 {
8819         int checkexit = 0;
8820         int (*evalfn)(union node *, int);
8821         int status = 0;
8822
8823         if (n == NULL) {
8824                 TRACE(("evaltree(NULL) called\n"));
8825                 goto out;
8826         }
8827         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8828
8829         dotrap();
8830
8831         switch (n->type) {
8832         default:
8833 #if DEBUG
8834                 out1fmt("Node type = %d\n", n->type);
8835                 fflush_all();
8836                 break;
8837 #endif
8838         case NNOT:
8839                 status = !evaltree(n->nnot.com, EV_TESTED);
8840                 goto setstatus;
8841         case NREDIR:
8842                 expredir(n->nredir.redirect);
8843                 pushredir(n->nredir.redirect);
8844                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8845                 if (!status) {
8846                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8847                 }
8848                 if (n->nredir.redirect)
8849                         popredir(/*drop:*/ 0);
8850                 goto setstatus;
8851         case NCMD:
8852                 evalfn = evalcommand;
8853  checkexit:
8854                 if (eflag && !(flags & EV_TESTED))
8855                         checkexit = ~0;
8856                 goto calleval;
8857         case NFOR:
8858                 evalfn = evalfor;
8859                 goto calleval;
8860         case NWHILE:
8861         case NUNTIL:
8862                 evalfn = evalloop;
8863                 goto calleval;
8864         case NSUBSHELL:
8865         case NBACKGND:
8866                 evalfn = evalsubshell;
8867                 goto checkexit;
8868         case NPIPE:
8869                 evalfn = evalpipe;
8870                 goto checkexit;
8871         case NCASE:
8872                 evalfn = evalcase;
8873                 goto calleval;
8874         case NAND:
8875         case NOR:
8876         case NSEMI: {
8877
8878 #if NAND + 1 != NOR
8879 #error NAND + 1 != NOR
8880 #endif
8881 #if NOR + 1 != NSEMI
8882 #error NOR + 1 != NSEMI
8883 #endif
8884                 unsigned is_or = n->type - NAND;
8885                 status = evaltree(
8886                         n->nbinary.ch1,
8887                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8888                 );
8889                 if ((!status) == is_or || evalskip)
8890                         break;
8891                 n = n->nbinary.ch2;
8892  evaln:
8893                 evalfn = evaltree;
8894  calleval:
8895                 status = evalfn(n, flags);
8896                 goto setstatus;
8897         }
8898         case NIF:
8899                 status = evaltree(n->nif.test, EV_TESTED);
8900                 if (evalskip)
8901                         break;
8902                 if (!status) {
8903                         n = n->nif.ifpart;
8904                         goto evaln;
8905                 }
8906                 if (n->nif.elsepart) {
8907                         n = n->nif.elsepart;
8908                         goto evaln;
8909                 }
8910                 status = 0;
8911                 goto setstatus;
8912         case NDEFUN:
8913                 defun(n);
8914                 /* Not necessary. To test it:
8915                  * "false; f() { qwerty; }; echo $?" should print 0.
8916                  */
8917                 /* status = 0; */
8918  setstatus:
8919                 exitstatus = status;
8920                 break;
8921         }
8922  out:
8923         /* Order of checks below is important:
8924          * signal handlers trigger before exit caused by "set -e".
8925          */
8926         dotrap();
8927
8928         if (checkexit & status)
8929                 raise_exception(EXEXIT);
8930         if (flags & EV_EXIT)
8931                 raise_exception(EXEXIT);
8932
8933         TRACE(("leaving evaltree (no interrupts)\n"));
8934         return exitstatus;
8935 }
8936
8937 static int
8938 skiploop(void)
8939 {
8940         int skip = evalskip;
8941
8942         switch (skip) {
8943         case 0:
8944                 break;
8945         case SKIPBREAK:
8946         case SKIPCONT:
8947                 if (--skipcount <= 0) {
8948                         evalskip = 0;
8949                         break;
8950                 }
8951                 skip = SKIPBREAK;
8952                 break;
8953         }
8954         return skip;
8955 }
8956
8957 static int
8958 evalloop(union node *n, int flags)
8959 {
8960         int skip;
8961         int status;
8962
8963         loopnest++;
8964         status = 0;
8965         flags &= EV_TESTED;
8966         do {
8967                 int i;
8968
8969                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8970                 skip = skiploop();
8971                 if (skip == SKIPFUNC)
8972                         status = i;
8973                 if (skip)
8974                         continue;
8975                 if (n->type != NWHILE)
8976                         i = !i;
8977                 if (i != 0)
8978                         break;
8979                 status = evaltree(n->nbinary.ch2, flags);
8980                 skip = skiploop();
8981         } while (!(skip & ~SKIPCONT));
8982         loopnest--;
8983
8984         return status;
8985 }
8986
8987 static int
8988 evalfor(union node *n, int flags)
8989 {
8990         struct arglist arglist;
8991         union node *argp;
8992         struct strlist *sp;
8993         struct stackmark smark;
8994         int status = 0;
8995
8996         setstackmark(&smark);
8997         arglist.list = NULL;
8998         arglist.lastp = &arglist.list;
8999         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9000                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9001         }
9002         *arglist.lastp = NULL;
9003
9004         loopnest++;
9005         flags &= EV_TESTED;
9006         for (sp = arglist.list; sp; sp = sp->next) {
9007                 setvar0(n->nfor.var, sp->text);
9008                 status = evaltree(n->nfor.body, flags);
9009                 if (skiploop() & ~SKIPCONT)
9010                         break;
9011         }
9012         loopnest--;
9013         popstackmark(&smark);
9014
9015         return status;
9016 }
9017
9018 static int
9019 evalcase(union node *n, int flags)
9020 {
9021         union node *cp;
9022         union node *patp;
9023         struct arglist arglist;
9024         struct stackmark smark;
9025         int status = 0;
9026
9027         setstackmark(&smark);
9028         arglist.list = NULL;
9029         arglist.lastp = &arglist.list;
9030         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9031         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9032                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9033                         if (casematch(patp, arglist.list->text)) {
9034                                 /* Ensure body is non-empty as otherwise
9035                                  * EV_EXIT may prevent us from setting the
9036                                  * exit status.
9037                                  */
9038                                 if (evalskip == 0 && cp->nclist.body) {
9039                                         status = evaltree(cp->nclist.body, flags);
9040                                 }
9041                                 goto out;
9042                         }
9043                 }
9044         }
9045  out:
9046         popstackmark(&smark);
9047
9048         return status;
9049 }
9050
9051 /*
9052  * Kick off a subshell to evaluate a tree.
9053  */
9054 static int
9055 evalsubshell(union node *n, int flags)
9056 {
9057         struct job *jp;
9058         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9059         int status;
9060
9061         expredir(n->nredir.redirect);
9062         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9063                 goto nofork;
9064         INT_OFF;
9065         if (backgnd == FORK_FG)
9066                 get_tty_state();
9067         jp = makejob(/*n,*/ 1);
9068         if (forkshell(jp, n, backgnd) == 0) {
9069                 /* child */
9070                 INT_ON;
9071                 flags |= EV_EXIT;
9072                 if (backgnd)
9073                         flags &= ~EV_TESTED;
9074  nofork:
9075                 redirect(n->nredir.redirect, 0);
9076                 evaltreenr(n->nredir.n, flags);
9077                 /* never returns */
9078         }
9079         /* parent */
9080         status = 0;
9081         if (backgnd == FORK_FG)
9082                 status = waitforjob(jp);
9083         INT_ON;
9084         return status;
9085 }
9086
9087 /*
9088  * Compute the names of the files in a redirection list.
9089  */
9090 static void fixredir(union node *, const char *, int);
9091 static void
9092 expredir(union node *n)
9093 {
9094         union node *redir;
9095
9096         for (redir = n; redir; redir = redir->nfile.next) {
9097                 struct arglist fn;
9098
9099                 fn.list = NULL;
9100                 fn.lastp = &fn.list;
9101                 switch (redir->type) {
9102                 case NFROMTO:
9103                 case NFROM:
9104                 case NTO:
9105 #if BASH_REDIR_OUTPUT
9106                 case NTO2:
9107 #endif
9108                 case NCLOBBER:
9109                 case NAPPEND:
9110                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9111                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9112 #if BASH_REDIR_OUTPUT
9113  store_expfname:
9114 #endif
9115 #if 0
9116 // By the design of stack allocator, the loop of this kind:
9117 //      while true; do while true; do break; done </dev/null; done
9118 // will look like a memory leak: ash plans to free expfname's
9119 // of "/dev/null" as soon as it finishes running the loop
9120 // (in this case, never).
9121 // This "fix" is wrong:
9122                         if (redir->nfile.expfname)
9123                                 stunalloc(redir->nfile.expfname);
9124 // It results in corrupted state of stacked allocations.
9125 #endif
9126                         redir->nfile.expfname = fn.list->text;
9127                         break;
9128                 case NFROMFD:
9129                 case NTOFD: /* >& */
9130                         if (redir->ndup.vname) {
9131                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9132                                 if (fn.list == NULL)
9133                                         ash_msg_and_raise_error("redir error");
9134 #if BASH_REDIR_OUTPUT
9135 //FIXME: we used expandarg with different args!
9136                                 if (!isdigit_str9(fn.list->text)) {
9137                                         /* >&file, not >&fd */
9138                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9139                                                 ash_msg_and_raise_error("redir error");
9140                                         redir->type = NTO2;
9141                                         goto store_expfname;
9142                                 }
9143 #endif
9144                                 fixredir(redir, fn.list->text, 1);
9145                         }
9146                         break;
9147                 }
9148         }
9149 }
9150
9151 /*
9152  * Evaluate a pipeline.  All the processes in the pipeline are children
9153  * of the process creating the pipeline.  (This differs from some versions
9154  * of the shell, which make the last process in a pipeline the parent
9155  * of all the rest.)
9156  */
9157 static int
9158 evalpipe(union node *n, int flags)
9159 {
9160         struct job *jp;
9161         struct nodelist *lp;
9162         int pipelen;
9163         int prevfd;
9164         int pip[2];
9165         int status = 0;
9166
9167         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9168         pipelen = 0;
9169         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9170                 pipelen++;
9171         flags |= EV_EXIT;
9172         INT_OFF;
9173         if (n->npipe.pipe_backgnd == 0)
9174                 get_tty_state();
9175         jp = makejob(/*n,*/ pipelen);
9176         prevfd = -1;
9177         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9178                 prehash(lp->n);
9179                 pip[1] = -1;
9180                 if (lp->next) {
9181                         if (pipe(pip) < 0) {
9182                                 close(prevfd);
9183                                 ash_msg_and_raise_error("pipe call failed");
9184                         }
9185                 }
9186                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9187                         /* child */
9188                         INT_ON;
9189                         if (pip[1] >= 0) {
9190                                 close(pip[0]);
9191                         }
9192                         if (prevfd > 0) {
9193                                 dup2(prevfd, 0);
9194                                 close(prevfd);
9195                         }
9196                         if (pip[1] > 1) {
9197                                 dup2(pip[1], 1);
9198                                 close(pip[1]);
9199                         }
9200                         evaltreenr(lp->n, flags);
9201                         /* never returns */
9202                 }
9203                 /* parent */
9204                 if (prevfd >= 0)
9205                         close(prevfd);
9206                 prevfd = pip[0];
9207                 /* Don't want to trigger debugging */
9208                 if (pip[1] != -1)
9209                         close(pip[1]);
9210         }
9211         if (n->npipe.pipe_backgnd == 0) {
9212                 status = waitforjob(jp);
9213                 TRACE(("evalpipe:  job done exit status %d\n", status));
9214         }
9215         INT_ON;
9216
9217         return status;
9218 }
9219
9220 /*
9221  * Controls whether the shell is interactive or not.
9222  */
9223 static void
9224 setinteractive(int on)
9225 {
9226         static smallint is_interactive;
9227
9228         if (++on == is_interactive)
9229                 return;
9230         is_interactive = on;
9231         setsignal(SIGINT);
9232         setsignal(SIGQUIT);
9233         setsignal(SIGTERM);
9234 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9235         if (is_interactive > 1) {
9236                 /* Looks like they want an interactive shell */
9237                 static smallint did_banner;
9238
9239                 if (!did_banner) {
9240                         /* note: ash and hush share this string */
9241                         out1fmt("\n\n%s %s\n"
9242                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9243                                 "\n",
9244                                 bb_banner,
9245                                 "built-in shell (ash)"
9246                         );
9247                         did_banner = 1;
9248                 }
9249         }
9250 #endif
9251 }
9252
9253 static void
9254 optschanged(void)
9255 {
9256 #if DEBUG
9257         opentrace();
9258 #endif
9259         setinteractive(iflag);
9260         setjobctl(mflag);
9261 #if ENABLE_FEATURE_EDITING_VI
9262         if (viflag)
9263                 line_input_state->flags |= VI_MODE;
9264         else
9265                 line_input_state->flags &= ~VI_MODE;
9266 #else
9267         viflag = 0; /* forcibly keep the option off */
9268 #endif
9269 }
9270
9271 struct localvar_list {
9272         struct localvar_list *next;
9273         struct localvar *lv;
9274 };
9275
9276 static struct localvar_list *localvar_stack;
9277
9278 /*
9279  * Called after a function returns.
9280  * Interrupts must be off.
9281  */
9282 static void
9283 poplocalvars(int keep)
9284 {
9285         struct localvar_list *ll;
9286         struct localvar *lvp, *next;
9287         struct var *vp;
9288
9289         INT_OFF;
9290         ll = localvar_stack;
9291         localvar_stack = ll->next;
9292
9293         next = ll->lv;
9294         free(ll);
9295
9296         while ((lvp = next) != NULL) {
9297                 next = lvp->next;
9298                 vp = lvp->vp;
9299                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9300                 if (keep) {
9301                         int bits = VSTRFIXED;
9302
9303                         if (lvp->flags != VUNSET) {
9304                                 if (vp->var_text == lvp->text)
9305                                         bits |= VTEXTFIXED;
9306                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9307                                         free((char*)lvp->text);
9308                         }
9309
9310                         vp->flags &= ~bits;
9311                         vp->flags |= (lvp->flags & bits);
9312
9313                         if ((vp->flags &
9314                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9315                                 unsetvar(vp->var_text);
9316                 } else if (vp == NULL) {        /* $- saved */
9317                         memcpy(optlist, lvp->text, sizeof(optlist));
9318                         free((char*)lvp->text);
9319                         optschanged();
9320                 } else if (lvp->flags == VUNSET) {
9321                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9322                         unsetvar(vp->var_text);
9323                 } else {
9324                         if (vp->var_func)
9325                                 vp->var_func(var_end(lvp->text));
9326                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9327                                 free((char*)vp->var_text);
9328                         vp->flags = lvp->flags;
9329                         vp->var_text = lvp->text;
9330                 }
9331                 free(lvp);
9332         }
9333         INT_ON;
9334 }
9335
9336 /*
9337  * Create a new localvar environment.
9338  */
9339 static struct localvar_list *
9340 pushlocalvars(void)
9341 {
9342         struct localvar_list *ll;
9343
9344         INT_OFF;
9345         ll = ckzalloc(sizeof(*ll));
9346         /*ll->lv = NULL; - zalloc did it */
9347         ll->next = localvar_stack;
9348         localvar_stack = ll;
9349         INT_ON;
9350
9351         return ll->next;
9352 }
9353
9354 static void
9355 unwindlocalvars(struct localvar_list *stop)
9356 {
9357         while (localvar_stack != stop)
9358                 poplocalvars(0);
9359 }
9360
9361 static int
9362 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9363 {
9364         volatile struct shparam saveparam;
9365         struct jmploc *volatile savehandler;
9366         struct jmploc jmploc;
9367         int e;
9368
9369         saveparam = shellparam;
9370         savehandler = exception_handler;
9371         e = setjmp(jmploc.loc);
9372         if (e) {
9373                 goto funcdone;
9374         }
9375         INT_OFF;
9376         exception_handler = &jmploc;
9377         shellparam.malloced = 0;
9378         func->count++;
9379         funcnest++;
9380         INT_ON;
9381         shellparam.nparam = argc - 1;
9382         shellparam.p = argv + 1;
9383 #if ENABLE_ASH_GETOPTS
9384         shellparam.optind = 1;
9385         shellparam.optoff = -1;
9386 #endif
9387         pushlocalvars();
9388         evaltree(func->n.narg.next, flags & EV_TESTED);
9389         poplocalvars(0);
9390  funcdone:
9391         INT_OFF;
9392         funcnest--;
9393         freefunc(func);
9394         freeparam(&shellparam);
9395         shellparam = saveparam;
9396         exception_handler = savehandler;
9397         INT_ON;
9398         evalskip &= ~SKIPFUNC;
9399         return e;
9400 }
9401
9402 /*
9403  * Make a variable a local variable.  When a variable is made local, it's
9404  * value and flags are saved in a localvar structure.  The saved values
9405  * will be restored when the shell function returns.  We handle the name
9406  * "-" as a special case: it makes changes to "set +-options" local
9407  * (options will be restored on return from the function).
9408  */
9409 static void
9410 mklocal(char *name)
9411 {
9412         struct localvar *lvp;
9413         struct var **vpp;
9414         struct var *vp;
9415         char *eq = strchr(name, '=');
9416
9417         INT_OFF;
9418         /* Cater for duplicate "local". Examples:
9419          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9420          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9421          */
9422         lvp = localvar_stack->lv;
9423         while (lvp) {
9424                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9425                         if (eq)
9426                                 setvareq(name, 0);
9427                         /* else:
9428                          * it's a duplicate "local VAR" declaration, do nothing
9429                          */
9430                         goto ret;
9431                 }
9432                 lvp = lvp->next;
9433         }
9434
9435         lvp = ckzalloc(sizeof(*lvp));
9436         if (LONE_DASH(name)) {
9437                 char *p;
9438                 p = ckmalloc(sizeof(optlist));
9439                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9440                 vp = NULL;
9441         } else {
9442                 vpp = hashvar(name);
9443                 vp = *findvar(vpp, name);
9444                 if (vp == NULL) {
9445                         /* variable did not exist yet */
9446                         if (eq)
9447                                 vp = setvareq(name, VSTRFIXED);
9448                         else
9449                                 vp = setvar(name, NULL, VSTRFIXED);
9450                         lvp->flags = VUNSET;
9451                 } else {
9452                         lvp->text = vp->var_text;
9453                         lvp->flags = vp->flags;
9454                         /* make sure neither "struct var" nor string gets freed
9455                          * during (un)setting:
9456                          */
9457                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9458                         if (eq)
9459                                 setvareq(name, 0);
9460                         else
9461                                 /* "local VAR" unsets VAR: */
9462                                 setvar0(name, NULL);
9463                 }
9464         }
9465         lvp->vp = vp;
9466         lvp->next = localvar_stack->lv;
9467         localvar_stack->lv = lvp;
9468  ret:
9469         INT_ON;
9470 }
9471
9472 /*
9473  * The "local" command.
9474  */
9475 static int FAST_FUNC
9476 localcmd(int argc UNUSED_PARAM, char **argv)
9477 {
9478         char *name;
9479
9480         if (!localvar_stack)
9481                 ash_msg_and_raise_error("not in a function");
9482
9483         argv = argptr;
9484         while ((name = *argv++) != NULL) {
9485                 mklocal(name);
9486         }
9487         return 0;
9488 }
9489
9490 static int FAST_FUNC
9491 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9492 {
9493         return 1;
9494 }
9495
9496 static int FAST_FUNC
9497 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9498 {
9499         return 0;
9500 }
9501
9502 static int FAST_FUNC
9503 execcmd(int argc UNUSED_PARAM, char **argv)
9504 {
9505         optionarg = NULL;
9506         while (nextopt("a:") != '\0')
9507                 /* nextopt() sets optionarg to "-a ARGV0" */;
9508
9509         argv = argptr;
9510         if (argv[0]) {
9511                 char *prog;
9512
9513                 iflag = 0;              /* exit on error */
9514                 mflag = 0;
9515                 optschanged();
9516                 /* We should set up signals for "exec CMD"
9517                  * the same way as for "CMD" without "exec".
9518                  * But optschanged->setinteractive->setsignal
9519                  * still thought we are a root shell. Therefore, for example,
9520                  * SIGQUIT is still set to IGN. Fix it:
9521                  */
9522                 shlvl++;
9523                 setsignal(SIGQUIT);
9524                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9525                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9526                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9527
9528                 prog = argv[0];
9529                 if (optionarg)
9530                         argv[0] = optionarg;
9531                 shellexec(prog, argv, pathval(), 0);
9532                 /* NOTREACHED */
9533         }
9534         return 0;
9535 }
9536
9537 /*
9538  * The return command.
9539  */
9540 static int FAST_FUNC
9541 returncmd(int argc UNUSED_PARAM, char **argv)
9542 {
9543         /*
9544          * If called outside a function, do what ksh does;
9545          * skip the rest of the file.
9546          */
9547         evalskip = SKIPFUNC;
9548         return argv[1] ? number(argv[1]) : exitstatus;
9549 }
9550
9551 /* Forward declarations for builtintab[] */
9552 static int breakcmd(int, char **) FAST_FUNC;
9553 static int dotcmd(int, char **) FAST_FUNC;
9554 static int evalcmd(int, char **, int) FAST_FUNC;
9555 static int exitcmd(int, char **) FAST_FUNC;
9556 static int exportcmd(int, char **) FAST_FUNC;
9557 #if ENABLE_ASH_GETOPTS
9558 static int getoptscmd(int, char **) FAST_FUNC;
9559 #endif
9560 #if ENABLE_ASH_HELP
9561 static int helpcmd(int, char **) FAST_FUNC;
9562 #endif
9563 #if MAX_HISTORY
9564 static int historycmd(int, char **) FAST_FUNC;
9565 #endif
9566 #if ENABLE_FEATURE_SH_MATH
9567 static int letcmd(int, char **) FAST_FUNC;
9568 #endif
9569 static int readcmd(int, char **) FAST_FUNC;
9570 static int setcmd(int, char **) FAST_FUNC;
9571 static int shiftcmd(int, char **) FAST_FUNC;
9572 static int timescmd(int, char **) FAST_FUNC;
9573 static int trapcmd(int, char **) FAST_FUNC;
9574 static int umaskcmd(int, char **) FAST_FUNC;
9575 static int unsetcmd(int, char **) FAST_FUNC;
9576 static int ulimitcmd(int, char **) FAST_FUNC;
9577
9578 #define BUILTIN_NOSPEC          "0"
9579 #define BUILTIN_SPECIAL         "1"
9580 #define BUILTIN_REGULAR         "2"
9581 #define BUILTIN_SPEC_REG        "3"
9582 #define BUILTIN_ASSIGN          "4"
9583 #define BUILTIN_SPEC_ASSG       "5"
9584 #define BUILTIN_REG_ASSG        "6"
9585 #define BUILTIN_SPEC_REG_ASSG   "7"
9586
9587 /* Stubs for calling non-FAST_FUNC's */
9588 #if ENABLE_ASH_ECHO
9589 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9590 #endif
9591 #if ENABLE_ASH_PRINTF
9592 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9593 #endif
9594 #if ENABLE_ASH_TEST || BASH_TEST2
9595 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9596 #endif
9597
9598 /* Keep these in proper order since it is searched via bsearch() */
9599 static const struct builtincmd builtintab[] = {
9600         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9601         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9602 #if ENABLE_ASH_TEST
9603         { BUILTIN_REGULAR       "["       , testcmd    },
9604 #endif
9605 #if BASH_TEST2
9606         { BUILTIN_REGULAR       "[["      , testcmd    },
9607 #endif
9608 #if ENABLE_ASH_ALIAS
9609         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9610 #endif
9611 #if JOBS
9612         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9613 #endif
9614         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9615         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9616         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9617 #if ENABLE_ASH_CMDCMD
9618         { BUILTIN_REGULAR       "command" , commandcmd },
9619 #endif
9620         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9621 #if ENABLE_ASH_ECHO
9622         { BUILTIN_REGULAR       "echo"    , echocmd    },
9623 #endif
9624         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9625         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9626         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9627         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9628         { BUILTIN_REGULAR       "false"   , falsecmd   },
9629 #if JOBS
9630         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9631 #endif
9632 #if ENABLE_ASH_GETOPTS
9633         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9634 #endif
9635         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9636 #if ENABLE_ASH_HELP
9637         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9638 #endif
9639 #if MAX_HISTORY
9640         { BUILTIN_NOSPEC        "history" , historycmd },
9641 #endif
9642 #if JOBS
9643         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9644         { BUILTIN_REGULAR       "kill"    , killcmd    },
9645 #endif
9646 #if ENABLE_FEATURE_SH_MATH
9647         { BUILTIN_NOSPEC        "let"     , letcmd     },
9648 #endif
9649         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9650 #if ENABLE_ASH_PRINTF
9651         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9652 #endif
9653         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9654         { BUILTIN_REGULAR       "read"    , readcmd    },
9655         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9656         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9657         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9658         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9659 #if BASH_SOURCE
9660         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9661 #endif
9662 #if ENABLE_ASH_TEST
9663         { BUILTIN_REGULAR       "test"    , testcmd    },
9664 #endif
9665         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9666         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9667         { BUILTIN_REGULAR       "true"    , truecmd    },
9668         { BUILTIN_NOSPEC        "type"    , typecmd    },
9669         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9670         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9671 #if ENABLE_ASH_ALIAS
9672         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9673 #endif
9674         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9675         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9676 };
9677
9678 /* Should match the above table! */
9679 #define COMMANDCMD (builtintab + \
9680         /* . : */       2 + \
9681         /* [ */         1 * ENABLE_ASH_TEST + \
9682         /* [[ */        1 * BASH_TEST2 + \
9683         /* alias */     1 * ENABLE_ASH_ALIAS + \
9684         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9685         /* break cd cddir  */   3)
9686 #define EVALCMD (COMMANDCMD + \
9687         /* command */   1 * ENABLE_ASH_CMDCMD + \
9688         /* continue */  1 + \
9689         /* echo */      1 * ENABLE_ASH_ECHO + \
9690         0)
9691 #define EXECCMD (EVALCMD + \
9692         /* eval */      1)
9693
9694 /*
9695  * Search the table of builtin commands.
9696  */
9697 static int
9698 pstrcmp1(const void *a, const void *b)
9699 {
9700         return strcmp((char*)a, *(char**)b + 1);
9701 }
9702 static struct builtincmd *
9703 find_builtin(const char *name)
9704 {
9705         struct builtincmd *bp;
9706
9707         bp = bsearch(
9708                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9709                 pstrcmp1
9710         );
9711         return bp;
9712 }
9713
9714 /*
9715  * Execute a simple command.
9716  */
9717 static int
9718 isassignment(const char *p)
9719 {
9720         const char *q = endofname(p);
9721         if (p == q)
9722                 return 0;
9723         return *q == '=';
9724 }
9725 static int FAST_FUNC
9726 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9727 {
9728         /* Preserve exitstatus of a previous possible redirection
9729          * as POSIX mandates */
9730         return back_exitstatus;
9731 }
9732 static int
9733 evalcommand(union node *cmd, int flags)
9734 {
9735         static const struct builtincmd null_bltin = {
9736                 "\0\0", bltincmd /* why three NULs? */
9737         };
9738         struct localvar_list *localvar_stop;
9739         struct redirtab *redir_stop;
9740         struct stackmark smark;
9741         union node *argp;
9742         struct arglist arglist;
9743         struct arglist varlist;
9744         char **argv;
9745         int argc;
9746         const struct strlist *sp;
9747         struct cmdentry cmdentry;
9748         struct job *jp;
9749         char *lastarg;
9750         const char *path;
9751         int spclbltin;
9752         int status;
9753         char **nargv;
9754         smallint cmd_is_exec;
9755
9756         /* First expand the arguments. */
9757         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9758         setstackmark(&smark);
9759         localvar_stop = pushlocalvars();
9760         back_exitstatus = 0;
9761
9762         cmdentry.cmdtype = CMDBUILTIN;
9763         cmdentry.u.cmd = &null_bltin;
9764         varlist.lastp = &varlist.list;
9765         *varlist.lastp = NULL;
9766         arglist.lastp = &arglist.list;
9767         *arglist.lastp = NULL;
9768
9769         argc = 0;
9770         if (cmd->ncmd.args) {
9771                 struct builtincmd *bcmd;
9772                 smallint pseudovarflag;
9773
9774                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9775                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9776
9777                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9778                         struct strlist **spp;
9779
9780                         spp = arglist.lastp;
9781                         if (pseudovarflag && isassignment(argp->narg.text))
9782                                 expandarg(argp, &arglist, EXP_VARTILDE);
9783                         else
9784                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9785
9786                         for (sp = *spp; sp; sp = sp->next)
9787                                 argc++;
9788                 }
9789         }
9790
9791         /* Reserve one extra spot at the front for shellexec. */
9792         nargv = stalloc(sizeof(char *) * (argc + 2));
9793         argv = ++nargv;
9794         for (sp = arglist.list; sp; sp = sp->next) {
9795                 TRACE(("evalcommand arg: %s\n", sp->text));
9796                 *nargv++ = sp->text;
9797         }
9798         *nargv = NULL;
9799
9800         lastarg = NULL;
9801         if (iflag && funcnest == 0 && argc > 0)
9802                 lastarg = nargv[-1];
9803
9804         expredir(cmd->ncmd.redirect);
9805         redir_stop = pushredir(cmd->ncmd.redirect);
9806         preverrout_fd = 2;
9807         if (BASH_XTRACEFD && xflag) {
9808                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9809                  * we do not emulate this. We only use its value.
9810                  */
9811                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9812                 if (xtracefd && is_number(xtracefd))
9813                         preverrout_fd = atoi(xtracefd);
9814
9815         }
9816         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9817
9818         path = vpath.var_text;
9819         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9820                 struct strlist **spp;
9821                 char *p;
9822
9823                 spp = varlist.lastp;
9824                 expandarg(argp, &varlist, EXP_VARTILDE);
9825
9826                 mklocal((*spp)->text);
9827
9828                 /*
9829                  * Modify the command lookup path, if a PATH= assignment
9830                  * is present
9831                  */
9832                 p = (*spp)->text;
9833                 if (varcmp(p, path) == 0)
9834                         path = p;
9835         }
9836
9837         /* Print the command if xflag is set. */
9838         if (xflag) {
9839                 const char *pfx = "";
9840
9841                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9842
9843                 sp = varlist.list;
9844                 while (sp) {
9845                         char *varval = sp->text;
9846                         char *eq = strchrnul(varval, '=');
9847                         if (*eq)
9848                                 eq++;
9849                         fdprintf(preverrout_fd, "%s%.*s%s",
9850                                 pfx,
9851                                 (int)(eq - varval), varval,
9852                                 maybe_single_quote(eq)
9853                         );
9854                         sp = sp->next;
9855                         pfx = " ";
9856                 }
9857
9858                 sp = arglist.list;
9859                 while (sp) {
9860                         fdprintf(preverrout_fd, "%s%s",
9861                                 pfx,
9862                                 /* always quote if matches reserved word: */
9863                                 findkwd(sp->text)
9864                                 ? single_quote(sp->text)
9865                                 : maybe_single_quote(sp->text)
9866                         );
9867                         sp = sp->next;
9868                         pfx = " ";
9869                 }
9870                 safe_write(preverrout_fd, "\n", 1);
9871         }
9872
9873         cmd_is_exec = 0;
9874         spclbltin = -1;
9875
9876         /* Now locate the command. */
9877         if (argc) {
9878                 int cmd_flag = DO_ERR;
9879 #if ENABLE_ASH_CMDCMD
9880                 const char *oldpath = path + 5;
9881 #endif
9882                 path += 5;
9883                 for (;;) {
9884                         find_command(argv[0], &cmdentry, cmd_flag, path);
9885                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9886                                 flush_stdout_stderr();
9887                                 status = 127;
9888                                 goto bail;
9889                         }
9890
9891                         /* implement bltin and command here */
9892                         if (cmdentry.cmdtype != CMDBUILTIN)
9893                                 break;
9894                         if (spclbltin < 0)
9895                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9896                         if (cmdentry.u.cmd == EXECCMD)
9897                                 cmd_is_exec = 1;
9898 #if ENABLE_ASH_CMDCMD
9899                         if (cmdentry.u.cmd == COMMANDCMD) {
9900                                 path = oldpath;
9901                                 nargv = parse_command_args(argv, &path);
9902                                 if (!nargv)
9903                                         break;
9904                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9905                                  * nargv => "PROG". path is updated if -p.
9906                                  */
9907                                 argc -= nargv - argv;
9908                                 argv = nargv;
9909                                 cmd_flag |= DO_NOFUNC;
9910                         } else
9911 #endif
9912                                 break;
9913                 }
9914         }
9915
9916         if (status) {
9917  bail:
9918                 exitstatus = status;
9919
9920                 /* We have a redirection error. */
9921                 if (spclbltin > 0)
9922                         raise_exception(EXERROR);
9923
9924                 goto out;
9925         }
9926
9927         /* Execute the command. */
9928         switch (cmdentry.cmdtype) {
9929         default: {
9930
9931 #if ENABLE_FEATURE_SH_NOFORK
9932 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9933  *     around run_nofork_applet() call.
9934  * (2) Should this check also be done in forkshell()?
9935  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9936  */
9937                 /* find_command() encodes applet_no as (-2 - applet_no) */
9938                 int applet_no = (- cmdentry.u.index - 2);
9939                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9940                         listsetvar(varlist.list, VEXPORT|VSTACK);
9941                         /*
9942                          * Run <applet>_main().
9943                          * Signals (^C) can't interrupt here.
9944                          * Otherwise we can mangle stdio or malloc internal state.
9945                          * This makes applets which can run for a long time
9946                          * and/or wait for user input ineligible for NOFORK:
9947                          * for example, "yes" or "rm" (rm -i waits for input).
9948                          */
9949                         INT_OFF;
9950                         status = run_nofork_applet(applet_no, argv);
9951                         /*
9952                          * Try enabling NOFORK for "yes" applet.
9953                          * ^C _will_ stop it (write returns EINTR),
9954                          * but this causes stdout FILE to be stuck
9955                          * and needing clearerr(). What if other applets
9956                          * also can get EINTRs? Do we need to switch
9957                          * our signals to SA_RESTART?
9958                          */
9959                         /*clearerr(stdout);*/
9960                         INT_ON;
9961                         break;
9962                 }
9963 #endif
9964                 /* Can we avoid forking? For example, very last command
9965                  * in a script or a subshell does not need forking,
9966                  * we can just exec it.
9967                  */
9968                 if (!(flags & EV_EXIT) || may_have_traps) {
9969                         /* No, forking off a child is necessary */
9970                         INT_OFF;
9971                         get_tty_state();
9972                         jp = makejob(/*cmd,*/ 1);
9973                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9974                                 /* parent */
9975                                 status = waitforjob(jp);
9976                                 INT_ON;
9977                                 TRACE(("forked child exited with %d\n", status));
9978                                 break;
9979                         }
9980                         /* child */
9981                         FORCE_INT_ON;
9982                         /* fall through to exec'ing external program */
9983                 }
9984                 listsetvar(varlist.list, VEXPORT|VSTACK);
9985                 shellexec(argv[0], argv, path, cmdentry.u.index);
9986                 /* NOTREACHED */
9987         } /* default */
9988         case CMDBUILTIN:
9989                 if (spclbltin > 0 || argc == 0) {
9990                         poplocalvars(1);
9991                         if (cmd_is_exec && argc > 1)
9992                                 listsetvar(varlist.list, VEXPORT);
9993                 }
9994
9995                 /* Tight loop with builtins only:
9996                  * "while kill -0 $child; do true; done"
9997                  * will never exit even if $child died, unless we do this
9998                  * to reap the zombie and make kill detect that it's gone: */
9999                 dowait(DOWAIT_NONBLOCK, NULL);
10000
10001                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10002                         if (exception_type == EXERROR && spclbltin <= 0) {
10003                                 FORCE_INT_ON;
10004                                 goto readstatus;
10005                         }
10006  raise:
10007                         longjmp(exception_handler->loc, 1);
10008                 }
10009                 goto readstatus;
10010
10011         case CMDFUNCTION:
10012                 poplocalvars(1);
10013                 /* See above for the rationale */
10014                 dowait(DOWAIT_NONBLOCK, NULL);
10015                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10016                         goto raise;
10017  readstatus:
10018                 status = exitstatus;
10019                 break;
10020         } /* switch */
10021
10022  out:
10023         if (cmd->ncmd.redirect)
10024                 popredir(/*drop:*/ cmd_is_exec);
10025         unwindredir(redir_stop);
10026         unwindlocalvars(localvar_stop);
10027         if (lastarg) {
10028                 /* dsl: I think this is intended to be used to support
10029                  * '_' in 'vi' command mode during line editing...
10030                  * However I implemented that within libedit itself.
10031                  */
10032                 setvar0("_", lastarg);
10033         }
10034         popstackmark(&smark);
10035
10036         return status;
10037 }
10038
10039 static int
10040 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10041 {
10042         char *volatile savecmdname;
10043         struct jmploc *volatile savehandler;
10044         struct jmploc jmploc;
10045         int status;
10046         int i;
10047
10048         savecmdname = commandname;
10049         savehandler = exception_handler;
10050         i = setjmp(jmploc.loc);
10051         if (i)
10052                 goto cmddone;
10053         exception_handler = &jmploc;
10054         commandname = argv[0];
10055         argptr = argv + 1;
10056         optptr = NULL;                  /* initialize nextopt */
10057         if (cmd == EVALCMD)
10058                 status = evalcmd(argc, argv, flags);
10059         else
10060                 status = (*cmd->builtin)(argc, argv);
10061         flush_stdout_stderr();
10062         status |= ferror(stdout);
10063         exitstatus = status;
10064  cmddone:
10065         clearerr(stdout);
10066         commandname = savecmdname;
10067         exception_handler = savehandler;
10068
10069         return i;
10070 }
10071
10072 static int
10073 goodname(const char *p)
10074 {
10075         return endofname(p)[0] == '\0';
10076 }
10077
10078
10079 /*
10080  * Search for a command.  This is called before we fork so that the
10081  * location of the command will be available in the parent as well as
10082  * the child.  The check for "goodname" is an overly conservative
10083  * check that the name will not be subject to expansion.
10084  */
10085 static void
10086 prehash(union node *n)
10087 {
10088         struct cmdentry entry;
10089
10090         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10091                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10092 }
10093
10094
10095 /* ============ Builtin commands
10096  *
10097  * Builtin commands whose functions are closely tied to evaluation
10098  * are implemented here.
10099  */
10100
10101 /*
10102  * Handle break and continue commands.  Break, continue, and return are
10103  * all handled by setting the evalskip flag.  The evaluation routines
10104  * above all check this flag, and if it is set they start skipping
10105  * commands rather than executing them.  The variable skipcount is
10106  * the number of loops to break/continue, or the number of function
10107  * levels to return.  (The latter is always 1.)  It should probably
10108  * be an error to break out of more loops than exist, but it isn't
10109  * in the standard shell so we don't make it one here.
10110  */
10111 static int FAST_FUNC
10112 breakcmd(int argc UNUSED_PARAM, char **argv)
10113 {
10114         int n = argv[1] ? number(argv[1]) : 1;
10115
10116         if (n <= 0)
10117                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10118         if (n > loopnest)
10119                 n = loopnest;
10120         if (n > 0) {
10121                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10122                 skipcount = n;
10123         }
10124         return 0;
10125 }
10126
10127
10128 /*
10129  * This implements the input routines used by the parser.
10130  */
10131
10132 enum {
10133         INPUT_PUSH_FILE = 1,
10134         INPUT_NOFILE_OK = 2,
10135 };
10136
10137 static smallint checkkwd;
10138 /* values of checkkwd variable */
10139 #define CHKALIAS        0x1
10140 #define CHKKWD          0x2
10141 #define CHKNL           0x4
10142 #define CHKEOFMARK      0x8
10143
10144 /*
10145  * Push a string back onto the input at this current parsefile level.
10146  * We handle aliases this way.
10147  */
10148 #if !ENABLE_ASH_ALIAS
10149 #define pushstring(s, ap) pushstring(s)
10150 #endif
10151 static void
10152 pushstring(char *s, struct alias *ap)
10153 {
10154         struct strpush *sp;
10155         int len;
10156
10157         len = strlen(s);
10158         INT_OFF;
10159         if (g_parsefile->strpush) {
10160                 sp = ckzalloc(sizeof(*sp));
10161                 sp->prev = g_parsefile->strpush;
10162         } else {
10163                 sp = &(g_parsefile->basestrpush);
10164         }
10165         g_parsefile->strpush = sp;
10166         sp->prev_string = g_parsefile->next_to_pgetc;
10167         sp->prev_left_in_line = g_parsefile->left_in_line;
10168         sp->unget = g_parsefile->unget;
10169         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10170 #if ENABLE_ASH_ALIAS
10171         sp->ap = ap;
10172         if (ap) {
10173                 ap->flag |= ALIASINUSE;
10174                 sp->string = s;
10175         }
10176 #endif
10177         g_parsefile->next_to_pgetc = s;
10178         g_parsefile->left_in_line = len;
10179         g_parsefile->unget = 0;
10180         INT_ON;
10181 }
10182
10183 static void
10184 popstring(void)
10185 {
10186         struct strpush *sp = g_parsefile->strpush;
10187
10188         INT_OFF;
10189 #if ENABLE_ASH_ALIAS
10190         if (sp->ap) {
10191                 if (g_parsefile->next_to_pgetc[-1] == ' '
10192                  || g_parsefile->next_to_pgetc[-1] == '\t'
10193                 ) {
10194                         checkkwd |= CHKALIAS;
10195                 }
10196                 if (sp->string != sp->ap->val) {
10197                         free(sp->string);
10198                 }
10199                 sp->ap->flag &= ~ALIASINUSE;
10200                 if (sp->ap->flag & ALIASDEAD) {
10201                         unalias(sp->ap->name);
10202                 }
10203         }
10204 #endif
10205         g_parsefile->next_to_pgetc = sp->prev_string;
10206         g_parsefile->left_in_line = sp->prev_left_in_line;
10207         g_parsefile->unget = sp->unget;
10208         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10209         g_parsefile->strpush = sp->prev;
10210         if (sp != &(g_parsefile->basestrpush))
10211                 free(sp);
10212         INT_ON;
10213 }
10214
10215 static int
10216 preadfd(void)
10217 {
10218         int nr;
10219         char *buf = g_parsefile->buf;
10220
10221         g_parsefile->next_to_pgetc = buf;
10222 #if ENABLE_FEATURE_EDITING
10223  retry:
10224         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10225                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10226         else {
10227 # if ENABLE_ASH_IDLE_TIMEOUT
10228                 int timeout = -1;
10229                 if (iflag) {
10230                         const char *tmout_var = lookupvar("TMOUT");
10231                         if (tmout_var) {
10232                                 timeout = atoi(tmout_var) * 1000;
10233                                 if (timeout <= 0)
10234                                         timeout = -1;
10235                         }
10236                 }
10237                 line_input_state->timeout = timeout;
10238 # endif
10239 # if ENABLE_FEATURE_TAB_COMPLETION
10240                 line_input_state->path_lookup = pathval();
10241 # endif
10242                 reinit_unicode_for_ash();
10243                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10244                 if (nr == 0) {
10245                         /* ^C pressed, "convert" to SIGINT */
10246                         write(STDOUT_FILENO, "^C", 2);
10247                         if (trap[SIGINT]) {
10248                                 buf[0] = '\n';
10249                                 buf[1] = '\0';
10250                                 raise(SIGINT);
10251                                 return 1;
10252                         }
10253                         exitstatus = 128 + SIGINT;
10254                         bb_putchar('\n');
10255                         goto retry;
10256                 }
10257                 if (nr < 0) {
10258                         if (errno == 0) {
10259                                 /* Ctrl+D pressed */
10260                                 nr = 0;
10261                         }
10262 # if ENABLE_ASH_IDLE_TIMEOUT
10263                         else if (errno == EAGAIN && timeout > 0) {
10264                                 puts("\007timed out waiting for input: auto-logout");
10265                                 exitshell();
10266                         }
10267 # endif
10268                 }
10269         }
10270 #else
10271         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10272 #endif
10273
10274 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10275         if (nr < 0) {
10276                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10277                         int flags = fcntl(0, F_GETFL);
10278                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10279                                 flags &= ~O_NONBLOCK;
10280                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10281                                         out2str("sh: turning off NDELAY mode\n");
10282                                         goto retry;
10283                                 }
10284                         }
10285                 }
10286         }
10287 #endif
10288         return nr;
10289 }
10290
10291 /*
10292  * Refill the input buffer and return the next input character:
10293  *
10294  * 1) If a string was pushed back on the input, pop it;
10295  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10296  *    or we are reading from a string so we can't refill the buffer,
10297  *    return EOF.
10298  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10299  * 4) Process input up to the next newline, deleting nul characters.
10300  */
10301 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10302 #define pgetc_debug(...) ((void)0)
10303 static int pgetc(void);
10304 static int
10305 preadbuffer(void)
10306 {
10307         char *q;
10308         int more;
10309
10310         if (g_parsefile->strpush) {
10311 #if ENABLE_ASH_ALIAS
10312                 if (g_parsefile->left_in_line == -1
10313                  && g_parsefile->strpush->ap
10314                  && g_parsefile->next_to_pgetc[-1] != ' '
10315                  && g_parsefile->next_to_pgetc[-1] != '\t'
10316                 ) {
10317                         pgetc_debug("preadbuffer PEOA");
10318                         return PEOA;
10319                 }
10320 #endif
10321                 popstring();
10322                 return pgetc();
10323         }
10324         /* on both branches above g_parsefile->left_in_line < 0.
10325          * "pgetc" needs refilling.
10326          */
10327
10328         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10329          * pungetc() may increment it a few times.
10330          * Assuming it won't increment it to less than -90.
10331          */
10332         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10333                 pgetc_debug("preadbuffer PEOF1");
10334                 /* even in failure keep left_in_line and next_to_pgetc
10335                  * in lock step, for correct multi-layer pungetc.
10336                  * left_in_line was decremented before preadbuffer(),
10337                  * must inc next_to_pgetc: */
10338                 g_parsefile->next_to_pgetc++;
10339                 return PEOF;
10340         }
10341
10342         more = g_parsefile->left_in_buffer;
10343         if (more <= 0) {
10344                 flush_stdout_stderr();
10345  again:
10346                 more = preadfd();
10347                 if (more <= 0) {
10348                         /* don't try reading again */
10349                         g_parsefile->left_in_line = -99;
10350                         pgetc_debug("preadbuffer PEOF2");
10351                         g_parsefile->next_to_pgetc++;
10352                         return PEOF;
10353                 }
10354         }
10355
10356         /* Find out where's the end of line.
10357          * Set g_parsefile->left_in_line
10358          * and g_parsefile->left_in_buffer acordingly.
10359          * NUL chars are deleted.
10360          */
10361         q = g_parsefile->next_to_pgetc;
10362         for (;;) {
10363                 char c;
10364
10365                 more--;
10366
10367                 c = *q;
10368                 if (c == '\0') {
10369                         memmove(q, q + 1, more);
10370                 } else {
10371                         q++;
10372                         if (c == '\n') {
10373                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10374                                 break;
10375                         }
10376                 }
10377
10378                 if (more <= 0) {
10379                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10380                         if (g_parsefile->left_in_line < 0)
10381                                 goto again;
10382                         break;
10383                 }
10384         }
10385         g_parsefile->left_in_buffer = more;
10386
10387         if (vflag) {
10388                 char save = *q;
10389                 *q = '\0';
10390                 out2str(g_parsefile->next_to_pgetc);
10391                 *q = save;
10392         }
10393
10394         pgetc_debug("preadbuffer at %d:%p'%s'",
10395                         g_parsefile->left_in_line,
10396                         g_parsefile->next_to_pgetc,
10397                         g_parsefile->next_to_pgetc);
10398         return (unsigned char)*g_parsefile->next_to_pgetc++;
10399 }
10400
10401 static void
10402 nlprompt(void)
10403 {
10404         g_parsefile->linno++;
10405         setprompt_if(doprompt, 2);
10406 }
10407 static void
10408 nlnoprompt(void)
10409 {
10410         g_parsefile->linno++;
10411         needprompt = doprompt;
10412 }
10413
10414 static int
10415 pgetc(void)
10416 {
10417         int c;
10418
10419         pgetc_debug("pgetc at %d:%p'%s'",
10420                         g_parsefile->left_in_line,
10421                         g_parsefile->next_to_pgetc,
10422                         g_parsefile->next_to_pgetc);
10423         if (g_parsefile->unget)
10424                 return g_parsefile->lastc[--g_parsefile->unget];
10425
10426         if (--g_parsefile->left_in_line >= 0)
10427                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10428         else
10429                 c = preadbuffer();
10430
10431         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10432         g_parsefile->lastc[0] = c;
10433
10434         return c;
10435 }
10436
10437 #if ENABLE_ASH_ALIAS
10438 static int
10439 pgetc_without_PEOA(void)
10440 {
10441         int c;
10442         do {
10443                 pgetc_debug("pgetc at %d:%p'%s'",
10444                                 g_parsefile->left_in_line,
10445                                 g_parsefile->next_to_pgetc,
10446                                 g_parsefile->next_to_pgetc);
10447                 c = pgetc();
10448         } while (c == PEOA);
10449         return c;
10450 }
10451 #else
10452 # define pgetc_without_PEOA() pgetc()
10453 #endif
10454
10455 /*
10456  * Undo a call to pgetc.  Only two characters may be pushed back.
10457  * PEOF may be pushed back.
10458  */
10459 static void
10460 pungetc(void)
10461 {
10462         g_parsefile->unget++;
10463 }
10464
10465 /* This one eats backslash+newline */
10466 static int
10467 pgetc_eatbnl(void)
10468 {
10469         int c;
10470
10471         while ((c = pgetc()) == '\\') {
10472                 if (pgetc() != '\n') {
10473                         pungetc();
10474                         break;
10475                 }
10476
10477                 nlprompt();
10478         }
10479
10480         return c;
10481 }
10482
10483 /*
10484  * To handle the "." command, a stack of input files is used.  Pushfile
10485  * adds a new entry to the stack and popfile restores the previous level.
10486  */
10487 static void
10488 pushfile(void)
10489 {
10490         struct parsefile *pf;
10491
10492         pf = ckzalloc(sizeof(*pf));
10493         pf->prev = g_parsefile;
10494         pf->pf_fd = -1;
10495         /*pf->strpush = NULL; - ckzalloc did it */
10496         /*pf->basestrpush.prev = NULL;*/
10497         /*pf->unget = 0;*/
10498         g_parsefile = pf;
10499 }
10500
10501 static void
10502 popfile(void)
10503 {
10504         struct parsefile *pf = g_parsefile;
10505
10506         if (pf == &basepf)
10507                 return;
10508
10509         INT_OFF;
10510         if (pf->pf_fd >= 0)
10511                 close(pf->pf_fd);
10512         free(pf->buf);
10513         while (pf->strpush)
10514                 popstring();
10515         g_parsefile = pf->prev;
10516         free(pf);
10517         INT_ON;
10518 }
10519
10520 /*
10521  * Return to top level.
10522  */
10523 static void
10524 popallfiles(void)
10525 {
10526         while (g_parsefile != &basepf)
10527                 popfile();
10528 }
10529
10530 /*
10531  * Close the file(s) that the shell is reading commands from.  Called
10532  * after a fork is done.
10533  */
10534 static void
10535 closescript(void)
10536 {
10537         popallfiles();
10538         if (g_parsefile->pf_fd > 0) {
10539                 close(g_parsefile->pf_fd);
10540                 g_parsefile->pf_fd = 0;
10541         }
10542 }
10543
10544 /*
10545  * Like setinputfile, but takes an open file descriptor.  Call this with
10546  * interrupts off.
10547  */
10548 static void
10549 setinputfd(int fd, int push)
10550 {
10551         if (push) {
10552                 pushfile();
10553                 g_parsefile->buf = NULL;
10554         }
10555         g_parsefile->pf_fd = fd;
10556         if (g_parsefile->buf == NULL)
10557                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10558         g_parsefile->left_in_buffer = 0;
10559         g_parsefile->left_in_line = 0;
10560         g_parsefile->linno = 1;
10561 }
10562
10563 /*
10564  * Set the input to take input from a file.  If push is set, push the
10565  * old input onto the stack first.
10566  */
10567 static int
10568 setinputfile(const char *fname, int flags)
10569 {
10570         int fd;
10571
10572         INT_OFF;
10573         fd = open(fname, O_RDONLY);
10574         if (fd < 0) {
10575                 if (flags & INPUT_NOFILE_OK)
10576                         goto out;
10577                 exitstatus = 127;
10578                 ash_msg_and_raise_perror("can't open '%s'", fname);
10579         }
10580         if (fd < 10)
10581                 fd = savefd(fd);
10582         else
10583                 close_on_exec_on(fd);
10584         setinputfd(fd, flags & INPUT_PUSH_FILE);
10585  out:
10586         INT_ON;
10587         return fd;
10588 }
10589
10590 /*
10591  * Like setinputfile, but takes input from a string.
10592  */
10593 static void
10594 setinputstring(char *string)
10595 {
10596         INT_OFF;
10597         pushfile();
10598         g_parsefile->next_to_pgetc = string;
10599         g_parsefile->left_in_line = strlen(string);
10600         g_parsefile->buf = NULL;
10601         g_parsefile->linno = 1;
10602         INT_ON;
10603 }
10604
10605
10606 /*
10607  * Routines to check for mail.
10608  */
10609
10610 #if ENABLE_ASH_MAIL
10611
10612 /* Hash of mtimes of mailboxes */
10613 static unsigned mailtime_hash;
10614 /* Set if MAIL or MAILPATH is changed. */
10615 static smallint mail_var_path_changed;
10616
10617 /*
10618  * Print appropriate message(s) if mail has arrived.
10619  * If mail_var_path_changed is set,
10620  * then the value of MAIL has mail_var_path_changed,
10621  * so we just update the values.
10622  */
10623 static void
10624 chkmail(void)
10625 {
10626         const char *mpath;
10627         char *p;
10628         char *q;
10629         unsigned new_hash;
10630         struct stackmark smark;
10631         struct stat statb;
10632
10633         setstackmark(&smark);
10634         mpath = mpathset() ? mpathval() : mailval();
10635         new_hash = 0;
10636         for (;;) {
10637                 p = path_advance(&mpath, nullstr);
10638                 if (p == NULL)
10639                         break;
10640                 if (*p == '\0')
10641                         continue;
10642                 for (q = p; *q; q++)
10643                         continue;
10644 #if DEBUG
10645                 if (q[-1] != '/')
10646                         abort();
10647 #endif
10648                 q[-1] = '\0';                   /* delete trailing '/' */
10649                 if (stat(p, &statb) < 0) {
10650                         continue;
10651                 }
10652                 /* Very simplistic "hash": just a sum of all mtimes */
10653                 new_hash += (unsigned)statb.st_mtime;
10654         }
10655         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10656                 if (mailtime_hash != 0)
10657                         out2str("you have mail\n");
10658                 mailtime_hash = new_hash;
10659         }
10660         mail_var_path_changed = 0;
10661         popstackmark(&smark);
10662 }
10663
10664 static void FAST_FUNC
10665 changemail(const char *val UNUSED_PARAM)
10666 {
10667         mail_var_path_changed = 1;
10668 }
10669
10670 #endif /* ASH_MAIL */
10671
10672
10673 /* ============ ??? */
10674
10675 /*
10676  * Set the shell parameters.
10677  */
10678 static void
10679 setparam(char **argv)
10680 {
10681         char **newparam;
10682         char **ap;
10683         int nparam;
10684
10685         for (nparam = 0; argv[nparam]; nparam++)
10686                 continue;
10687         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10688         while (*argv) {
10689                 *ap++ = ckstrdup(*argv++);
10690         }
10691         *ap = NULL;
10692         freeparam(&shellparam);
10693         shellparam.malloced = 1;
10694         shellparam.nparam = nparam;
10695         shellparam.p = newparam;
10696 #if ENABLE_ASH_GETOPTS
10697         shellparam.optind = 1;
10698         shellparam.optoff = -1;
10699 #endif
10700 }
10701
10702 /*
10703  * Process shell options.  The global variable argptr contains a pointer
10704  * to the argument list; we advance it past the options.
10705  *
10706  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10707  * For a non-interactive shell, an error condition encountered
10708  * by a special built-in ... shall cause the shell to write a diagnostic message
10709  * to standard error and exit as shown in the following table:
10710  * Error                                           Special Built-In
10711  * ...
10712  * Utility syntax error (option or operand error)  Shall exit
10713  * ...
10714  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10715  * we see that bash does not do that (set "finishes" with error code 1 instead,
10716  * and shell continues), and people rely on this behavior!
10717  * Testcase:
10718  * set -o barfoo 2>/dev/null
10719  * echo $?
10720  *
10721  * Oh well. Let's mimic that.
10722  */
10723 static int
10724 plus_minus_o(char *name, int val)
10725 {
10726         int i;
10727
10728         if (name) {
10729                 for (i = 0; i < NOPTS; i++) {
10730                         if (strcmp(name, optnames(i)) == 0) {
10731                                 optlist[i] = val;
10732                                 return 0;
10733                         }
10734                 }
10735                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10736                 return 1;
10737         }
10738         for (i = 0; i < NOPTS; i++) {
10739                 if (val) {
10740                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10741                 } else {
10742                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10743                 }
10744         }
10745         return 0;
10746 }
10747 static void
10748 setoption(int flag, int val)
10749 {
10750         int i;
10751
10752         for (i = 0; i < NOPTS; i++) {
10753                 if (optletters(i) == flag) {
10754                         optlist[i] = val;
10755                         return;
10756                 }
10757         }
10758         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10759         /* NOTREACHED */
10760 }
10761 static int
10762 options(int cmdline, int *login_sh)
10763 {
10764         char *p;
10765         int val;
10766         int c;
10767
10768         if (cmdline)
10769                 minusc = NULL;
10770         while ((p = *argptr) != NULL) {
10771                 c = *p++;
10772                 if (c != '-' && c != '+')
10773                         break;
10774                 argptr++;
10775                 val = 0; /* val = 0 if c == '+' */
10776                 if (c == '-') {
10777                         val = 1;
10778                         if (p[0] == '\0' || LONE_DASH(p)) {
10779                                 if (!cmdline) {
10780                                         /* "-" means turn off -x and -v */
10781                                         if (p[0] == '\0')
10782                                                 xflag = vflag = 0;
10783                                         /* "--" means reset params */
10784                                         else if (*argptr == NULL)
10785                                                 setparam(argptr);
10786                                 }
10787                                 break;    /* "-" or "--" terminates options */
10788                         }
10789                 }
10790                 /* first char was + or - */
10791                 while ((c = *p++) != '\0') {
10792                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10793                         if (c == 'c' && cmdline) {
10794                                 minusc = p;     /* command is after shell args */
10795                         } else if (c == 'o') {
10796                                 if (plus_minus_o(*argptr, val)) {
10797                                         /* it already printed err message */
10798                                         return 1; /* error */
10799                                 }
10800                                 if (*argptr)
10801                                         argptr++;
10802                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10803                                 if (login_sh)
10804                                         *login_sh = 1;
10805                         /* bash does not accept +-login, we also won't */
10806                         } else if (cmdline && val && (c == '-')) { /* long options */
10807                                 if (strcmp(p, "login") == 0) {
10808                                         if (login_sh)
10809                                                 *login_sh = 1;
10810                                 }
10811                                 break;
10812                         } else {
10813                                 setoption(c, val);
10814                         }
10815                 }
10816         }
10817         return 0;
10818 }
10819
10820 /*
10821  * The shift builtin command.
10822  */
10823 static int FAST_FUNC
10824 shiftcmd(int argc UNUSED_PARAM, char **argv)
10825 {
10826         int n;
10827         char **ap1, **ap2;
10828
10829         n = 1;
10830         if (argv[1])
10831                 n = number(argv[1]);
10832         if (n > shellparam.nparam)
10833                 n = 0; /* bash compat, was = shellparam.nparam; */
10834         INT_OFF;
10835         shellparam.nparam -= n;
10836         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10837                 if (shellparam.malloced)
10838                         free(*ap1);
10839         }
10840         ap2 = shellparam.p;
10841         while ((*ap2++ = *ap1++) != NULL)
10842                 continue;
10843 #if ENABLE_ASH_GETOPTS
10844         shellparam.optind = 1;
10845         shellparam.optoff = -1;
10846 #endif
10847         INT_ON;
10848         return 0;
10849 }
10850
10851 /*
10852  * POSIX requires that 'set' (but not export or readonly) output the
10853  * variables in lexicographic order - by the locale's collating order (sigh).
10854  * Maybe we could keep them in an ordered balanced binary tree
10855  * instead of hashed lists.
10856  * For now just roll 'em through qsort for printing...
10857  */
10858 static int
10859 showvars(const char *sep_prefix, int on, int off)
10860 {
10861         const char *sep;
10862         char **ep, **epend;
10863
10864         ep = listvars(on, off, &epend);
10865         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10866
10867         sep = *sep_prefix ? " " : sep_prefix;
10868
10869         for (; ep < epend; ep++) {
10870                 const char *p;
10871                 const char *q;
10872
10873                 p = strchrnul(*ep, '=');
10874                 q = nullstr;
10875                 if (*p)
10876                         q = single_quote(++p);
10877                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10878         }
10879         return 0;
10880 }
10881
10882 /*
10883  * The set command builtin.
10884  */
10885 static int FAST_FUNC
10886 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10887 {
10888         int retval;
10889
10890         if (!argv[1])
10891                 return showvars(nullstr, 0, VUNSET);
10892
10893         INT_OFF;
10894         retval = options(/*cmdline:*/ 0, NULL);
10895         if (retval == 0) { /* if no parse error... */
10896                 optschanged();
10897                 if (*argptr != NULL) {
10898                         setparam(argptr);
10899                 }
10900         }
10901         INT_ON;
10902         return retval;
10903 }
10904
10905 #if ENABLE_ASH_RANDOM_SUPPORT
10906 static void FAST_FUNC
10907 change_random(const char *value)
10908 {
10909         uint32_t t;
10910
10911         if (value == NULL) {
10912                 /* "get", generate */
10913                 t = next_random(&random_gen);
10914                 /* set without recursion */
10915                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10916                 vrandom.flags &= ~VNOFUNC;
10917         } else {
10918                 /* set/reset */
10919                 t = strtoul(value, NULL, 10);
10920                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10921         }
10922 }
10923 #endif
10924
10925 #if ENABLE_ASH_GETOPTS
10926 static int
10927 getopts(char *optstr, char *optvar, char **optfirst)
10928 {
10929         char *p, *q;
10930         char c = '?';
10931         int done = 0;
10932         char sbuf[2];
10933         char **optnext;
10934         int ind = shellparam.optind;
10935         int off = shellparam.optoff;
10936
10937         sbuf[1] = '\0';
10938
10939         shellparam.optind = -1;
10940         optnext = optfirst + ind - 1;
10941
10942         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10943                 p = NULL;
10944         else
10945                 p = optnext[-1] + off;
10946         if (p == NULL || *p == '\0') {
10947                 /* Current word is done, advance */
10948                 p = *optnext;
10949                 if (p == NULL || *p != '-' || *++p == '\0') {
10950  atend:
10951                         unsetvar("OPTARG");
10952                         p = NULL;
10953                         done = 1;
10954                         goto out;
10955                 }
10956                 optnext++;
10957                 if (LONE_DASH(p))        /* check for "--" */
10958                         goto atend;
10959         }
10960
10961         c = *p++;
10962         for (q = optstr; *q != c;) {
10963                 if (*q == '\0') {
10964                         /* OPTERR is a bashism */
10965                         const char *cp = lookupvar("OPTERR");
10966                         if ((cp && LONE_CHAR(cp, '0'))
10967                          || (optstr[0] == ':')
10968                         ) {
10969                                 sbuf[0] = c;
10970                                 /*sbuf[1] = '\0'; - already is */
10971                                 setvar0("OPTARG", sbuf);
10972                         } else {
10973                                 fprintf(stderr, "Illegal option -%c\n", c);
10974                                 unsetvar("OPTARG");
10975                         }
10976                         c = '?';
10977                         goto out;
10978                 }
10979                 if (*++q == ':')
10980                         q++;
10981         }
10982
10983         if (*++q == ':') {
10984                 if (*p == '\0' && (p = *optnext) == NULL) {
10985                         /* OPTERR is a bashism */
10986                         const char *cp = lookupvar("OPTERR");
10987                         if ((cp && LONE_CHAR(cp, '0'))
10988                          || (optstr[0] == ':')
10989                         ) {
10990                                 sbuf[0] = c;
10991                                 /*sbuf[1] = '\0'; - already is */
10992                                 setvar0("OPTARG", sbuf);
10993                                 c = ':';
10994                         } else {
10995                                 fprintf(stderr, "No arg for -%c option\n", c);
10996                                 unsetvar("OPTARG");
10997                                 c = '?';
10998                         }
10999                         goto out;
11000                 }
11001
11002                 if (p == *optnext)
11003                         optnext++;
11004                 setvar0("OPTARG", p);
11005                 p = NULL;
11006         } else
11007                 setvar0("OPTARG", nullstr);
11008  out:
11009         ind = optnext - optfirst + 1;
11010         setvar("OPTIND", itoa(ind), VNOFUNC);
11011         sbuf[0] = c;
11012         /*sbuf[1] = '\0'; - already is */
11013         setvar0(optvar, sbuf);
11014
11015         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11016         shellparam.optind = ind;
11017
11018         return done;
11019 }
11020
11021 /*
11022  * The getopts builtin.  Shellparam.optnext points to the next argument
11023  * to be processed.  Shellparam.optptr points to the next character to
11024  * be processed in the current argument.  If shellparam.optnext is NULL,
11025  * then it's the first time getopts has been called.
11026  */
11027 static int FAST_FUNC
11028 getoptscmd(int argc, char **argv)
11029 {
11030         char **optbase;
11031
11032         if (argc < 3)
11033                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11034         if (argc == 3) {
11035                 optbase = shellparam.p;
11036                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11037                         shellparam.optind = 1;
11038                         shellparam.optoff = -1;
11039                 }
11040         } else {
11041                 optbase = &argv[3];
11042                 if ((unsigned)shellparam.optind > argc - 2) {
11043                         shellparam.optind = 1;
11044                         shellparam.optoff = -1;
11045                 }
11046         }
11047
11048         return getopts(argv[1], argv[2], optbase);
11049 }
11050 #endif /* ASH_GETOPTS */
11051
11052
11053 /* ============ Shell parser */
11054
11055 struct heredoc {
11056         struct heredoc *next;   /* next here document in list */
11057         union node *here;       /* redirection node */
11058         char *eofmark;          /* string indicating end of input */
11059         smallint striptabs;     /* if set, strip leading tabs */
11060 };
11061
11062 static smallint tokpushback;           /* last token pushed back */
11063 static smallint quoteflag;             /* set if (part of) last token was quoted */
11064 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11065 static struct heredoc *heredoclist;    /* list of here documents to read */
11066 static char *wordtext;                 /* text of last word returned by readtoken */
11067 static struct nodelist *backquotelist;
11068 static union node *redirnode;
11069 static struct heredoc *heredoc;
11070
11071 static const char *
11072 tokname(char *buf, int tok)
11073 {
11074         if (tok < TSEMI)
11075                 return tokname_array[tok];
11076         sprintf(buf, "\"%s\"", tokname_array[tok]);
11077         return buf;
11078 }
11079
11080 /* raise_error_unexpected_syntax:
11081  * Called when an unexpected token is read during the parse.  The argument
11082  * is the token that is expected, or -1 if more than one type of token can
11083  * occur at this point.
11084  */
11085 static void raise_error_unexpected_syntax(int) NORETURN;
11086 static void
11087 raise_error_unexpected_syntax(int token)
11088 {
11089         char msg[64];
11090         char buf[16];
11091         int l;
11092
11093         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11094         if (token >= 0)
11095                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11096         raise_error_syntax(msg);
11097         /* NOTREACHED */
11098 }
11099
11100 /* parsing is heavily cross-recursive, need these forward decls */
11101 static union node *andor(void);
11102 static union node *pipeline(void);
11103 static union node *parse_command(void);
11104 static void parseheredoc(void);
11105 static int peektoken(void);
11106 static int readtoken(void);
11107
11108 static union node *
11109 list(int nlflag)
11110 {
11111         union node *n1, *n2, *n3;
11112         int tok;
11113
11114         n1 = NULL;
11115         for (;;) {
11116                 switch (peektoken()) {
11117                 case TNL:
11118                         if (!(nlflag & 1))
11119                                 break;
11120                         parseheredoc();
11121                         return n1;
11122
11123                 case TEOF:
11124                         if (!n1 && (nlflag & 1))
11125                                 n1 = NODE_EOF;
11126                         parseheredoc();
11127                         return n1;
11128                 }
11129
11130                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11131                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11132                         return n1;
11133                 nlflag |= 2;
11134
11135                 n2 = andor();
11136                 tok = readtoken();
11137                 if (tok == TBACKGND) {
11138                         if (n2->type == NPIPE) {
11139                                 n2->npipe.pipe_backgnd = 1;
11140                         } else {
11141                                 if (n2->type != NREDIR) {
11142                                         n3 = stzalloc(sizeof(struct nredir));
11143                                         n3->nredir.n = n2;
11144                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11145                                         n2 = n3;
11146                                 }
11147                                 n2->type = NBACKGND;
11148                         }
11149                 }
11150                 if (n1 == NULL) {
11151                         n1 = n2;
11152                 } else {
11153                         n3 = stzalloc(sizeof(struct nbinary));
11154                         n3->type = NSEMI;
11155                         n3->nbinary.ch1 = n1;
11156                         n3->nbinary.ch2 = n2;
11157                         n1 = n3;
11158                 }
11159                 switch (tok) {
11160                 case TNL:
11161                 case TEOF:
11162                         tokpushback = 1;
11163                         /* fall through */
11164                 case TBACKGND:
11165                 case TSEMI:
11166                         break;
11167                 default:
11168                         if ((nlflag & 1))
11169                                 raise_error_unexpected_syntax(-1);
11170                         tokpushback = 1;
11171                         return n1;
11172                 }
11173         }
11174 }
11175
11176 static union node *
11177 andor(void)
11178 {
11179         union node *n1, *n2, *n3;
11180         int t;
11181
11182         n1 = pipeline();
11183         for (;;) {
11184                 t = readtoken();
11185                 if (t == TAND) {
11186                         t = NAND;
11187                 } else if (t == TOR) {
11188                         t = NOR;
11189                 } else {
11190                         tokpushback = 1;
11191                         return n1;
11192                 }
11193                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11194                 n2 = pipeline();
11195                 n3 = stzalloc(sizeof(struct nbinary));
11196                 n3->type = t;
11197                 n3->nbinary.ch1 = n1;
11198                 n3->nbinary.ch2 = n2;
11199                 n1 = n3;
11200         }
11201 }
11202
11203 static union node *
11204 pipeline(void)
11205 {
11206         union node *n1, *n2, *pipenode;
11207         struct nodelist *lp, *prev;
11208         int negate;
11209
11210         negate = 0;
11211         TRACE(("pipeline: entered\n"));
11212         if (readtoken() == TNOT) {
11213                 negate = !negate;
11214                 checkkwd = CHKKWD | CHKALIAS;
11215         } else
11216                 tokpushback = 1;
11217         n1 = parse_command();
11218         if (readtoken() == TPIPE) {
11219                 pipenode = stzalloc(sizeof(struct npipe));
11220                 pipenode->type = NPIPE;
11221                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11222                 lp = stzalloc(sizeof(struct nodelist));
11223                 pipenode->npipe.cmdlist = lp;
11224                 lp->n = n1;
11225                 do {
11226                         prev = lp;
11227                         lp = stzalloc(sizeof(struct nodelist));
11228                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11229                         lp->n = parse_command();
11230                         prev->next = lp;
11231                 } while (readtoken() == TPIPE);
11232                 lp->next = NULL;
11233                 n1 = pipenode;
11234         }
11235         tokpushback = 1;
11236         if (negate) {
11237                 n2 = stzalloc(sizeof(struct nnot));
11238                 n2->type = NNOT;
11239                 n2->nnot.com = n1;
11240                 return n2;
11241         }
11242         return n1;
11243 }
11244
11245 static union node *
11246 makename(void)
11247 {
11248         union node *n;
11249
11250         n = stzalloc(sizeof(struct narg));
11251         n->type = NARG;
11252         /*n->narg.next = NULL; - stzalloc did it */
11253         n->narg.text = wordtext;
11254         n->narg.backquote = backquotelist;
11255         return n;
11256 }
11257
11258 static void
11259 fixredir(union node *n, const char *text, int err)
11260 {
11261         int fd;
11262
11263         TRACE(("Fix redir %s %d\n", text, err));
11264         if (!err)
11265                 n->ndup.vname = NULL;
11266
11267         fd = bb_strtou(text, NULL, 10);
11268         if (!errno && fd >= 0)
11269                 n->ndup.dupfd = fd;
11270         else if (LONE_DASH(text))
11271                 n->ndup.dupfd = -1;
11272         else {
11273                 if (err)
11274                         raise_error_syntax("bad fd number");
11275                 n->ndup.vname = makename();
11276         }
11277 }
11278
11279 static void
11280 parsefname(void)
11281 {
11282         union node *n = redirnode;
11283
11284         if (n->type == NHERE)
11285                 checkkwd = CHKEOFMARK;
11286         if (readtoken() != TWORD)
11287                 raise_error_unexpected_syntax(-1);
11288         if (n->type == NHERE) {
11289                 struct heredoc *here = heredoc;
11290                 struct heredoc *p;
11291
11292                 if (quoteflag == 0)
11293                         n->type = NXHERE;
11294                 TRACE(("Here document %d\n", n->type));
11295                 rmescapes(wordtext, 0);
11296                 here->eofmark = wordtext;
11297                 here->next = NULL;
11298                 if (heredoclist == NULL)
11299                         heredoclist = here;
11300                 else {
11301                         for (p = heredoclist; p->next; p = p->next)
11302                                 continue;
11303                         p->next = here;
11304                 }
11305         } else if (n->type == NTOFD || n->type == NFROMFD) {
11306                 fixredir(n, wordtext, 0);
11307         } else {
11308                 n->nfile.fname = makename();
11309         }
11310 }
11311
11312 static union node *
11313 simplecmd(void)
11314 {
11315         union node *args, **app;
11316         union node *n = NULL;
11317         union node *vars, **vpp;
11318         union node **rpp, *redir;
11319         int savecheckkwd;
11320 #if BASH_TEST2
11321         smallint double_brackets_flag = 0;
11322 #endif
11323         IF_BASH_FUNCTION(smallint function_flag = 0;)
11324
11325         args = NULL;
11326         app = &args;
11327         vars = NULL;
11328         vpp = &vars;
11329         redir = NULL;
11330         rpp = &redir;
11331
11332         savecheckkwd = CHKALIAS;
11333         for (;;) {
11334                 int t;
11335                 checkkwd = savecheckkwd;
11336                 t = readtoken();
11337                 switch (t) {
11338 #if BASH_FUNCTION
11339                 case TFUNCTION:
11340                         if (peektoken() != TWORD)
11341                                 raise_error_unexpected_syntax(TWORD);
11342                         function_flag = 1;
11343                         break;
11344 #endif
11345 #if BASH_TEST2
11346                 case TAND: /* "&&" */
11347                 case TOR: /* "||" */
11348                         if (!double_brackets_flag) {
11349                                 tokpushback = 1;
11350                                 goto out;
11351                         }
11352                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11353 #endif
11354                 case TWORD:
11355                         n = stzalloc(sizeof(struct narg));
11356                         n->type = NARG;
11357                         /*n->narg.next = NULL; - stzalloc did it */
11358                         n->narg.text = wordtext;
11359 #if BASH_TEST2
11360                         if (strcmp("[[", wordtext) == 0)
11361                                 double_brackets_flag = 1;
11362                         else if (strcmp("]]", wordtext) == 0)
11363                                 double_brackets_flag = 0;
11364 #endif
11365                         n->narg.backquote = backquotelist;
11366                         if (savecheckkwd && isassignment(wordtext)) {
11367                                 *vpp = n;
11368                                 vpp = &n->narg.next;
11369                         } else {
11370                                 *app = n;
11371                                 app = &n->narg.next;
11372                                 savecheckkwd = 0;
11373                         }
11374 #if BASH_FUNCTION
11375                         if (function_flag) {
11376                                 checkkwd = CHKNL | CHKKWD;
11377                                 switch (peektoken()) {
11378                                 case TBEGIN:
11379                                 case TIF:
11380                                 case TCASE:
11381                                 case TUNTIL:
11382                                 case TWHILE:
11383                                 case TFOR:
11384                                         goto do_func;
11385                                 case TLP:
11386                                         function_flag = 0;
11387                                         break;
11388                                 case TWORD:
11389                                         if (strcmp("[[", wordtext) == 0)
11390                                                 goto do_func;
11391                                         /* fall through */
11392                                 default:
11393                                         raise_error_unexpected_syntax(-1);
11394                                 }
11395                         }
11396 #endif
11397                         break;
11398                 case TREDIR:
11399                         *rpp = n = redirnode;
11400                         rpp = &n->nfile.next;
11401                         parsefname();   /* read name of redirection file */
11402                         break;
11403                 case TLP:
11404  IF_BASH_FUNCTION(do_func:)
11405                         if (args && app == &args->narg.next
11406                          && !vars && !redir
11407                         ) {
11408                                 struct builtincmd *bcmd;
11409                                 const char *name;
11410
11411                                 /* We have a function */
11412                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11413                                         raise_error_unexpected_syntax(TRP);
11414                                 name = n->narg.text;
11415                                 if (!goodname(name)
11416                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11417                                 ) {
11418                                         raise_error_syntax("bad function name");
11419                                 }
11420                                 n->type = NDEFUN;
11421                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11422                                 n->narg.next = parse_command();
11423                                 return n;
11424                         }
11425                         IF_BASH_FUNCTION(function_flag = 0;)
11426                         /* fall through */
11427                 default:
11428                         tokpushback = 1;
11429                         goto out;
11430                 }
11431         }
11432  out:
11433         *app = NULL;
11434         *vpp = NULL;
11435         *rpp = NULL;
11436         n = stzalloc(sizeof(struct ncmd));
11437         n->type = NCMD;
11438         n->ncmd.args = args;
11439         n->ncmd.assign = vars;
11440         n->ncmd.redirect = redir;
11441         return n;
11442 }
11443
11444 static union node *
11445 parse_command(void)
11446 {
11447         union node *n1, *n2;
11448         union node *ap, **app;
11449         union node *cp, **cpp;
11450         union node *redir, **rpp;
11451         union node **rpp2;
11452         int t;
11453
11454         redir = NULL;
11455         rpp2 = &redir;
11456
11457         switch (readtoken()) {
11458         default:
11459                 raise_error_unexpected_syntax(-1);
11460                 /* NOTREACHED */
11461         case TIF:
11462                 n1 = stzalloc(sizeof(struct nif));
11463                 n1->type = NIF;
11464                 n1->nif.test = list(0);
11465                 if (readtoken() != TTHEN)
11466                         raise_error_unexpected_syntax(TTHEN);
11467                 n1->nif.ifpart = list(0);
11468                 n2 = n1;
11469                 while (readtoken() == TELIF) {
11470                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11471                         n2 = n2->nif.elsepart;
11472                         n2->type = NIF;
11473                         n2->nif.test = list(0);
11474                         if (readtoken() != TTHEN)
11475                                 raise_error_unexpected_syntax(TTHEN);
11476                         n2->nif.ifpart = list(0);
11477                 }
11478                 if (lasttoken == TELSE)
11479                         n2->nif.elsepart = list(0);
11480                 else {
11481                         n2->nif.elsepart = NULL;
11482                         tokpushback = 1;
11483                 }
11484                 t = TFI;
11485                 break;
11486         case TWHILE:
11487         case TUNTIL: {
11488                 int got;
11489                 n1 = stzalloc(sizeof(struct nbinary));
11490                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11491                 n1->nbinary.ch1 = list(0);
11492                 got = readtoken();
11493                 if (got != TDO) {
11494                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11495                                         got == TWORD ? wordtext : ""));
11496                         raise_error_unexpected_syntax(TDO);
11497                 }
11498                 n1->nbinary.ch2 = list(0);
11499                 t = TDONE;
11500                 break;
11501         }
11502         case TFOR:
11503                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11504                         raise_error_syntax("bad for loop variable");
11505                 n1 = stzalloc(sizeof(struct nfor));
11506                 n1->type = NFOR;
11507                 n1->nfor.var = wordtext;
11508                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11509                 if (readtoken() == TIN) {
11510                         app = &ap;
11511                         while (readtoken() == TWORD) {
11512                                 n2 = stzalloc(sizeof(struct narg));
11513                                 n2->type = NARG;
11514                                 /*n2->narg.next = NULL; - stzalloc did it */
11515                                 n2->narg.text = wordtext;
11516                                 n2->narg.backquote = backquotelist;
11517                                 *app = n2;
11518                                 app = &n2->narg.next;
11519                         }
11520                         *app = NULL;
11521                         n1->nfor.args = ap;
11522                         if (lasttoken != TNL && lasttoken != TSEMI)
11523                                 raise_error_unexpected_syntax(-1);
11524                 } else {
11525                         n2 = stzalloc(sizeof(struct narg));
11526                         n2->type = NARG;
11527                         /*n2->narg.next = NULL; - stzalloc did it */
11528                         n2->narg.text = (char *)dolatstr;
11529                         /*n2->narg.backquote = NULL;*/
11530                         n1->nfor.args = n2;
11531                         /*
11532                          * Newline or semicolon here is optional (but note
11533                          * that the original Bourne shell only allowed NL).
11534                          */
11535                         if (lasttoken != TSEMI)
11536                                 tokpushback = 1;
11537                 }
11538                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11539                 if (readtoken() != TDO)
11540                         raise_error_unexpected_syntax(TDO);
11541                 n1->nfor.body = list(0);
11542                 t = TDONE;
11543                 break;
11544         case TCASE:
11545                 n1 = stzalloc(sizeof(struct ncase));
11546                 n1->type = NCASE;
11547                 if (readtoken() != TWORD)
11548                         raise_error_unexpected_syntax(TWORD);
11549                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11550                 n2->type = NARG;
11551                 /*n2->narg.next = NULL; - stzalloc did it */
11552                 n2->narg.text = wordtext;
11553                 n2->narg.backquote = backquotelist;
11554                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11555                 if (readtoken() != TIN)
11556                         raise_error_unexpected_syntax(TIN);
11557                 cpp = &n1->ncase.cases;
11558  next_case:
11559                 checkkwd = CHKNL | CHKKWD;
11560                 t = readtoken();
11561                 while (t != TESAC) {
11562                         if (lasttoken == TLP)
11563                                 readtoken();
11564                         *cpp = cp = stzalloc(sizeof(struct nclist));
11565                         cp->type = NCLIST;
11566                         app = &cp->nclist.pattern;
11567                         for (;;) {
11568                                 *app = ap = stzalloc(sizeof(struct narg));
11569                                 ap->type = NARG;
11570                                 /*ap->narg.next = NULL; - stzalloc did it */
11571                                 ap->narg.text = wordtext;
11572                                 ap->narg.backquote = backquotelist;
11573                                 if (readtoken() != TPIPE)
11574                                         break;
11575                                 app = &ap->narg.next;
11576                                 readtoken();
11577                         }
11578                         //ap->narg.next = NULL;
11579                         if (lasttoken != TRP)
11580                                 raise_error_unexpected_syntax(TRP);
11581                         cp->nclist.body = list(2);
11582
11583                         cpp = &cp->nclist.next;
11584
11585                         checkkwd = CHKNL | CHKKWD;
11586                         t = readtoken();
11587                         if (t != TESAC) {
11588                                 if (t != TENDCASE)
11589                                         raise_error_unexpected_syntax(TENDCASE);
11590                                 goto next_case;
11591                         }
11592                 }
11593                 *cpp = NULL;
11594                 goto redir;
11595         case TLP:
11596                 n1 = stzalloc(sizeof(struct nredir));
11597                 n1->type = NSUBSHELL;
11598                 n1->nredir.n = list(0);
11599                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11600                 t = TRP;
11601                 break;
11602         case TBEGIN:
11603                 n1 = list(0);
11604                 t = TEND;
11605                 break;
11606         IF_BASH_FUNCTION(case TFUNCTION:)
11607         case TWORD:
11608         case TREDIR:
11609                 tokpushback = 1;
11610                 return simplecmd();
11611         }
11612
11613         if (readtoken() != t)
11614                 raise_error_unexpected_syntax(t);
11615
11616  redir:
11617         /* Now check for redirection which may follow command */
11618         checkkwd = CHKKWD | CHKALIAS;
11619         rpp = rpp2;
11620         while (readtoken() == TREDIR) {
11621                 *rpp = n2 = redirnode;
11622                 rpp = &n2->nfile.next;
11623                 parsefname();
11624         }
11625         tokpushback = 1;
11626         *rpp = NULL;
11627         if (redir) {
11628                 if (n1->type != NSUBSHELL) {
11629                         n2 = stzalloc(sizeof(struct nredir));
11630                         n2->type = NREDIR;
11631                         n2->nredir.n = n1;
11632                         n1 = n2;
11633                 }
11634                 n1->nredir.redirect = redir;
11635         }
11636         return n1;
11637 }
11638
11639 #if BASH_DOLLAR_SQUOTE
11640 static int
11641 decode_dollar_squote(void)
11642 {
11643         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11644         int c, cnt;
11645         char *p;
11646         char buf[4];
11647
11648         c = pgetc();
11649         p = strchr(C_escapes, c);
11650         if (p) {
11651                 buf[0] = c;
11652                 p = buf;
11653                 cnt = 3;
11654                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11655                         do {
11656                                 c = pgetc();
11657                                 *++p = c;
11658                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11659                         pungetc();
11660                 } else if (c == 'x') { /* \xHH */
11661                         do {
11662                                 c = pgetc();
11663                                 *++p = c;
11664                         } while (isxdigit(c) && --cnt);
11665                         pungetc();
11666                         if (cnt == 3) { /* \x but next char is "bad" */
11667                                 c = 'x';
11668                                 goto unrecognized;
11669                         }
11670                 } else { /* simple seq like \\ or \t */
11671                         p++;
11672                 }
11673                 *p = '\0';
11674                 p = buf;
11675                 c = bb_process_escape_sequence((void*)&p);
11676         } else { /* unrecognized "\z": print both chars unless ' or " */
11677                 if (c != '\'' && c != '"') {
11678  unrecognized:
11679                         c |= 0x100; /* "please encode \, then me" */
11680                 }
11681         }
11682         return c;
11683 }
11684 #endif
11685
11686 /* Used by expandstr to get here-doc like behaviour. */
11687 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11688
11689 static ALWAYS_INLINE int
11690 realeofmark(const char *eofmark)
11691 {
11692         return eofmark && eofmark != FAKEEOFMARK;
11693 }
11694
11695 /*
11696  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11697  * is not NULL, read a here document.  In the latter case, eofmark is the
11698  * word which marks the end of the document and striptabs is true if
11699  * leading tabs should be stripped from the document.  The argument c
11700  * is the first character of the input token or document.
11701  *
11702  * Because C does not have internal subroutines, I have simulated them
11703  * using goto's to implement the subroutine linkage.  The following macros
11704  * will run code that appears at the end of readtoken1.
11705  */
11706 #define CHECKEND()      {goto checkend; checkend_return:;}
11707 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11708 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11709 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11710 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11711 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11712 static int
11713 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11714 {
11715         /* NB: syntax parameter fits into smallint */
11716         /* c parameter is an unsigned char or PEOF or PEOA */
11717         char *out;
11718         size_t len;
11719         struct nodelist *bqlist;
11720         smallint quotef;
11721         smallint dblquote;
11722         smallint oldstyle;
11723         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11724         smallint pssyntax;   /* we are expanding a prompt string */
11725         int varnest;         /* levels of variables expansion */
11726         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11727         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11728         int dqvarnest;       /* levels of variables expansion within double quotes */
11729
11730         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11731
11732         startlinno = g_parsefile->linno;
11733         bqlist = NULL;
11734         quotef = 0;
11735         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11736 #if ENABLE_ASH_EXPAND_PRMT
11737         pssyntax = (syntax == PSSYNTAX);
11738         if (pssyntax)
11739                 syntax = DQSYNTAX;
11740 #else
11741         pssyntax = 0; /* constant */
11742 #endif
11743         dblquote = (syntax == DQSYNTAX);
11744         varnest = 0;
11745         IF_FEATURE_SH_MATH(arinest = 0;)
11746         IF_FEATURE_SH_MATH(parenlevel = 0;)
11747         dqvarnest = 0;
11748
11749         STARTSTACKSTR(out);
11750  loop:
11751         /* For each line, until end of word */
11752         CHECKEND();     /* set c to PEOF if at end of here document */
11753         for (;;) {      /* until end of line or end of word */
11754                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11755                 switch (SIT(c, syntax)) {
11756                 case CNL:       /* '\n' */
11757                         if (syntax == BASESYNTAX)
11758                                 goto endword;   /* exit outer loop */
11759                         USTPUTC(c, out);
11760                         nlprompt();
11761                         c = pgetc();
11762                         goto loop;              /* continue outer loop */
11763                 case CWORD:
11764                         USTPUTC(c, out);
11765                         break;
11766                 case CCTL:
11767 #if BASH_DOLLAR_SQUOTE
11768                         if (c == '\\' && bash_dollar_squote) {
11769                                 c = decode_dollar_squote();
11770                                 if (c == '\0') {
11771                                         /* skip $'\000', $'\x00' (like bash) */
11772                                         break;
11773                                 }
11774                                 if (c & 0x100) {
11775                                         /* Unknown escape. Encode as '\z' */
11776                                         c = (unsigned char)c;
11777                                         if (eofmark == NULL || dblquote)
11778                                                 USTPUTC(CTLESC, out);
11779                                         USTPUTC('\\', out);
11780                                 }
11781                         }
11782 #endif
11783                         if (eofmark == NULL || dblquote)
11784                                 USTPUTC(CTLESC, out);
11785                         USTPUTC(c, out);
11786                         break;
11787                 case CBACK:     /* backslash */
11788                         c = pgetc_without_PEOA();
11789                         if (c == PEOF) {
11790                                 USTPUTC(CTLESC, out);
11791                                 USTPUTC('\\', out);
11792                                 pungetc();
11793                         } else if (c == '\n') {
11794                                 nlprompt();
11795                         } else {
11796                                 if (pssyntax && c == '$') {
11797                                         USTPUTC(CTLESC, out);
11798                                         USTPUTC('\\', out);
11799                                 }
11800                                 /* Backslash is retained if we are in "str" and next char isn't special */
11801                                 if (dblquote
11802                                  && c != '\\'
11803                                  && c != '`'
11804                                  && c != '$'
11805                                  && (c != '"' || eofmark != NULL)
11806                                 ) {
11807                                         USTPUTC('\\', out);
11808                                 }
11809                                 USTPUTC(CTLESC, out);
11810                                 USTPUTC(c, out);
11811                                 quotef = 1;
11812                         }
11813                         break;
11814                 case CSQUOTE:
11815                         syntax = SQSYNTAX;
11816  quotemark:
11817                         if (eofmark == NULL) {
11818                                 USTPUTC(CTLQUOTEMARK, out);
11819                         }
11820                         break;
11821                 case CDQUOTE:
11822                         syntax = DQSYNTAX;
11823                         dblquote = 1;
11824                         goto quotemark;
11825                 case CENDQUOTE:
11826                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11827                         if (eofmark != NULL && varnest == 0) {
11828                                 USTPUTC(c, out);
11829                         } else {
11830                                 if (dqvarnest == 0) {
11831                                         syntax = BASESYNTAX;
11832                                         dblquote = 0;
11833                                 }
11834                                 quotef = 1;
11835                                 goto quotemark;
11836                         }
11837                         break;
11838                 case CVAR:      /* '$' */
11839                         PARSESUB();             /* parse substitution */
11840                         break;
11841                 case CENDVAR:   /* '}' */
11842                         if (varnest > 0) {
11843                                 varnest--;
11844                                 if (dqvarnest > 0) {
11845                                         dqvarnest--;
11846                                 }
11847                                 c = CTLENDVAR;
11848                         }
11849                         USTPUTC(c, out);
11850                         break;
11851 #if ENABLE_FEATURE_SH_MATH
11852                 case CLP:       /* '(' in arithmetic */
11853                         parenlevel++;
11854                         USTPUTC(c, out);
11855                         break;
11856                 case CRP:       /* ')' in arithmetic */
11857                         if (parenlevel > 0) {
11858                                 parenlevel--;
11859                         } else {
11860                                 if (pgetc_eatbnl() == ')') {
11861                                         c = CTLENDARI;
11862                                         if (--arinest == 0) {
11863                                                 syntax = prevsyntax;
11864                                         }
11865                                 } else {
11866                                         /*
11867                                          * unbalanced parens
11868                                          * (don't 2nd guess - no error)
11869                                          */
11870                                         pungetc();
11871                                 }
11872                         }
11873                         USTPUTC(c, out);
11874                         break;
11875 #endif
11876                 case CBQUOTE:   /* '`' */
11877                         PARSEBACKQOLD();
11878                         break;
11879                 case CENDFILE:
11880                         goto endword;           /* exit outer loop */
11881                 case CIGN:
11882                         break;
11883                 default:
11884                         if (varnest == 0) {
11885 #if BASH_REDIR_OUTPUT
11886                                 if (c == '&') {
11887 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11888                                         if (pgetc() == '>')
11889                                                 c = 0x100 + '>'; /* flag &> */
11890                                         pungetc();
11891                                 }
11892 #endif
11893                                 goto endword;   /* exit outer loop */
11894                         }
11895                         IF_ASH_ALIAS(if (c != PEOA))
11896                                 USTPUTC(c, out);
11897                 }
11898                 c = pgetc();
11899         } /* for (;;) */
11900  endword:
11901
11902 #if ENABLE_FEATURE_SH_MATH
11903         if (syntax == ARISYNTAX)
11904                 raise_error_syntax("missing '))'");
11905 #endif
11906         if (syntax != BASESYNTAX && eofmark == NULL)
11907                 raise_error_syntax("unterminated quoted string");
11908         if (varnest != 0) {
11909                 startlinno = g_parsefile->linno;
11910                 /* { */
11911                 raise_error_syntax("missing '}'");
11912         }
11913         USTPUTC('\0', out);
11914         len = out - (char *)stackblock();
11915         out = stackblock();
11916         if (eofmark == NULL) {
11917                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11918                  && quotef == 0
11919                 ) {
11920                         if (isdigit_str9(out)) {
11921                                 PARSEREDIR(); /* passed as params: out, c */
11922                                 lasttoken = TREDIR;
11923                                 return lasttoken;
11924                         }
11925                         /* else: non-number X seen, interpret it
11926                          * as "NNNX>file" = "NNNX >file" */
11927                 }
11928                 pungetc();
11929         }
11930         quoteflag = quotef;
11931         backquotelist = bqlist;
11932         grabstackblock(len);
11933         wordtext = out;
11934         lasttoken = TWORD;
11935         return lasttoken;
11936 /* end of readtoken routine */
11937
11938 /*
11939  * Check to see whether we are at the end of the here document.  When this
11940  * is called, c is set to the first character of the next input line.  If
11941  * we are at the end of the here document, this routine sets the c to PEOF.
11942  */
11943 checkend: {
11944         if (realeofmark(eofmark)) {
11945                 int markloc;
11946                 char *p;
11947
11948 #if ENABLE_ASH_ALIAS
11949                 if (c == PEOA)
11950                         c = pgetc_without_PEOA();
11951 #endif
11952                 if (striptabs) {
11953                         while (c == '\t') {
11954                                 c = pgetc_without_PEOA();
11955                         }
11956                 }
11957
11958                 markloc = out - (char *)stackblock();
11959                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11960                         if (c != *p)
11961                                 goto more_heredoc;
11962
11963                         c = pgetc_without_PEOA();
11964                 }
11965
11966                 if (c == '\n' || c == PEOF) {
11967                         c = PEOF;
11968                         g_parsefile->linno++;
11969                         needprompt = doprompt;
11970                 } else {
11971                         int len_here;
11972
11973  more_heredoc:
11974                         p = (char *)stackblock() + markloc + 1;
11975                         len_here = out - p;
11976
11977                         if (len_here) {
11978                                 len_here -= (c >= PEOF);
11979                                 c = p[-1];
11980
11981                                 if (len_here) {
11982                                         char *str;
11983
11984                                         str = alloca(len_here + 1);
11985                                         *(char *)mempcpy(str, p, len_here) = '\0';
11986
11987                                         pushstring(str, NULL);
11988                                 }
11989                         }
11990                 }
11991
11992                 STADJUST((char *)stackblock() + markloc - out, out);
11993         }
11994         goto checkend_return;
11995 }
11996
11997 /*
11998  * Parse a redirection operator.  The variable "out" points to a string
11999  * specifying the fd to be redirected.  The variable "c" contains the
12000  * first character of the redirection operator.
12001  */
12002 parseredir: {
12003         /* out is already checked to be a valid number or "" */
12004         int fd = (*out == '\0' ? -1 : atoi(out));
12005         union node *np;
12006
12007         np = stzalloc(sizeof(struct nfile));
12008         if (c == '>') {
12009                 np->nfile.fd = 1;
12010                 c = pgetc();
12011                 if (c == '>')
12012                         np->type = NAPPEND;
12013                 else if (c == '|')
12014                         np->type = NCLOBBER;
12015                 else if (c == '&')
12016                         np->type = NTOFD;
12017                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12018                 else {
12019                         np->type = NTO;
12020                         pungetc();
12021                 }
12022         }
12023 #if BASH_REDIR_OUTPUT
12024         else if (c == 0x100 + '>') { /* this flags &> redirection */
12025                 np->nfile.fd = 1;
12026                 pgetc(); /* this is '>', no need to check */
12027                 np->type = NTO2;
12028         }
12029 #endif
12030         else { /* c == '<' */
12031                 /*np->nfile.fd = 0; - stzalloc did it */
12032                 c = pgetc();
12033                 switch (c) {
12034                 case '<':
12035                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12036                                 np = stzalloc(sizeof(struct nhere));
12037                                 /*np->nfile.fd = 0; - stzalloc did it */
12038                         }
12039                         np->type = NHERE;
12040                         heredoc = stzalloc(sizeof(struct heredoc));
12041                         heredoc->here = np;
12042                         c = pgetc();
12043                         if (c == '-') {
12044                                 heredoc->striptabs = 1;
12045                         } else {
12046                                 /*heredoc->striptabs = 0; - stzalloc did it */
12047                                 pungetc();
12048                         }
12049                         break;
12050
12051                 case '&':
12052                         np->type = NFROMFD;
12053                         break;
12054
12055                 case '>':
12056                         np->type = NFROMTO;
12057                         break;
12058
12059                 default:
12060                         np->type = NFROM;
12061                         pungetc();
12062                         break;
12063                 }
12064         }
12065         if (fd >= 0)
12066                 np->nfile.fd = fd;
12067         redirnode = np;
12068         goto parseredir_return;
12069 }
12070
12071 /*
12072  * Parse a substitution.  At this point, we have read the dollar sign
12073  * and nothing else.
12074  */
12075
12076 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12077  * (assuming ascii char codes, as the original implementation did) */
12078 #define is_special(c) \
12079         (((unsigned)(c) - 33 < 32) \
12080                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12081 parsesub: {
12082         unsigned char subtype;
12083         int typeloc;
12084
12085         c = pgetc_eatbnl();
12086         if ((checkkwd & CHKEOFMARK)
12087          || c > 255 /* PEOA or PEOF */
12088          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12089         ) {
12090 #if BASH_DOLLAR_SQUOTE
12091                 if (syntax != DQSYNTAX && c == '\'')
12092                         bash_dollar_squote = 1;
12093                 else
12094 #endif
12095                         USTPUTC('$', out);
12096                 pungetc();
12097         } else if (c == '(') {
12098                 /* $(command) or $((arith)) */
12099                 if (pgetc_eatbnl() == '(') {
12100 #if ENABLE_FEATURE_SH_MATH
12101                         PARSEARITH();
12102 #else
12103                         raise_error_syntax("support for $((arith)) is disabled");
12104 #endif
12105                 } else {
12106                         pungetc();
12107                         PARSEBACKQNEW();
12108                 }
12109         } else {
12110                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12111                 USTPUTC(CTLVAR, out);
12112                 typeloc = out - (char *)stackblock();
12113                 STADJUST(1, out);
12114                 subtype = VSNORMAL;
12115                 if (c == '{') {
12116                         c = pgetc_eatbnl();
12117                         subtype = 0;
12118                 }
12119  varname:
12120                 if (is_name(c)) {
12121                         /* $[{[#]]NAME[}] */
12122                         do {
12123                                 STPUTC(c, out);
12124                                 c = pgetc_eatbnl();
12125                         } while (is_in_name(c));
12126                 } else if (isdigit(c)) {
12127                         /* $[{[#]]NUM[}] */
12128                         do {
12129                                 STPUTC(c, out);
12130                                 c = pgetc_eatbnl();
12131                         } while (isdigit(c));
12132                 } else {
12133                         /* $[{[#]]<specialchar>[}] */
12134                         int cc = c;
12135
12136                         c = pgetc_eatbnl();
12137                         if (!subtype && cc == '#') {
12138                                 subtype = VSLENGTH;
12139                                 if (c == '_' || isalnum(c))
12140                                         goto varname;
12141                                 cc = c;
12142                                 c = pgetc_eatbnl();
12143                                 if (cc == '}' || c != '}') {
12144                                         pungetc();
12145                                         subtype = 0;
12146                                         c = cc;
12147                                         cc = '#';
12148                                 }
12149                         }
12150
12151                         if (!is_special(cc)) {
12152                                 if (subtype == VSLENGTH)
12153                                         subtype = 0;
12154                                 goto badsub;
12155                         }
12156
12157                         USTPUTC(cc, out);
12158                 }
12159
12160                 if (c != '}' && subtype == VSLENGTH) {
12161                         /* ${#VAR didn't end with } */
12162                         goto badsub;
12163                 }
12164
12165                 if (subtype == 0) {
12166                         static const char types[] ALIGN1 = "}-+?=";
12167                         /* ${VAR...} but not $VAR or ${#VAR} */
12168                         /* c == first char after VAR */
12169                         switch (c) {
12170                         case ':':
12171                                 c = pgetc_eatbnl();
12172 #if BASH_SUBSTR
12173                                 /* This check is only needed to not misinterpret
12174                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12175                                  * constructs.
12176                                  */
12177                                 if (!strchr(types, c)) {
12178                                         subtype = VSSUBSTR;
12179                                         pungetc();
12180                                         break; /* "goto badsub" is bigger (!) */
12181                                 }
12182 #endif
12183                                 subtype = VSNUL;
12184                                 /*FALLTHROUGH*/
12185                         default: {
12186                                 const char *p = strchr(types, c);
12187                                 if (p == NULL)
12188                                         break;
12189                                 subtype |= p - types + VSNORMAL;
12190                                 break;
12191                         }
12192                         case '%':
12193                         case '#': {
12194                                 int cc = c;
12195                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12196                                 c = pgetc_eatbnl();
12197                                 if (c != cc)
12198                                         goto badsub;
12199                                 subtype++;
12200                                 break;
12201                         }
12202 #if BASH_PATTERN_SUBST
12203                         case '/':
12204                                 /* ${v/[/]pattern/repl} */
12205 //TODO: encode pattern and repl separately.
12206 // Currently ${v/$var_with_slash/repl} is horribly broken
12207                                 subtype = VSREPLACE;
12208                                 c = pgetc_eatbnl();
12209                                 if (c != '/')
12210                                         goto badsub;
12211                                 subtype++; /* VSREPLACEALL */
12212                                 break;
12213 #endif
12214                         }
12215                 } else {
12216  badsub:
12217                         pungetc();
12218                 }
12219                 ((unsigned char *)stackblock())[typeloc] = subtype;
12220                 if (subtype != VSNORMAL) {
12221                         varnest++;
12222                         if (dblquote)
12223                                 dqvarnest++;
12224                 }
12225                 STPUTC('=', out);
12226         }
12227         goto parsesub_return;
12228 }
12229
12230 /*
12231  * Called to parse command substitutions.  Newstyle is set if the command
12232  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12233  * list of commands (passed by reference), and savelen is the number of
12234  * characters on the top of the stack which must be preserved.
12235  */
12236 parsebackq: {
12237         struct nodelist **nlpp;
12238         union node *n;
12239         char *str;
12240         size_t savelen;
12241         smallint saveprompt = 0;
12242
12243         str = NULL;
12244         savelen = out - (char *)stackblock();
12245         if (savelen > 0) {
12246                 /*
12247                  * FIXME: this can allocate very large block on stack and SEGV.
12248                  * Example:
12249                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12250                  * allocates 100kb for every command subst. With about
12251                  * a hundred command substitutions stack overflows.
12252                  * With larger prepended string, SEGV happens sooner.
12253                  */
12254                 str = alloca(savelen);
12255                 memcpy(str, stackblock(), savelen);
12256         }
12257
12258         if (oldstyle) {
12259                 /* We must read until the closing backquote, giving special
12260                  * treatment to some slashes, and then push the string and
12261                  * reread it as input, interpreting it normally.
12262                  */
12263                 char *pout;
12264                 size_t psavelen;
12265                 char *pstr;
12266
12267                 STARTSTACKSTR(pout);
12268                 for (;;) {
12269                         int pc;
12270
12271                         setprompt_if(needprompt, 2);
12272                         pc = pgetc();
12273                         switch (pc) {
12274                         case '`':
12275                                 goto done;
12276
12277                         case '\\':
12278                                 pc = pgetc();
12279                                 if (pc == '\n') {
12280                                         nlprompt();
12281                                         /*
12282                                          * If eating a newline, avoid putting
12283                                          * the newline into the new character
12284                                          * stream (via the STPUTC after the
12285                                          * switch).
12286                                          */
12287                                         continue;
12288                                 }
12289                                 if (pc != '\\' && pc != '`' && pc != '$'
12290                                  && (!dblquote || pc != '"')
12291                                 ) {
12292                                         STPUTC('\\', pout);
12293                                 }
12294                                 if (pc <= 255 /* not PEOA or PEOF */) {
12295                                         break;
12296                                 }
12297                                 /* fall through */
12298
12299                         case PEOF:
12300                         IF_ASH_ALIAS(case PEOA:)
12301                                 startlinno = g_parsefile->linno;
12302                                 raise_error_syntax("EOF in backquote substitution");
12303
12304                         case '\n':
12305                                 nlnoprompt();
12306                                 break;
12307
12308                         default:
12309                                 break;
12310                         }
12311                         STPUTC(pc, pout);
12312                 }
12313  done:
12314                 STPUTC('\0', pout);
12315                 psavelen = pout - (char *)stackblock();
12316                 if (psavelen > 0) {
12317                         pstr = grabstackstr(pout);
12318                         setinputstring(pstr);
12319                 }
12320         }
12321         nlpp = &bqlist;
12322         while (*nlpp)
12323                 nlpp = &(*nlpp)->next;
12324         *nlpp = stzalloc(sizeof(**nlpp));
12325         /* (*nlpp)->next = NULL; - stzalloc did it */
12326
12327         if (oldstyle) {
12328                 saveprompt = doprompt;
12329                 doprompt = 0;
12330         }
12331
12332         n = list(2);
12333
12334         if (oldstyle)
12335                 doprompt = saveprompt;
12336         else if (readtoken() != TRP)
12337                 raise_error_unexpected_syntax(TRP);
12338
12339         (*nlpp)->n = n;
12340         if (oldstyle) {
12341                 /*
12342                  * Start reading from old file again, ignoring any pushed back
12343                  * tokens left from the backquote parsing
12344                  */
12345                 popfile();
12346                 tokpushback = 0;
12347         }
12348         while (stackblocksize() <= savelen)
12349                 growstackblock();
12350         STARTSTACKSTR(out);
12351         if (str) {
12352                 memcpy(out, str, savelen);
12353                 STADJUST(savelen, out);
12354         }
12355         USTPUTC(CTLBACKQ, out);
12356         if (oldstyle)
12357                 goto parsebackq_oldreturn;
12358         goto parsebackq_newreturn;
12359 }
12360
12361 #if ENABLE_FEATURE_SH_MATH
12362 /*
12363  * Parse an arithmetic expansion (indicate start of one and set state)
12364  */
12365 parsearith: {
12366         if (++arinest == 1) {
12367                 prevsyntax = syntax;
12368                 syntax = ARISYNTAX;
12369         }
12370         USTPUTC(CTLARI, out);
12371         goto parsearith_return;
12372 }
12373 #endif
12374 } /* end of readtoken */
12375
12376 /*
12377  * Read the next input token.
12378  * If the token is a word, we set backquotelist to the list of cmds in
12379  *      backquotes.  We set quoteflag to true if any part of the word was
12380  *      quoted.
12381  * If the token is TREDIR, then we set redirnode to a structure containing
12382  *      the redirection.
12383  * In all cases, the variable startlinno is set to the number of the line
12384  *      on which the token starts.
12385  *
12386  * [Change comment:  here documents and internal procedures]
12387  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12388  *  word parsing code into a separate routine.  In this case, readtoken
12389  *  doesn't need to have any internal procedures, but parseword does.
12390  *  We could also make parseoperator in essence the main routine, and
12391  *  have parseword (readtoken1?) handle both words and redirection.]
12392  */
12393 #define NEW_xxreadtoken
12394 #ifdef NEW_xxreadtoken
12395 /* singles must be first! */
12396 static const char xxreadtoken_chars[7] ALIGN1 = {
12397         '\n', '(', ')', /* singles */
12398         '&', '|', ';',  /* doubles */
12399         0
12400 };
12401
12402 #define xxreadtoken_singles 3
12403 #define xxreadtoken_doubles 3
12404
12405 static const char xxreadtoken_tokens[] ALIGN1 = {
12406         TNL, TLP, TRP,          /* only single occurrence allowed */
12407         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12408         TEOF,                   /* corresponds to trailing nul */
12409         TAND, TOR, TENDCASE     /* if double occurrence */
12410 };
12411
12412 static int
12413 xxreadtoken(void)
12414 {
12415         int c;
12416
12417         if (tokpushback) {
12418                 tokpushback = 0;
12419                 return lasttoken;
12420         }
12421         setprompt_if(needprompt, 2);
12422         startlinno = g_parsefile->linno;
12423         for (;;) {                      /* until token or start of word found */
12424                 c = pgetc();
12425                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12426                         continue;
12427
12428                 if (c == '#') {
12429                         while ((c = pgetc()) != '\n' && c != PEOF)
12430                                 continue;
12431                         pungetc();
12432                 } else if (c == '\\') {
12433                         if (pgetc() != '\n') {
12434                                 pungetc();
12435                                 break; /* return readtoken1(...) */
12436                         }
12437                         nlprompt();
12438                 } else {
12439                         const char *p;
12440
12441                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12442                         if (c != PEOF) {
12443                                 if (c == '\n') {
12444                                         nlnoprompt();
12445                                 }
12446
12447                                 p = strchr(xxreadtoken_chars, c);
12448                                 if (p == NULL)
12449                                         break; /* return readtoken1(...) */
12450
12451                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12452                                         int cc = pgetc();
12453                                         if (cc == c) {    /* double occurrence? */
12454                                                 p += xxreadtoken_doubles + 1;
12455                                         } else {
12456                                                 pungetc();
12457 #if BASH_REDIR_OUTPUT
12458                                                 if (c == '&' && cc == '>') /* &> */
12459                                                         break; /* return readtoken1(...) */
12460 #endif
12461                                         }
12462                                 }
12463                         }
12464                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12465                         return lasttoken;
12466                 }
12467         } /* for (;;) */
12468
12469         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12470 }
12471 #else /* old xxreadtoken */
12472 #define RETURN(token)   return lasttoken = token
12473 static int
12474 xxreadtoken(void)
12475 {
12476         int c;
12477
12478         if (tokpushback) {
12479                 tokpushback = 0;
12480                 return lasttoken;
12481         }
12482         setprompt_if(needprompt, 2);
12483         startlinno = g_parsefile->linno;
12484         for (;;) {      /* until token or start of word found */
12485                 c = pgetc();
12486                 switch (c) {
12487                 case ' ': case '\t':
12488                 IF_ASH_ALIAS(case PEOA:)
12489                         continue;
12490                 case '#':
12491                         while ((c = pgetc()) != '\n' && c != PEOF)
12492                                 continue;
12493                         pungetc();
12494                         continue;
12495                 case '\\':
12496                         if (pgetc() == '\n') {
12497                                 nlprompt();
12498                                 continue;
12499                         }
12500                         pungetc();
12501                         goto breakloop;
12502                 case '\n':
12503                         nlnoprompt();
12504                         RETURN(TNL);
12505                 case PEOF:
12506                         RETURN(TEOF);
12507                 case '&':
12508                         if (pgetc() == '&')
12509                                 RETURN(TAND);
12510                         pungetc();
12511                         RETURN(TBACKGND);
12512                 case '|':
12513                         if (pgetc() == '|')
12514                                 RETURN(TOR);
12515                         pungetc();
12516                         RETURN(TPIPE);
12517                 case ';':
12518                         if (pgetc() == ';')
12519                                 RETURN(TENDCASE);
12520                         pungetc();
12521                         RETURN(TSEMI);
12522                 case '(':
12523                         RETURN(TLP);
12524                 case ')':
12525                         RETURN(TRP);
12526                 default:
12527                         goto breakloop;
12528                 }
12529         }
12530  breakloop:
12531         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12532 #undef RETURN
12533 }
12534 #endif /* old xxreadtoken */
12535
12536 static int
12537 readtoken(void)
12538 {
12539         int t;
12540         int kwd = checkkwd;
12541 #if DEBUG
12542         smallint alreadyseen = tokpushback;
12543 #endif
12544
12545 #if ENABLE_ASH_ALIAS
12546  top:
12547 #endif
12548
12549         t = xxreadtoken();
12550
12551         /*
12552          * eat newlines
12553          */
12554         if (kwd & CHKNL) {
12555                 while (t == TNL) {
12556                         parseheredoc();
12557                         t = xxreadtoken();
12558                 }
12559         }
12560
12561         if (t != TWORD || quoteflag) {
12562                 goto out;
12563         }
12564
12565         /*
12566          * check for keywords
12567          */
12568         if (kwd & CHKKWD) {
12569                 const char *const *pp;
12570
12571                 pp = findkwd(wordtext);
12572                 if (pp) {
12573                         lasttoken = t = pp - tokname_array;
12574                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12575                         goto out;
12576                 }
12577         }
12578
12579         if (checkkwd & CHKALIAS) {
12580 #if ENABLE_ASH_ALIAS
12581                 struct alias *ap;
12582                 ap = lookupalias(wordtext, 1);
12583                 if (ap != NULL) {
12584                         if (*ap->val) {
12585                                 pushstring(ap->val, ap);
12586                         }
12587                         goto top;
12588                 }
12589 #endif
12590         }
12591  out:
12592         checkkwd = 0;
12593 #if DEBUG
12594         if (!alreadyseen)
12595                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12596         else
12597                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12598 #endif
12599         return t;
12600 }
12601
12602 static int
12603 peektoken(void)
12604 {
12605         int t;
12606
12607         t = readtoken();
12608         tokpushback = 1;
12609         return t;
12610 }
12611
12612 /*
12613  * Read and parse a command.  Returns NODE_EOF on end of file.
12614  * (NULL is a valid parse tree indicating a blank line.)
12615  */
12616 static union node *
12617 parsecmd(int interact)
12618 {
12619         tokpushback = 0;
12620         checkkwd = 0;
12621         heredoclist = 0;
12622         doprompt = interact;
12623         setprompt_if(doprompt, doprompt);
12624         needprompt = 0;
12625         return list(1);
12626 }
12627
12628 /*
12629  * Input any here documents.
12630  */
12631 static void
12632 parseheredoc(void)
12633 {
12634         struct heredoc *here;
12635         union node *n;
12636
12637         here = heredoclist;
12638         heredoclist = NULL;
12639
12640         while (here) {
12641                 setprompt_if(needprompt, 2);
12642                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12643                                 here->eofmark, here->striptabs);
12644                 n = stzalloc(sizeof(struct narg));
12645                 n->narg.type = NARG;
12646                 /*n->narg.next = NULL; - stzalloc did it */
12647                 n->narg.text = wordtext;
12648                 n->narg.backquote = backquotelist;
12649                 here->here->nhere.doc = n;
12650                 here = here->next;
12651         }
12652 }
12653
12654
12655 static const char *
12656 expandstr(const char *ps, int syntax_type)
12657 {
12658         union node n;
12659         int saveprompt;
12660
12661         /* XXX Fix (char *) cast. */
12662         setinputstring((char *)ps);
12663
12664         saveprompt = doprompt;
12665         doprompt = 0;
12666         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12667         doprompt = saveprompt;
12668
12669         popfile();
12670
12671         n.narg.type = NARG;
12672         n.narg.next = NULL;
12673         n.narg.text = wordtext;
12674         n.narg.backquote = backquotelist;
12675
12676         expandarg(&n, NULL, EXP_QUOTED);
12677         return stackblock();
12678 }
12679
12680 static inline int
12681 parser_eof(void)
12682 {
12683         return tokpushback && lasttoken == TEOF;
12684 }
12685
12686 /*
12687  * Execute a command or commands contained in a string.
12688  */
12689 static int
12690 evalstring(char *s, int flags)
12691 {
12692         struct jmploc *volatile savehandler;
12693         struct jmploc jmploc;
12694         int ex;
12695
12696         union node *n;
12697         struct stackmark smark;
12698         int status;
12699
12700         s = sstrdup(s);
12701         setinputstring(s);
12702         setstackmark(&smark);
12703
12704         status = 0;
12705         /* On exception inside execution loop, we must popfile().
12706          * Try interactively:
12707          *      readonly a=a
12708          *      command eval "a=b"  # throws "is read only" error
12709          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12710          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12711          */
12712         savehandler = exception_handler;
12713         ex = setjmp(jmploc.loc);
12714         if (ex)
12715                 goto out;
12716         exception_handler = &jmploc;
12717
12718         while ((n = parsecmd(0)) != NODE_EOF) {
12719                 int i;
12720
12721                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12722                 if (n)
12723                         status = i;
12724                 popstackmark(&smark);
12725                 if (evalskip)
12726                         break;
12727         }
12728  out:
12729         popstackmark(&smark);
12730         popfile();
12731         stunalloc(s);
12732
12733         exception_handler = savehandler;
12734         if (ex)
12735                 longjmp(exception_handler->loc, ex);
12736
12737         return status;
12738 }
12739
12740 /*
12741  * The eval command.
12742  */
12743 static int FAST_FUNC
12744 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12745 {
12746         char *p;
12747         char *concat;
12748
12749         if (argv[1]) {
12750                 p = argv[1];
12751                 argv += 2;
12752                 if (argv[0]) {
12753                         STARTSTACKSTR(concat);
12754                         for (;;) {
12755                                 concat = stack_putstr(p, concat);
12756                                 p = *argv++;
12757                                 if (p == NULL)
12758                                         break;
12759                                 STPUTC(' ', concat);
12760                         }
12761                         STPUTC('\0', concat);
12762                         p = grabstackstr(concat);
12763                 }
12764                 return evalstring(p, flags & EV_TESTED);
12765         }
12766         return 0;
12767 }
12768
12769 /*
12770  * Read and execute commands.
12771  * "Top" is nonzero for the top level command loop;
12772  * it turns on prompting if the shell is interactive.
12773  */
12774 static int
12775 cmdloop(int top)
12776 {
12777         union node *n;
12778         struct stackmark smark;
12779         int inter;
12780         int status = 0;
12781         int numeof = 0;
12782
12783         TRACE(("cmdloop(%d) called\n", top));
12784         for (;;) {
12785                 int skip;
12786
12787                 setstackmark(&smark);
12788 #if JOBS
12789                 if (doing_jobctl)
12790                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12791 #endif
12792                 inter = 0;
12793                 if (iflag && top) {
12794                         inter++;
12795                         chkmail();
12796                 }
12797                 n = parsecmd(inter);
12798 #if DEBUG
12799                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12800                         showtree(n);
12801 #endif
12802                 if (n == NODE_EOF) {
12803                         if (!top || numeof >= 50)
12804                                 break;
12805                         if (!stoppedjobs()) {
12806                                 if (!Iflag)
12807                                         break;
12808                                 out2str("\nUse \"exit\" to leave shell.\n");
12809                         }
12810                         numeof++;
12811                 } else if (nflag == 0) {
12812                         int i;
12813
12814                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12815                         job_warning >>= 1;
12816                         numeof = 0;
12817                         i = evaltree(n, 0);
12818                         if (n)
12819                                 status = i;
12820                 }
12821                 popstackmark(&smark);
12822                 skip = evalskip;
12823
12824                 if (skip) {
12825                         evalskip &= ~SKIPFUNC;
12826                         break;
12827                 }
12828         }
12829         return status;
12830 }
12831
12832 /*
12833  * Take commands from a file.  To be compatible we should do a path
12834  * search for the file, which is necessary to find sub-commands.
12835  */
12836 static char *
12837 find_dot_file(char *name)
12838 {
12839         char *fullname;
12840         const char *path = pathval();
12841         struct stat statb;
12842
12843         /* don't try this for absolute or relative paths */
12844         if (strchr(name, '/'))
12845                 return name;
12846
12847         while ((fullname = path_advance(&path, name)) != NULL) {
12848                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12849                         /*
12850                          * Don't bother freeing here, since it will
12851                          * be freed by the caller.
12852                          */
12853                         return fullname;
12854                 }
12855                 if (fullname != name)
12856                         stunalloc(fullname);
12857         }
12858
12859         /* not found in the PATH */
12860         ash_msg_and_raise_error("%s: not found", name);
12861         /* NOTREACHED */
12862 }
12863
12864 static int FAST_FUNC
12865 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12866 {
12867         /* "false; . empty_file; echo $?" should print 0, not 1: */
12868         int status = 0;
12869         char *fullname;
12870         char **argv;
12871         char *args_need_save;
12872         volatile struct shparam saveparam;
12873
12874 //???
12875 //      struct strlist *sp;
12876 //      for (sp = cmdenviron; sp; sp = sp->next)
12877 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12878
12879         nextopt(nullstr); /* handle possible "--" */
12880         argv = argptr;
12881
12882         if (!argv[0]) {
12883                 /* bash says: "bash: .: filename argument required" */
12884                 return 2; /* bash compat */
12885         }
12886
12887         /* This aborts if file isn't found, which is POSIXly correct.
12888          * bash returns exitcode 1 instead.
12889          */
12890         fullname = find_dot_file(argv[0]);
12891         argv++;
12892         args_need_save = argv[0];
12893         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12894                 int argc;
12895                 saveparam = shellparam;
12896                 shellparam.malloced = 0;
12897                 argc = 1;
12898                 while (argv[argc])
12899                         argc++;
12900                 shellparam.nparam = argc;
12901                 shellparam.p = argv;
12902         };
12903
12904         /* This aborts if file can't be opened, which is POSIXly correct.
12905          * bash returns exitcode 1 instead.
12906          */
12907         setinputfile(fullname, INPUT_PUSH_FILE);
12908         commandname = fullname;
12909         status = cmdloop(0);
12910         popfile();
12911
12912         if (args_need_save) {
12913                 freeparam(&shellparam);
12914                 shellparam = saveparam;
12915         };
12916
12917         return status;
12918 }
12919
12920 static int FAST_FUNC
12921 exitcmd(int argc UNUSED_PARAM, char **argv)
12922 {
12923         if (stoppedjobs())
12924                 return 0;
12925         if (argv[1])
12926                 exitstatus = number(argv[1]);
12927         raise_exception(EXEXIT);
12928         /* NOTREACHED */
12929 }
12930
12931 /*
12932  * Read a file containing shell functions.
12933  */
12934 static void
12935 readcmdfile(char *name)
12936 {
12937         setinputfile(name, INPUT_PUSH_FILE);
12938         cmdloop(0);
12939         popfile();
12940 }
12941
12942
12943 /* ============ find_command inplementation */
12944
12945 /*
12946  * Resolve a command name.  If you change this routine, you may have to
12947  * change the shellexec routine as well.
12948  */
12949 static void
12950 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12951 {
12952         struct tblentry *cmdp;
12953         int idx;
12954         int prev;
12955         char *fullname;
12956         struct stat statb;
12957         int e;
12958         int updatetbl;
12959         struct builtincmd *bcmd;
12960
12961         /* If name contains a slash, don't use PATH or hash table */
12962         if (strchr(name, '/') != NULL) {
12963                 entry->u.index = -1;
12964                 if (act & DO_ABS) {
12965                         while (stat(name, &statb) < 0) {
12966 #ifdef SYSV
12967                                 if (errno == EINTR)
12968                                         continue;
12969 #endif
12970                                 entry->cmdtype = CMDUNKNOWN;
12971                                 return;
12972                         }
12973                 }
12974                 entry->cmdtype = CMDNORMAL;
12975                 return;
12976         }
12977
12978 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12979
12980         updatetbl = (path == pathval());
12981         if (!updatetbl) {
12982                 act |= DO_ALTPATH;
12983                 if (strstr(path, "%builtin") != NULL)
12984                         act |= DO_ALTBLTIN;
12985         }
12986
12987         /* If name is in the table, check answer will be ok */
12988         cmdp = cmdlookup(name, 0);
12989         if (cmdp != NULL) {
12990                 int bit;
12991
12992                 switch (cmdp->cmdtype) {
12993                 default:
12994 #if DEBUG
12995                         abort();
12996 #endif
12997                 case CMDNORMAL:
12998                         bit = DO_ALTPATH;
12999                         break;
13000                 case CMDFUNCTION:
13001                         bit = DO_NOFUNC;
13002                         break;
13003                 case CMDBUILTIN:
13004                         bit = DO_ALTBLTIN;
13005                         break;
13006                 }
13007                 if (act & bit) {
13008                         updatetbl = 0;
13009                         cmdp = NULL;
13010                 } else if (cmdp->rehash == 0)
13011                         /* if not invalidated by cd, we're done */
13012                         goto success;
13013         }
13014
13015         /* If %builtin not in path, check for builtin next */
13016         bcmd = find_builtin(name);
13017         if (bcmd) {
13018                 if (IS_BUILTIN_REGULAR(bcmd))
13019                         goto builtin_success;
13020                 if (act & DO_ALTPATH) {
13021                         if (!(act & DO_ALTBLTIN))
13022                                 goto builtin_success;
13023                 } else if (builtinloc <= 0) {
13024                         goto builtin_success;
13025                 }
13026         }
13027
13028 #if ENABLE_FEATURE_SH_STANDALONE
13029         {
13030                 int applet_no = find_applet_by_name(name);
13031                 if (applet_no >= 0) {
13032                         entry->cmdtype = CMDNORMAL;
13033                         entry->u.index = -2 - applet_no;
13034                         return;
13035                 }
13036         }
13037 #endif
13038
13039         /* We have to search path. */
13040         prev = -1;              /* where to start */
13041         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13042                 if (cmdp->cmdtype == CMDBUILTIN)
13043                         prev = builtinloc;
13044                 else
13045                         prev = cmdp->param.index;
13046         }
13047
13048         e = ENOENT;
13049         idx = -1;
13050  loop:
13051         while ((fullname = path_advance(&path, name)) != NULL) {
13052                 stunalloc(fullname);
13053                 /* NB: code below will still use fullname
13054                  * despite it being "unallocated" */
13055                 idx++;
13056                 if (pathopt) {
13057                         if (prefix(pathopt, "builtin")) {
13058                                 if (bcmd)
13059                                         goto builtin_success;
13060                                 continue;
13061                         }
13062                         if ((act & DO_NOFUNC)
13063                          || !prefix(pathopt, "func")
13064                         ) {     /* ignore unimplemented options */
13065                                 continue;
13066                         }
13067                 }
13068                 /* if rehash, don't redo absolute path names */
13069                 if (fullname[0] == '/' && idx <= prev) {
13070                         if (idx < prev)
13071                                 continue;
13072                         TRACE(("searchexec \"%s\": no change\n", name));
13073                         goto success;
13074                 }
13075                 while (stat(fullname, &statb) < 0) {
13076 #ifdef SYSV
13077                         if (errno == EINTR)
13078                                 continue;
13079 #endif
13080                         if (errno != ENOENT && errno != ENOTDIR)
13081                                 e = errno;
13082                         goto loop;
13083                 }
13084                 e = EACCES;     /* if we fail, this will be the error */
13085                 if (!S_ISREG(statb.st_mode))
13086                         continue;
13087                 if (pathopt) {          /* this is a %func directory */
13088                         stalloc(strlen(fullname) + 1);
13089                         /* NB: stalloc will return space pointed by fullname
13090                          * (because we don't have any intervening allocations
13091                          * between stunalloc above and this stalloc) */
13092                         readcmdfile(fullname);
13093                         cmdp = cmdlookup(name, 0);
13094                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13095                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13096                         stunalloc(fullname);
13097                         goto success;
13098                 }
13099                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13100                 if (!updatetbl) {
13101                         entry->cmdtype = CMDNORMAL;
13102                         entry->u.index = idx;
13103                         return;
13104                 }
13105                 INT_OFF;
13106                 cmdp = cmdlookup(name, 1);
13107                 cmdp->cmdtype = CMDNORMAL;
13108                 cmdp->param.index = idx;
13109                 INT_ON;
13110                 goto success;
13111         }
13112
13113         /* We failed.  If there was an entry for this command, delete it */
13114         if (cmdp && updatetbl)
13115                 delete_cmd_entry();
13116         if (act & DO_ERR)
13117                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13118         entry->cmdtype = CMDUNKNOWN;
13119         return;
13120
13121  builtin_success:
13122         if (!updatetbl) {
13123                 entry->cmdtype = CMDBUILTIN;
13124                 entry->u.cmd = bcmd;
13125                 return;
13126         }
13127         INT_OFF;
13128         cmdp = cmdlookup(name, 1);
13129         cmdp->cmdtype = CMDBUILTIN;
13130         cmdp->param.cmd = bcmd;
13131         INT_ON;
13132  success:
13133         cmdp->rehash = 0;
13134         entry->cmdtype = cmdp->cmdtype;
13135         entry->u = cmdp->param;
13136 }
13137
13138
13139 /*
13140  * The trap builtin.
13141  */
13142 static int FAST_FUNC
13143 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13144 {
13145         char *action;
13146         char **ap;
13147         int signo, exitcode;
13148
13149         nextopt(nullstr);
13150         ap = argptr;
13151         if (!*ap) {
13152                 for (signo = 0; signo < NSIG; signo++) {
13153                         char *tr = trap_ptr[signo];
13154                         if (tr) {
13155                                 /* note: bash adds "SIG", but only if invoked
13156                                  * as "bash". If called as "sh", or if set -o posix,
13157                                  * then it prints short signal names.
13158                                  * We are printing short names: */
13159                                 out1fmt("trap -- %s %s\n",
13160                                                 single_quote(tr),
13161                                                 get_signame(signo));
13162                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13163                  * In this case, we will exit very soon, no need to free(). */
13164                                 /* if (trap_ptr != trap && tp[0]) */
13165                                 /*      free(tr); */
13166                         }
13167                 }
13168                 /*
13169                 if (trap_ptr != trap) {
13170                         free(trap_ptr);
13171                         trap_ptr = trap;
13172                 }
13173                 */
13174                 return 0;
13175         }
13176
13177         /* Why the second check?
13178          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13179          * In this case, NUM is signal no, not an action.
13180          */
13181         action = NULL;
13182         if (ap[1] && !is_number(ap[0]))
13183                 action = *ap++;
13184
13185         exitcode = 0;
13186         while (*ap) {
13187                 signo = get_signum(*ap);
13188                 if (signo < 0) {
13189                         /* Mimic bash message exactly */
13190                         ash_msg("%s: invalid signal specification", *ap);
13191                         exitcode = 1;
13192                         goto next;
13193                 }
13194                 INT_OFF;
13195                 if (action) {
13196                         if (LONE_DASH(action))
13197                                 action = NULL;
13198                         else {
13199                                 if (action[0]) /* not NULL and not "" and not "-" */
13200                                         may_have_traps = 1;
13201                                 action = ckstrdup(action);
13202                         }
13203                 }
13204                 free(trap[signo]);
13205                 trap[signo] = action;
13206                 if (signo != 0)
13207                         setsignal(signo);
13208                 INT_ON;
13209  next:
13210                 ap++;
13211         }
13212         return exitcode;
13213 }
13214
13215
13216 /* ============ Builtins */
13217
13218 #if ENABLE_ASH_HELP
13219 static int FAST_FUNC
13220 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13221 {
13222         unsigned col;
13223         unsigned i;
13224
13225         out1fmt(
13226                 "Built-in commands:\n"
13227                 "------------------\n");
13228         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13229                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13230                                         builtintab[i].name + 1);
13231                 if (col > 60) {
13232                         out1fmt("\n");
13233                         col = 0;
13234                 }
13235         }
13236 # if ENABLE_FEATURE_SH_STANDALONE
13237         {
13238                 const char *a = applet_names;
13239                 while (*a) {
13240                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13241                         if (col > 60) {
13242                                 out1fmt("\n");
13243                                 col = 0;
13244                         }
13245                         while (*a++ != '\0')
13246                                 continue;
13247                 }
13248         }
13249 # endif
13250         newline_and_flush(stdout);
13251         return EXIT_SUCCESS;
13252 }
13253 #endif
13254
13255 #if MAX_HISTORY
13256 static int FAST_FUNC
13257 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13258 {
13259         show_history(line_input_state);
13260         return EXIT_SUCCESS;
13261 }
13262 #endif
13263
13264 /*
13265  * The export and readonly commands.
13266  */
13267 static int FAST_FUNC
13268 exportcmd(int argc UNUSED_PARAM, char **argv)
13269 {
13270         struct var *vp;
13271         char *name;
13272         const char *p;
13273         char **aptr;
13274         char opt;
13275         int flag;
13276         int flag_off;
13277
13278         /* "readonly" in bash accepts, but ignores -n.
13279          * We do the same: it saves a conditional in nextopt's param.
13280          */
13281         flag_off = 0;
13282         while ((opt = nextopt("np")) != '\0') {
13283                 if (opt == 'n')
13284                         flag_off = VEXPORT;
13285         }
13286         flag = VEXPORT;
13287         if (argv[0][0] == 'r') {
13288                 flag = VREADONLY;
13289                 flag_off = 0; /* readonly ignores -n */
13290         }
13291         flag_off = ~flag_off;
13292
13293         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13294         {
13295                 aptr = argptr;
13296                 name = *aptr;
13297                 if (name) {
13298                         do {
13299                                 p = strchr(name, '=');
13300                                 if (p != NULL) {
13301                                         p++;
13302                                 } else {
13303                                         vp = *findvar(hashvar(name), name);
13304                                         if (vp) {
13305                                                 vp->flags = ((vp->flags | flag) & flag_off);
13306                                                 continue;
13307                                         }
13308                                 }
13309                                 setvar(name, p, (flag & flag_off));
13310                         } while ((name = *++aptr) != NULL);
13311                         return 0;
13312                 }
13313         }
13314
13315         /* No arguments. Show the list of exported or readonly vars.
13316          * -n is ignored.
13317          */
13318         showvars(argv[0], flag, 0);
13319         return 0;
13320 }
13321
13322 /*
13323  * Delete a function if it exists.
13324  */
13325 static void
13326 unsetfunc(const char *name)
13327 {
13328         struct tblentry *cmdp;
13329
13330         cmdp = cmdlookup(name, 0);
13331         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13332                 delete_cmd_entry();
13333 }
13334
13335 /*
13336  * The unset builtin command.  We unset the function before we unset the
13337  * variable to allow a function to be unset when there is a readonly variable
13338  * with the same name.
13339  */
13340 static int FAST_FUNC
13341 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13342 {
13343         char **ap;
13344         int i;
13345         int flag = 0;
13346
13347         while ((i = nextopt("vf")) != 0) {
13348                 flag = i;
13349         }
13350
13351         for (ap = argptr; *ap; ap++) {
13352                 if (flag != 'f') {
13353                         unsetvar(*ap);
13354                         continue;
13355                 }
13356                 if (flag != 'v')
13357                         unsetfunc(*ap);
13358         }
13359         return 0;
13360 }
13361
13362 static const unsigned char timescmd_str[] ALIGN1 = {
13363         ' ',  offsetof(struct tms, tms_utime),
13364         '\n', offsetof(struct tms, tms_stime),
13365         ' ',  offsetof(struct tms, tms_cutime),
13366         '\n', offsetof(struct tms, tms_cstime),
13367         0
13368 };
13369 static int FAST_FUNC
13370 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13371 {
13372         unsigned clk_tck;
13373         const unsigned char *p;
13374         struct tms buf;
13375
13376         clk_tck = bb_clk_tck();
13377
13378         times(&buf);
13379         p = timescmd_str;
13380         do {
13381                 unsigned sec, frac;
13382                 unsigned long t;
13383                 t = *(clock_t *)(((char *) &buf) + p[1]);
13384                 sec = t / clk_tck;
13385                 frac = t % clk_tck;
13386                 out1fmt("%um%u.%03us%c",
13387                         sec / 60, sec % 60,
13388                         (frac * 1000) / clk_tck,
13389                         p[0]);
13390                 p += 2;
13391         } while (*p);
13392
13393         return 0;
13394 }
13395
13396 #if ENABLE_FEATURE_SH_MATH
13397 /*
13398  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13399  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13400  *
13401  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13402  */
13403 static int FAST_FUNC
13404 letcmd(int argc UNUSED_PARAM, char **argv)
13405 {
13406         arith_t i;
13407
13408         argv++;
13409         if (!*argv)
13410                 ash_msg_and_raise_error("expression expected");
13411         do {
13412                 i = ash_arith(*argv);
13413         } while (*++argv);
13414
13415         return !i;
13416 }
13417 #endif
13418
13419 /*
13420  * The read builtin. Options:
13421  *      -r              Do not interpret '\' specially
13422  *      -s              Turn off echo (tty only)
13423  *      -n NCHARS       Read NCHARS max
13424  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13425  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13426  *      -u FD           Read from given FD instead of fd 0
13427  *      -d DELIM        End on DELIM char, not newline
13428  * This uses unbuffered input, which may be avoidable in some cases.
13429  * TODO: bash also has:
13430  *      -a ARRAY        Read into array[0],[1],etc
13431  *      -e              Use line editing (tty only)
13432  */
13433 static int FAST_FUNC
13434 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13435 {
13436         char *opt_n = NULL;
13437         char *opt_p = NULL;
13438         char *opt_t = NULL;
13439         char *opt_u = NULL;
13440         char *opt_d = NULL; /* optimized out if !BASH */
13441         int read_flags = 0;
13442         const char *r;
13443         int i;
13444
13445         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13446                 switch (i) {
13447                 case 'p':
13448                         opt_p = optionarg;
13449                         break;
13450                 case 'n':
13451                         opt_n = optionarg;
13452                         break;
13453                 case 's':
13454                         read_flags |= BUILTIN_READ_SILENT;
13455                         break;
13456                 case 't':
13457                         opt_t = optionarg;
13458                         break;
13459                 case 'r':
13460                         read_flags |= BUILTIN_READ_RAW;
13461                         break;
13462                 case 'u':
13463                         opt_u = optionarg;
13464                         break;
13465 #if BASH_READ_D
13466                 case 'd':
13467                         opt_d = optionarg;
13468                         break;
13469 #endif
13470                 default:
13471                         break;
13472                 }
13473         }
13474
13475         /* "read -s" needs to save/restore termios, can't allow ^C
13476          * to jump out of it.
13477          */
13478  again:
13479         INT_OFF;
13480         r = shell_builtin_read(setvar0,
13481                 argptr,
13482                 bltinlookup("IFS"), /* can be NULL */
13483                 read_flags,
13484                 opt_n,
13485                 opt_p,
13486                 opt_t,
13487                 opt_u,
13488                 opt_d
13489         );
13490         INT_ON;
13491
13492         if ((uintptr_t)r == 1 && errno == EINTR) {
13493                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13494                  * Correct behavior is to not exit "read"
13495                  */
13496                 if (pending_sig == 0)
13497                         goto again;
13498         }
13499
13500         if ((uintptr_t)r > 1)
13501                 ash_msg_and_raise_error(r);
13502
13503         return (uintptr_t)r;
13504 }
13505
13506 static int FAST_FUNC
13507 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13508 {
13509         static const char permuser[3] ALIGN1 = "ogu";
13510
13511         mode_t mask;
13512         int symbolic_mode = 0;
13513
13514         while (nextopt("S") != '\0') {
13515                 symbolic_mode = 1;
13516         }
13517
13518         INT_OFF;
13519         mask = umask(0);
13520         umask(mask);
13521         INT_ON;
13522
13523         if (*argptr == NULL) {
13524                 if (symbolic_mode) {
13525                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13526                         char *p = buf;
13527                         int i;
13528
13529                         i = 2;
13530                         for (;;) {
13531                                 *p++ = ',';
13532                                 *p++ = permuser[i];
13533                                 *p++ = '=';
13534                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13535                                 if (!(mask & 0400)) *p++ = 'r';
13536                                 if (!(mask & 0200)) *p++ = 'w';
13537                                 if (!(mask & 0100)) *p++ = 'x';
13538                                 mask <<= 3;
13539                                 if (--i < 0)
13540                                         break;
13541                         }
13542                         *p = '\0';
13543                         puts(buf + 1);
13544                 } else {
13545                         out1fmt("%04o\n", mask);
13546                 }
13547         } else {
13548                 char *modestr = *argptr;
13549                 /* numeric umasks are taken as-is */
13550                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13551                 if (!isdigit(modestr[0]))
13552                         mask ^= 0777;
13553                 mask = bb_parse_mode(modestr, mask);
13554                 if ((unsigned)mask > 0777) {
13555                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13556                 }
13557                 if (!isdigit(modestr[0]))
13558                         mask ^= 0777;
13559                 umask(mask);
13560         }
13561         return 0;
13562 }
13563
13564 static int FAST_FUNC
13565 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13566 {
13567         return shell_builtin_ulimit(argv);
13568 }
13569
13570 /* ============ main() and helpers */
13571
13572 /*
13573  * Called to exit the shell.
13574  */
13575 static void
13576 exitshell(void)
13577 {
13578         struct jmploc loc;
13579         char *p;
13580         int status;
13581
13582 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13583         save_history(line_input_state);
13584 #endif
13585         status = exitstatus;
13586         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13587         if (setjmp(loc.loc)) {
13588                 if (exception_type == EXEXIT)
13589                         status = exitstatus;
13590                 goto out;
13591         }
13592         exception_handler = &loc;
13593         p = trap[0];
13594         if (p) {
13595                 trap[0] = NULL;
13596                 evalskip = 0;
13597                 evalstring(p, 0);
13598                 /*free(p); - we'll exit soon */
13599         }
13600  out:
13601         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13602          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13603          */
13604         setjobctl(0);
13605         flush_stdout_stderr();
13606         _exit(status);
13607         /* NOTREACHED */
13608 }
13609
13610 /* Don't inline: conserve stack of caller from having our locals too */
13611 static NOINLINE void
13612 init(void)
13613 {
13614         /* we will never free this */
13615         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13616         basepf.linno = 1;
13617
13618         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13619         setsignal(SIGCHLD);
13620
13621         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13622          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13623          */
13624         signal(SIGHUP, SIG_DFL);
13625
13626         {
13627                 char **envp;
13628                 const char *p;
13629
13630                 initvar();
13631                 for (envp = environ; envp && *envp; envp++) {
13632                         p = endofname(*envp);
13633                         if (p != *envp && *p == '=') {
13634                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13635                         }
13636                 }
13637
13638                 setvareq((char*)defoptindvar, VTEXTFIXED);
13639
13640                 setvar0("PPID", utoa(getppid()));
13641 #if BASH_SHLVL_VAR
13642                 p = lookupvar("SHLVL");
13643                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13644 #endif
13645 #if BASH_HOSTNAME_VAR
13646                 if (!lookupvar("HOSTNAME")) {
13647                         struct utsname uts;
13648                         uname(&uts);
13649                         setvar0("HOSTNAME", uts.nodename);
13650                 }
13651 #endif
13652                 p = lookupvar("PWD");
13653                 if (p) {
13654                         struct stat st1, st2;
13655                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13656                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13657                         ) {
13658                                 p = NULL;
13659                         }
13660                 }
13661                 setpwd(p, 0);
13662         }
13663 }
13664
13665
13666 //usage:#define ash_trivial_usage
13667 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13668 //usage:#define ash_full_usage "\n\n"
13669 //usage:        "Unix shell interpreter"
13670
13671 /*
13672  * Process the shell command line arguments.
13673  */
13674 static int
13675 procargs(char **argv)
13676 {
13677         int i;
13678         const char *xminusc;
13679         char **xargv;
13680         int login_sh;
13681
13682         xargv = argv;
13683         login_sh = xargv[0] && xargv[0][0] == '-';
13684         arg0 = xargv[0];
13685         /* if (xargv[0]) - mmm, this is always true! */
13686                 xargv++;
13687         for (i = 0; i < NOPTS; i++)
13688                 optlist[i] = 2;
13689         argptr = xargv;
13690         if (options(/*cmdline:*/ 1, &login_sh)) {
13691                 /* it already printed err message */
13692                 raise_exception(EXERROR);
13693         }
13694         xargv = argptr;
13695         xminusc = minusc;
13696         if (*xargv == NULL) {
13697                 if (xminusc)
13698                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13699                 sflag = 1;
13700         }
13701         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13702                 iflag = 1;
13703         if (mflag == 2)
13704                 mflag = iflag;
13705         for (i = 0; i < NOPTS; i++)
13706                 if (optlist[i] == 2)
13707                         optlist[i] = 0;
13708 #if DEBUG == 2
13709         debug = 1;
13710 #endif
13711         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13712         if (xminusc) {
13713                 minusc = *xargv++;
13714                 if (*xargv)
13715                         goto setarg0;
13716         } else if (!sflag) {
13717                 setinputfile(*xargv, 0);
13718  setarg0:
13719                 arg0 = *xargv++;
13720                 commandname = arg0;
13721         }
13722
13723         shellparam.p = xargv;
13724 #if ENABLE_ASH_GETOPTS
13725         shellparam.optind = 1;
13726         shellparam.optoff = -1;
13727 #endif
13728         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13729         while (*xargv) {
13730                 shellparam.nparam++;
13731                 xargv++;
13732         }
13733         optschanged();
13734
13735         return login_sh;
13736 }
13737
13738 /*
13739  * Read /etc/profile, ~/.profile, $ENV.
13740  */
13741 static void
13742 read_profile(const char *name)
13743 {
13744         name = expandstr(name, DQSYNTAX);
13745         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13746                 return;
13747         cmdloop(0);
13748         popfile();
13749 }
13750
13751 /*
13752  * This routine is called when an error or an interrupt occurs in an
13753  * interactive shell and control is returned to the main command loop.
13754  * (In dash, this function is auto-generated by build machinery).
13755  */
13756 static void
13757 reset(void)
13758 {
13759         /* from eval.c: */
13760         evalskip = 0;
13761         loopnest = 0;
13762
13763         /* from expand.c: */
13764         ifsfree();
13765
13766         /* from input.c: */
13767         g_parsefile->left_in_buffer = 0;
13768         g_parsefile->left_in_line = 0;      /* clear input buffer */
13769         popallfiles();
13770
13771         /* from redir.c: */
13772         unwindredir(NULL);
13773
13774         /* from var.c: */
13775         unwindlocalvars(NULL);
13776 }
13777
13778 #if PROFILE
13779 static short profile_buf[16384];
13780 extern int etext();
13781 #endif
13782
13783 /*
13784  * Main routine.  We initialize things, parse the arguments, execute
13785  * profiles if we're a login shell, and then call cmdloop to execute
13786  * commands.  The setjmp call sets up the location to jump to when an
13787  * exception occurs.  When an exception occurs the variable "state"
13788  * is used to figure out how far we had gotten.
13789  */
13790 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13791 int ash_main(int argc UNUSED_PARAM, char **argv)
13792 {
13793         volatile smallint state;
13794         struct jmploc jmploc;
13795         struct stackmark smark;
13796         int login_sh;
13797
13798         /* Initialize global data */
13799         INIT_G_misc();
13800         INIT_G_memstack();
13801         INIT_G_var();
13802 #if ENABLE_ASH_ALIAS
13803         INIT_G_alias();
13804 #endif
13805         INIT_G_cmdtable();
13806
13807 #if PROFILE
13808         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13809 #endif
13810
13811 #if ENABLE_FEATURE_EDITING
13812         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13813 #endif
13814         state = 0;
13815         if (setjmp(jmploc.loc)) {
13816                 smallint e;
13817                 smallint s;
13818
13819                 reset();
13820
13821                 e = exception_type;
13822                 s = state;
13823                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13824                         exitshell();
13825                 }
13826                 if (e == EXINT) {
13827                         newline_and_flush(stderr);
13828                 }
13829
13830                 popstackmark(&smark);
13831                 FORCE_INT_ON; /* enable interrupts */
13832                 if (s == 1)
13833                         goto state1;
13834                 if (s == 2)
13835                         goto state2;
13836                 if (s == 3)
13837                         goto state3;
13838                 goto state4;
13839         }
13840         exception_handler = &jmploc;
13841         rootpid = getpid();
13842
13843         init();
13844         setstackmark(&smark);
13845         login_sh = procargs(argv);
13846 #if DEBUG
13847         TRACE(("Shell args: "));
13848         trace_puts_args(argv);
13849 #endif
13850
13851         if (login_sh) {
13852                 const char *hp;
13853
13854                 state = 1;
13855                 read_profile("/etc/profile");
13856  state1:
13857                 state = 2;
13858                 hp = lookupvar("HOME");
13859                 if (hp)
13860                         read_profile("$HOME/.profile");
13861         }
13862  state2:
13863         state = 3;
13864         if (
13865 #ifndef linux
13866          getuid() == geteuid() && getgid() == getegid() &&
13867 #endif
13868          iflag
13869         ) {
13870                 const char *shinit = lookupvar("ENV");
13871                 if (shinit != NULL && *shinit != '\0')
13872                         read_profile(shinit);
13873         }
13874         popstackmark(&smark);
13875  state3:
13876         state = 4;
13877         if (minusc) {
13878                 /* evalstring pushes parsefile stack.
13879                  * Ensure we don't falsely claim that 0 (stdin)
13880                  * is one of stacked source fds.
13881                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13882                 // if (!sflag) g_parsefile->pf_fd = -1;
13883                 // ^^ not necessary since now we special-case fd 0
13884                 // in save_fd_on_redirect()
13885                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13886         }
13887
13888         if (sflag || minusc == NULL) {
13889 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13890                 if (iflag) {
13891                         const char *hp = lookupvar("HISTFILE");
13892                         if (!hp) {
13893                                 hp = lookupvar("HOME");
13894                                 if (hp) {
13895                                         INT_OFF;
13896                                         hp = concat_path_file(hp, ".ash_history");
13897                                         setvar0("HISTFILE", hp);
13898                                         free((char*)hp);
13899                                         INT_ON;
13900                                         hp = lookupvar("HISTFILE");
13901                                 }
13902                         }
13903                         if (hp)
13904                                 line_input_state->hist_file = hp;
13905 # if ENABLE_FEATURE_SH_HISTFILESIZE
13906                         hp = lookupvar("HISTFILESIZE");
13907                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13908 # endif
13909                 }
13910 #endif
13911  state4: /* XXX ??? - why isn't this before the "if" statement */
13912                 cmdloop(1);
13913         }
13914 #if PROFILE
13915         monitor(0);
13916 #endif
13917 #ifdef GPROF
13918         {
13919                 extern void _mcleanup(void);
13920                 _mcleanup();
13921         }
13922 #endif
13923         TRACE(("End of main reached\n"));
13924         exitshell();
13925         /* NOTREACHED */
13926 }
13927
13928
13929 /*-
13930  * Copyright (c) 1989, 1991, 1993, 1994
13931  *      The Regents of the University of California.  All rights reserved.
13932  *
13933  * This code is derived from software contributed to Berkeley by
13934  * Kenneth Almquist.
13935  *
13936  * Redistribution and use in source and binary forms, with or without
13937  * modification, are permitted provided that the following conditions
13938  * are met:
13939  * 1. Redistributions of source code must retain the above copyright
13940  *    notice, this list of conditions and the following disclaimer.
13941  * 2. Redistributions in binary form must reproduce the above copyright
13942  *    notice, this list of conditions and the following disclaimer in the
13943  *    documentation and/or other materials provided with the distribution.
13944  * 3. Neither the name of the University nor the names of its contributors
13945  *    may be used to endorse or promote products derived from this software
13946  *    without specific prior written permission.
13947  *
13948  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
13949  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13950  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13951  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13952  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13953  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13954  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13955  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13956  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13957  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13958  * SUCH DAMAGE.
13959  */