free,stat: make NOEXEC
[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
193 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
194 /* Bionic at least up to version 24 has no glob() */
195 # undef  ENABLE_ASH_INTERNAL_GLOB
196 # define ENABLE_ASH_INTERNAL_GLOB 1
197 #endif
198
199 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
200 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
201 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
202 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
203 # error glob() should unbackslash them and match. uClibc does not unbackslash,
204 # error fails to match dirname, subsequently not expanding <pattern> in it.
205 // Testcase:
206 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
207 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
208 #endif
209
210 #if !ENABLE_ASH_INTERNAL_GLOB
211 # include <glob.h>
212 #endif
213
214 #include "unicode.h"
215 #include "shell_common.h"
216 #if ENABLE_FEATURE_SH_MATH
217 # include "math.h"
218 #else
219 typedef long arith_t;
220 # define ARITH_FMT "%ld"
221 #endif
222 #if ENABLE_ASH_RANDOM_SUPPORT
223 # include "random.h"
224 #else
225 # define CLEAR_RANDOM_T(rnd) ((void)0)
226 #endif
227
228 #include "NUM_APPLETS.h"
229 #if NUM_APPLETS == 1
230 /* STANDALONE does not make sense, and won't compile */
231 # undef CONFIG_FEATURE_SH_STANDALONE
232 # undef ENABLE_FEATURE_SH_STANDALONE
233 # undef IF_FEATURE_SH_STANDALONE
234 # undef IF_NOT_FEATURE_SH_STANDALONE
235 # define ENABLE_FEATURE_SH_STANDALONE 0
236 # define IF_FEATURE_SH_STANDALONE(...)
237 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
238 #endif
239
240 #ifndef PIPE_BUF
241 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
242 #endif
243
244 #if !BB_MMU
245 # error "Do not even bother, ash will not run on NOMMU machine"
246 #endif
247
248
249 /* ============ Hash table sizes. Configurable. */
250
251 #define VTABSIZE 39
252 #define ATABSIZE 39
253 #define CMDTABLESIZE 31         /* should be prime */
254
255
256 /* ============ Shell options */
257
258 static const char *const optletters_optnames[] = {
259         "e"   "errexit",
260         "f"   "noglob",
261         "I"   "ignoreeof",
262         "i"   "interactive",
263         "m"   "monitor",
264         "n"   "noexec",
265         "s"   "stdin",
266         "x"   "xtrace",
267         "v"   "verbose",
268         "C"   "noclobber",
269         "a"   "allexport",
270         "b"   "notify",
271         "u"   "nounset",
272         "\0"  "vi"
273 #if BASH_PIPEFAIL
274         ,"\0"  "pipefail"
275 #endif
276 #if DEBUG
277         ,"\0"  "nolog"
278         ,"\0"  "debug"
279 #endif
280 };
281
282 #define optletters(n)  optletters_optnames[n][0]
283 #define optnames(n)   (optletters_optnames[n] + 1)
284
285 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
286
287
288 /* ============ Misc data */
289
290 #define msg_illnum "Illegal number: %s"
291
292 /*
293  * We enclose jmp_buf in a structure so that we can declare pointers to
294  * jump locations.  The global variable handler contains the location to
295  * jump to when an exception occurs, and the global variable exception_type
296  * contains a code identifying the exception.  To implement nested
297  * exception handlers, the user should save the value of handler on entry
298  * to an inner scope, set handler to point to a jmploc structure for the
299  * inner scope, and restore handler on exit from the scope.
300  */
301 struct jmploc {
302         jmp_buf loc;
303 };
304
305 struct globals_misc {
306         uint8_t exitstatus;     /* exit status of last command */
307         uint8_t back_exitstatus;/* exit status of backquoted command */
308         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
309         int rootpid;            /* pid of main shell */
310         /* shell level: 0 for the main shell, 1 for its children, and so on */
311         int shlvl;
312 #define rootshell (!shlvl)
313         char *minusc;  /* argument to -c option */
314
315         char *curdir; // = nullstr;     /* current working directory */
316         char *physdir; // = nullstr;    /* physical working directory */
317
318         char *arg0; /* value of $0 */
319
320         struct jmploc *exception_handler;
321
322         volatile int suppress_int; /* counter */
323         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
324         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
325         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
326         smallint exception_type; /* kind of exception (0..5) */
327         /* exceptions */
328 #define EXINT 0         /* SIGINT received */
329 #define EXERROR 1       /* a generic error */
330 #define EXEXIT 4        /* exit the shell */
331
332         char nullstr[1];        /* zero length string */
333
334         char optlist[NOPTS];
335 #define eflag optlist[0]
336 #define fflag optlist[1]
337 #define Iflag optlist[2]
338 #define iflag optlist[3]
339 #define mflag optlist[4]
340 #define nflag optlist[5]
341 #define sflag optlist[6]
342 #define xflag optlist[7]
343 #define vflag optlist[8]
344 #define Cflag optlist[9]
345 #define aflag optlist[10]
346 #define bflag optlist[11]
347 #define uflag optlist[12]
348 #define viflag optlist[13]
349 #if BASH_PIPEFAIL
350 # define pipefail optlist[14]
351 #else
352 # define pipefail 0
353 #endif
354 #if DEBUG
355 # define nolog optlist[14 + BASH_PIPEFAIL]
356 # define debug optlist[15 + BASH_PIPEFAIL]
357 #endif
358
359         /* trap handler commands */
360         /*
361          * Sigmode records the current value of the signal handlers for the various
362          * modes.  A value of zero means that the current handler is not known.
363          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
364          */
365         char sigmode[NSIG - 1];
366 #define S_DFL      1            /* default signal handling (SIG_DFL) */
367 #define S_CATCH    2            /* signal is caught */
368 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
369 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
370
371         /* indicates specified signal received */
372         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
373         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
374         char *trap[NSIG];
375         char **trap_ptr;        /* used only by "trap hack" */
376
377         /* Rarely referenced stuff */
378 #if ENABLE_ASH_RANDOM_SUPPORT
379         random_t random_gen;
380 #endif
381         pid_t backgndpid;        /* pid of last background process */
382 };
383 extern struct globals_misc *const ash_ptr_to_globals_misc;
384 #define G_misc (*ash_ptr_to_globals_misc)
385 #define exitstatus        (G_misc.exitstatus )
386 #define back_exitstatus   (G_misc.back_exitstatus )
387 #define job_warning       (G_misc.job_warning)
388 #define rootpid     (G_misc.rootpid    )
389 #define shlvl       (G_misc.shlvl      )
390 #define minusc      (G_misc.minusc     )
391 #define curdir      (G_misc.curdir     )
392 #define physdir     (G_misc.physdir    )
393 #define arg0        (G_misc.arg0       )
394 #define exception_handler (G_misc.exception_handler)
395 #define exception_type    (G_misc.exception_type   )
396 #define suppress_int      (G_misc.suppress_int     )
397 #define pending_int       (G_misc.pending_int      )
398 #define got_sigchld       (G_misc.got_sigchld      )
399 #define pending_sig       (G_misc.pending_sig      )
400 #define nullstr     (G_misc.nullstr    )
401 #define optlist     (G_misc.optlist    )
402 #define sigmode     (G_misc.sigmode    )
403 #define gotsig      (G_misc.gotsig     )
404 #define may_have_traps    (G_misc.may_have_traps   )
405 #define trap        (G_misc.trap       )
406 #define trap_ptr    (G_misc.trap_ptr   )
407 #define random_gen  (G_misc.random_gen )
408 #define backgndpid  (G_misc.backgndpid )
409 #define INIT_G_misc() do { \
410         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
411         barrier(); \
412         curdir = nullstr; \
413         physdir = nullstr; \
414         trap_ptr = trap; \
415 } while (0)
416
417
418 /* ============ DEBUG */
419 #if DEBUG
420 static void trace_printf(const char *fmt, ...);
421 static void trace_vprintf(const char *fmt, va_list va);
422 # define TRACE(param)    trace_printf param
423 # define TRACEV(param)   trace_vprintf param
424 # define close(fd) do { \
425         int dfd = (fd); \
426         if (close(dfd) < 0) \
427                 bb_error_msg("bug on %d: closing %d(0x%x)", \
428                         __LINE__, dfd, dfd); \
429 } while (0)
430 #else
431 # define TRACE(param)
432 # define TRACEV(param)
433 #endif
434
435
436 /* ============ Utility functions */
437 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
438 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
439
440 static int
441 isdigit_str9(const char *str)
442 {
443         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
444         while (--maxlen && isdigit(*str))
445                 str++;
446         return (*str == '\0');
447 }
448
449 static const char *
450 var_end(const char *var)
451 {
452         while (*var)
453                 if (*var++ == '=')
454                         break;
455         return var;
456 }
457
458
459 /* ============ Interrupts / exceptions */
460
461 static void exitshell(void) NORETURN;
462
463 /*
464  * These macros allow the user to suspend the handling of interrupt signals
465  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
466  * much more efficient and portable.  (But hacking the kernel is so much
467  * more fun than worrying about efficiency and portability. :-))
468  */
469 #if DEBUG_INTONOFF
470 # define INT_OFF do { \
471         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
472         suppress_int++; \
473         barrier(); \
474 } while (0)
475 #else
476 # define INT_OFF do { \
477         suppress_int++; \
478         barrier(); \
479 } while (0)
480 #endif
481
482 /*
483  * Called to raise an exception.  Since C doesn't include exceptions, we
484  * just do a longjmp to the exception handler.  The type of exception is
485  * stored in the global variable "exception_type".
486  */
487 static void raise_exception(int) NORETURN;
488 static void
489 raise_exception(int e)
490 {
491 #if DEBUG
492         if (exception_handler == NULL)
493                 abort();
494 #endif
495         INT_OFF;
496         exception_type = e;
497         longjmp(exception_handler->loc, 1);
498 }
499 #if DEBUG
500 #define raise_exception(e) do { \
501         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
502         raise_exception(e); \
503 } while (0)
504 #endif
505
506 /*
507  * Called when a SIGINT is received.  (If the user specifies
508  * that SIGINT is to be trapped or ignored using the trap builtin, then
509  * this routine is not called.)  Suppressint is nonzero when interrupts
510  * are held using the INT_OFF macro.  (The test for iflag is just
511  * defensive programming.)
512  */
513 static void raise_interrupt(void) NORETURN;
514 static void
515 raise_interrupt(void)
516 {
517         pending_int = 0;
518         /* Signal is not automatically unmasked after it is raised,
519          * do it ourself - unmask all signals */
520         sigprocmask_allsigs(SIG_UNBLOCK);
521         /* pending_sig = 0; - now done in signal_handler() */
522
523         if (!(rootshell && iflag)) {
524                 /* Kill ourself with SIGINT */
525                 signal(SIGINT, SIG_DFL);
526                 raise(SIGINT);
527         }
528         /* bash: ^C even on empty command line sets $? */
529         exitstatus = SIGINT + 128;
530         raise_exception(EXINT);
531         /* NOTREACHED */
532 }
533 #if DEBUG
534 #define raise_interrupt() do { \
535         TRACE(("raising interrupt on line %d\n", __LINE__)); \
536         raise_interrupt(); \
537 } while (0)
538 #endif
539
540 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
541 int_on(void)
542 {
543         barrier();
544         if (--suppress_int == 0 && pending_int) {
545                 raise_interrupt();
546         }
547 }
548 #if DEBUG_INTONOFF
549 # define INT_ON do { \
550         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
551         int_on(); \
552 } while (0)
553 #else
554 # define INT_ON int_on()
555 #endif
556 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
557 force_int_on(void)
558 {
559         barrier();
560         suppress_int = 0;
561         if (pending_int)
562                 raise_interrupt();
563 }
564 #define FORCE_INT_ON force_int_on()
565
566 #define SAVE_INT(v) ((v) = suppress_int)
567
568 #define RESTORE_INT(v) do { \
569         barrier(); \
570         suppress_int = (v); \
571         if (suppress_int == 0 && pending_int) \
572                 raise_interrupt(); \
573 } while (0)
574
575
576 /* ============ Stdout/stderr output */
577
578 static void
579 outstr(const char *p, FILE *file)
580 {
581         INT_OFF;
582         fputs(p, file);
583         INT_ON;
584 }
585
586 static void
587 flush_stdout_stderr(void)
588 {
589         INT_OFF;
590         fflush_all();
591         INT_ON;
592 }
593
594 /* Was called outcslow(c,FILE*), but c was always '\n' */
595 static void
596 newline_and_flush(FILE *dest)
597 {
598         INT_OFF;
599         putc('\n', dest);
600         fflush(dest);
601         INT_ON;
602 }
603
604 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
605 static int
606 out1fmt(const char *fmt, ...)
607 {
608         va_list ap;
609         int r;
610
611         INT_OFF;
612         va_start(ap, fmt);
613         r = vprintf(fmt, ap);
614         va_end(ap);
615         INT_ON;
616         return r;
617 }
618
619 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
620 static int
621 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
622 {
623         va_list ap;
624         int ret;
625
626         INT_OFF;
627         va_start(ap, fmt);
628         ret = vsnprintf(outbuf, length, fmt, ap);
629         va_end(ap);
630         INT_ON;
631         return ret;
632 }
633
634 static void
635 out1str(const char *p)
636 {
637         outstr(p, stdout);
638 }
639
640 static void
641 out2str(const char *p)
642 {
643         outstr(p, stderr);
644         flush_stdout_stderr();
645 }
646
647
648 /* ============ Parser structures */
649
650 /* control characters in argument strings */
651 #define CTL_FIRST CTLESC
652 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
653 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
654 #define CTLENDVAR    ((unsigned char)'\203')
655 #define CTLBACKQ     ((unsigned char)'\204')
656 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
657 #define CTLENDARI    ((unsigned char)'\207')
658 #define CTLQUOTEMARK ((unsigned char)'\210')
659 #define CTL_LAST CTLQUOTEMARK
660
661 /* variable substitution byte (follows CTLVAR) */
662 #define VSTYPE  0x0f            /* type of variable substitution */
663 #define VSNUL   0x10            /* colon--treat the empty string as unset */
664
665 /* values of VSTYPE field */
666 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
667 #define VSMINUS         0x2     /* ${var-text} */
668 #define VSPLUS          0x3     /* ${var+text} */
669 #define VSQUESTION      0x4     /* ${var?message} */
670 #define VSASSIGN        0x5     /* ${var=text} */
671 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
672 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
673 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
674 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
675 #define VSLENGTH        0xa     /* ${#var} */
676 #if BASH_SUBSTR
677 #define VSSUBSTR        0xc     /* ${var:position:length} */
678 #endif
679 #if BASH_PATTERN_SUBST
680 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
681 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
682 #endif
683
684 static const char dolatstr[] ALIGN1 = {
685         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
686 };
687 #define DOLATSTRLEN 6
688
689 #define NCMD      0
690 #define NPIPE     1
691 #define NREDIR    2
692 #define NBACKGND  3
693 #define NSUBSHELL 4
694 #define NAND      5
695 #define NOR       6
696 #define NSEMI     7
697 #define NIF       8
698 #define NWHILE    9
699 #define NUNTIL   10
700 #define NFOR     11
701 #define NCASE    12
702 #define NCLIST   13
703 #define NDEFUN   14
704 #define NARG     15
705 #define NTO      16
706 #if BASH_REDIR_OUTPUT
707 #define NTO2     17
708 #endif
709 #define NCLOBBER 18
710 #define NFROM    19
711 #define NFROMTO  20
712 #define NAPPEND  21
713 #define NTOFD    22
714 #define NFROMFD  23
715 #define NHERE    24
716 #define NXHERE   25
717 #define NNOT     26
718 #define N_NUMBER 27
719
720 union node;
721
722 struct ncmd {
723         smallint type; /* Nxxxx */
724         union node *assign;
725         union node *args;
726         union node *redirect;
727 };
728
729 struct npipe {
730         smallint type;
731         smallint pipe_backgnd;
732         struct nodelist *cmdlist;
733 };
734
735 struct nredir {
736         smallint type;
737         union node *n;
738         union node *redirect;
739 };
740
741 struct nbinary {
742         smallint type;
743         union node *ch1;
744         union node *ch2;
745 };
746
747 struct nif {
748         smallint type;
749         union node *test;
750         union node *ifpart;
751         union node *elsepart;
752 };
753
754 struct nfor {
755         smallint type;
756         union node *args;
757         union node *body;
758         char *var;
759 };
760
761 struct ncase {
762         smallint type;
763         union node *expr;
764         union node *cases;
765 };
766
767 struct nclist {
768         smallint type;
769         union node *next;
770         union node *pattern;
771         union node *body;
772 };
773
774 struct narg {
775         smallint type;
776         union node *next;
777         char *text;
778         struct nodelist *backquote;
779 };
780
781 /* nfile and ndup layout must match!
782  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
783  * that it is actually NTO2 (>&file), and change its type.
784  */
785 struct nfile {
786         smallint type;
787         union node *next;
788         int fd;
789         int _unused_dupfd;
790         union node *fname;
791         char *expfname;
792 };
793
794 struct ndup {
795         smallint type;
796         union node *next;
797         int fd;
798         int dupfd;
799         union node *vname;
800         char *_unused_expfname;
801 };
802
803 struct nhere {
804         smallint type;
805         union node *next;
806         int fd;
807         union node *doc;
808 };
809
810 struct nnot {
811         smallint type;
812         union node *com;
813 };
814
815 union node {
816         smallint type;
817         struct ncmd ncmd;
818         struct npipe npipe;
819         struct nredir nredir;
820         struct nbinary nbinary;
821         struct nif nif;
822         struct nfor nfor;
823         struct ncase ncase;
824         struct nclist nclist;
825         struct narg narg;
826         struct nfile nfile;
827         struct ndup ndup;
828         struct nhere nhere;
829         struct nnot nnot;
830 };
831
832 /*
833  * NODE_EOF is returned by parsecmd when it encounters an end of file.
834  * It must be distinct from NULL.
835  */
836 #define NODE_EOF ((union node *) -1L)
837
838 struct nodelist {
839         struct nodelist *next;
840         union node *n;
841 };
842
843 struct funcnode {
844         int count;
845         union node n;
846 };
847
848 /*
849  * Free a parse tree.
850  */
851 static void
852 freefunc(struct funcnode *f)
853 {
854         if (f && --f->count < 0)
855                 free(f);
856 }
857
858
859 /* ============ Debugging output */
860
861 #if DEBUG
862
863 static FILE *tracefile;
864
865 static void
866 trace_printf(const char *fmt, ...)
867 {
868         va_list va;
869
870         if (debug != 1)
871                 return;
872         if (DEBUG_TIME)
873                 fprintf(tracefile, "%u ", (int) time(NULL));
874         if (DEBUG_PID)
875                 fprintf(tracefile, "[%u] ", (int) getpid());
876         if (DEBUG_SIG)
877                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
878         va_start(va, fmt);
879         vfprintf(tracefile, fmt, va);
880         va_end(va);
881 }
882
883 static void
884 trace_vprintf(const char *fmt, va_list va)
885 {
886         if (debug != 1)
887                 return;
888         vfprintf(tracefile, fmt, va);
889         fprintf(tracefile, "\n");
890 }
891
892 static void
893 trace_puts(const char *s)
894 {
895         if (debug != 1)
896                 return;
897         fputs(s, tracefile);
898 }
899
900 static void
901 trace_puts_quoted(char *s)
902 {
903         char *p;
904         char c;
905
906         if (debug != 1)
907                 return;
908         putc('"', tracefile);
909         for (p = s; *p; p++) {
910                 switch ((unsigned char)*p) {
911                 case '\n': c = 'n'; goto backslash;
912                 case '\t': c = 't'; goto backslash;
913                 case '\r': c = 'r'; goto backslash;
914                 case '\"': c = '\"'; goto backslash;
915                 case '\\': c = '\\'; goto backslash;
916                 case CTLESC: c = 'e'; goto backslash;
917                 case CTLVAR: c = 'v'; goto backslash;
918                 case CTLBACKQ: c = 'q'; goto backslash;
919  backslash:
920                         putc('\\', tracefile);
921                         putc(c, tracefile);
922                         break;
923                 default:
924                         if (*p >= ' ' && *p <= '~')
925                                 putc(*p, tracefile);
926                         else {
927                                 putc('\\', tracefile);
928                                 putc((*p >> 6) & 03, tracefile);
929                                 putc((*p >> 3) & 07, tracefile);
930                                 putc(*p & 07, tracefile);
931                         }
932                         break;
933                 }
934         }
935         putc('"', tracefile);
936 }
937
938 static void
939 trace_puts_args(char **ap)
940 {
941         if (debug != 1)
942                 return;
943         if (!*ap)
944                 return;
945         while (1) {
946                 trace_puts_quoted(*ap);
947                 if (!*++ap) {
948                         putc('\n', tracefile);
949                         break;
950                 }
951                 putc(' ', tracefile);
952         }
953 }
954
955 static void
956 opentrace(void)
957 {
958         char s[100];
959 #ifdef O_APPEND
960         int flags;
961 #endif
962
963         if (debug != 1) {
964                 if (tracefile)
965                         fflush(tracefile);
966                 /* leave open because libedit might be using it */
967                 return;
968         }
969         strcpy(s, "./trace");
970         if (tracefile) {
971                 if (!freopen(s, "a", tracefile)) {
972                         fprintf(stderr, "Can't re-open %s\n", s);
973                         debug = 0;
974                         return;
975                 }
976         } else {
977                 tracefile = fopen(s, "a");
978                 if (tracefile == NULL) {
979                         fprintf(stderr, "Can't open %s\n", s);
980                         debug = 0;
981                         return;
982                 }
983         }
984 #ifdef O_APPEND
985         flags = fcntl(fileno(tracefile), F_GETFL);
986         if (flags >= 0)
987                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
988 #endif
989         setlinebuf(tracefile);
990         fputs("\nTracing started.\n", tracefile);
991 }
992
993 static void
994 indent(int amount, char *pfx, FILE *fp)
995 {
996         int i;
997
998         for (i = 0; i < amount; i++) {
999                 if (pfx && i == amount - 1)
1000                         fputs(pfx, fp);
1001                 putc('\t', fp);
1002         }
1003 }
1004
1005 /* little circular references here... */
1006 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1007
1008 static void
1009 sharg(union node *arg, FILE *fp)
1010 {
1011         char *p;
1012         struct nodelist *bqlist;
1013         unsigned char subtype;
1014
1015         if (arg->type != NARG) {
1016                 out1fmt("<node type %d>\n", arg->type);
1017                 abort();
1018         }
1019         bqlist = arg->narg.backquote;
1020         for (p = arg->narg.text; *p; p++) {
1021                 switch ((unsigned char)*p) {
1022                 case CTLESC:
1023                         p++;
1024                         putc(*p, fp);
1025                         break;
1026                 case CTLVAR:
1027                         putc('$', fp);
1028                         putc('{', fp);
1029                         subtype = *++p;
1030                         if (subtype == VSLENGTH)
1031                                 putc('#', fp);
1032
1033                         while (*p != '=') {
1034                                 putc(*p, fp);
1035                                 p++;
1036                         }
1037
1038                         if (subtype & VSNUL)
1039                                 putc(':', fp);
1040
1041                         switch (subtype & VSTYPE) {
1042                         case VSNORMAL:
1043                                 putc('}', fp);
1044                                 break;
1045                         case VSMINUS:
1046                                 putc('-', fp);
1047                                 break;
1048                         case VSPLUS:
1049                                 putc('+', fp);
1050                                 break;
1051                         case VSQUESTION:
1052                                 putc('?', fp);
1053                                 break;
1054                         case VSASSIGN:
1055                                 putc('=', fp);
1056                                 break;
1057                         case VSTRIMLEFT:
1058                                 putc('#', fp);
1059                                 break;
1060                         case VSTRIMLEFTMAX:
1061                                 putc('#', fp);
1062                                 putc('#', fp);
1063                                 break;
1064                         case VSTRIMRIGHT:
1065                                 putc('%', fp);
1066                                 break;
1067                         case VSTRIMRIGHTMAX:
1068                                 putc('%', fp);
1069                                 putc('%', fp);
1070                                 break;
1071                         case VSLENGTH:
1072                                 break;
1073                         default:
1074                                 out1fmt("<subtype %d>", subtype);
1075                         }
1076                         break;
1077                 case CTLENDVAR:
1078                         putc('}', fp);
1079                         break;
1080                 case CTLBACKQ:
1081                         putc('$', fp);
1082                         putc('(', fp);
1083                         shtree(bqlist->n, -1, NULL, fp);
1084                         putc(')', fp);
1085                         break;
1086                 default:
1087                         putc(*p, fp);
1088                         break;
1089                 }
1090         }
1091 }
1092
1093 static void
1094 shcmd(union node *cmd, FILE *fp)
1095 {
1096         union node *np;
1097         int first;
1098         const char *s;
1099         int dftfd;
1100
1101         first = 1;
1102         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1103                 if (!first)
1104                         putc(' ', fp);
1105                 sharg(np, fp);
1106                 first = 0;
1107         }
1108         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1109                 if (!first)
1110                         putc(' ', fp);
1111                 dftfd = 0;
1112                 switch (np->nfile.type) {
1113                 case NTO:      s = ">>"+1; dftfd = 1; break;
1114                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1115                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1116 #if BASH_REDIR_OUTPUT
1117                 case NTO2:
1118 #endif
1119                 case NTOFD:    s = ">&"; dftfd = 1; break;
1120                 case NFROM:    s = "<"; break;
1121                 case NFROMFD:  s = "<&"; break;
1122                 case NFROMTO:  s = "<>"; break;
1123                 default:       s = "*error*"; break;
1124                 }
1125                 if (np->nfile.fd != dftfd)
1126                         fprintf(fp, "%d", np->nfile.fd);
1127                 fputs(s, fp);
1128                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1129                         fprintf(fp, "%d", np->ndup.dupfd);
1130                 } else {
1131                         sharg(np->nfile.fname, fp);
1132                 }
1133                 first = 0;
1134         }
1135 }
1136
1137 static void
1138 shtree(union node *n, int ind, char *pfx, FILE *fp)
1139 {
1140         struct nodelist *lp;
1141         const char *s;
1142
1143         if (n == NULL)
1144                 return;
1145
1146         indent(ind, pfx, fp);
1147
1148         if (n == NODE_EOF) {
1149                 fputs("<EOF>", fp);
1150                 return;
1151         }
1152
1153         switch (n->type) {
1154         case NSEMI:
1155                 s = "; ";
1156                 goto binop;
1157         case NAND:
1158                 s = " && ";
1159                 goto binop;
1160         case NOR:
1161                 s = " || ";
1162  binop:
1163                 shtree(n->nbinary.ch1, ind, NULL, fp);
1164                 /* if (ind < 0) */
1165                         fputs(s, fp);
1166                 shtree(n->nbinary.ch2, ind, NULL, fp);
1167                 break;
1168         case NCMD:
1169                 shcmd(n, fp);
1170                 if (ind >= 0)
1171                         putc('\n', fp);
1172                 break;
1173         case NPIPE:
1174                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1175                         shtree(lp->n, 0, NULL, fp);
1176                         if (lp->next)
1177                                 fputs(" | ", fp);
1178                 }
1179                 if (n->npipe.pipe_backgnd)
1180                         fputs(" &", fp);
1181                 if (ind >= 0)
1182                         putc('\n', fp);
1183                 break;
1184         default:
1185                 fprintf(fp, "<node type %d>", n->type);
1186                 if (ind >= 0)
1187                         putc('\n', fp);
1188                 break;
1189         }
1190 }
1191
1192 static void
1193 showtree(union node *n)
1194 {
1195         trace_puts("showtree called\n");
1196         shtree(n, 1, NULL, stderr);
1197 }
1198
1199 #endif /* DEBUG */
1200
1201
1202 /* ============ Parser data */
1203
1204 /*
1205  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1206  */
1207 struct strlist {
1208         struct strlist *next;
1209         char *text;
1210 };
1211
1212 struct alias;
1213
1214 struct strpush {
1215         struct strpush *prev;   /* preceding string on stack */
1216         char *prev_string;
1217         int prev_left_in_line;
1218 #if ENABLE_ASH_ALIAS
1219         struct alias *ap;       /* if push was associated with an alias */
1220 #endif
1221         char *string;           /* remember the string since it may change */
1222
1223         /* Remember last two characters for pungetc. */
1224         int lastc[2];
1225
1226         /* Number of outstanding calls to pungetc. */
1227         int unget;
1228 };
1229
1230 struct parsefile {
1231         struct parsefile *prev; /* preceding file on stack */
1232         int linno;              /* current line */
1233         int pf_fd;              /* file descriptor (or -1 if string) */
1234         int left_in_line;       /* number of chars left in this line */
1235         int left_in_buffer;     /* number of chars left in this buffer past the line */
1236         char *next_to_pgetc;    /* next char in buffer */
1237         char *buf;              /* input buffer */
1238         struct strpush *strpush; /* for pushing strings at this level */
1239         struct strpush basestrpush; /* so pushing one is fast */
1240
1241         /* Remember last two characters for pungetc. */
1242         int lastc[2];
1243
1244         /* Number of outstanding calls to pungetc. */
1245         int unget;
1246 };
1247
1248 static struct parsefile basepf;        /* top level input file */
1249 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1250 static int startlinno;                 /* line # where last token started */
1251 static char *commandname;              /* currently executing command */
1252
1253
1254 /* ============ Message printing */
1255
1256 static void
1257 ash_vmsg(const char *msg, va_list ap)
1258 {
1259         fprintf(stderr, "%s: ", arg0);
1260         if (commandname) {
1261                 if (strcmp(arg0, commandname))
1262                         fprintf(stderr, "%s: ", commandname);
1263                 if (!iflag || g_parsefile->pf_fd > 0)
1264                         fprintf(stderr, "line %d: ", startlinno);
1265         }
1266         vfprintf(stderr, msg, ap);
1267         newline_and_flush(stderr);
1268 }
1269
1270 /*
1271  * Exverror is called to raise the error exception.  If the second argument
1272  * is not NULL then error prints an error message using printf style
1273  * formatting.  It then raises the error exception.
1274  */
1275 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1276 static void
1277 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1278 {
1279 #if DEBUG
1280         if (msg) {
1281                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1282                 TRACEV((msg, ap));
1283         } else
1284                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1285         if (msg)
1286 #endif
1287                 ash_vmsg(msg, ap);
1288
1289         flush_stdout_stderr();
1290         raise_exception(cond);
1291         /* NOTREACHED */
1292 }
1293
1294 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1295 static void
1296 ash_msg_and_raise_error(const char *msg, ...)
1297 {
1298         va_list ap;
1299
1300         exitstatus = 2;
1301
1302         va_start(ap, msg);
1303         ash_vmsg_and_raise(EXERROR, msg, ap);
1304         /* NOTREACHED */
1305         va_end(ap);
1306 }
1307
1308 /*
1309  * Use '%m' to append error string on platforms that support it, '%s' and
1310  * strerror() on those that don't.
1311  *
1312  * 'fmt' must be a string literal.
1313  */
1314 #ifdef HAVE_PRINTF_PERCENTM
1315 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1316 #else
1317 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1318 #endif
1319
1320 static void raise_error_syntax(const char *) NORETURN;
1321 static void
1322 raise_error_syntax(const char *msg)
1323 {
1324         ash_msg_and_raise_error("syntax error: %s", msg);
1325         /* NOTREACHED */
1326 }
1327
1328 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1329 static void
1330 ash_msg_and_raise(int cond, const char *msg, ...)
1331 {
1332         va_list ap;
1333
1334         va_start(ap, msg);
1335         ash_vmsg_and_raise(cond, msg, ap);
1336         /* NOTREACHED */
1337         va_end(ap);
1338 }
1339
1340 /*
1341  * error/warning routines for external builtins
1342  */
1343 static void
1344 ash_msg(const char *fmt, ...)
1345 {
1346         va_list ap;
1347
1348         va_start(ap, fmt);
1349         ash_vmsg(fmt, ap);
1350         va_end(ap);
1351 }
1352
1353 /*
1354  * Return a string describing an error.  The returned string may be a
1355  * pointer to a static buffer that will be overwritten on the next call.
1356  * Action describes the operation that got the error.
1357  */
1358 static const char *
1359 errmsg(int e, const char *em)
1360 {
1361         if (e == ENOENT || e == ENOTDIR) {
1362                 return em;
1363         }
1364         return strerror(e);
1365 }
1366
1367
1368 /* ============ Memory allocation */
1369
1370 #if 0
1371 /* I consider these wrappers nearly useless:
1372  * ok, they return you to nearest exception handler, but
1373  * how much memory do you leak in the process, making
1374  * memory starvation worse?
1375  */
1376 static void *
1377 ckrealloc(void * p, size_t nbytes)
1378 {
1379         p = realloc(p, nbytes);
1380         if (!p)
1381                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1382         return p;
1383 }
1384
1385 static void *
1386 ckmalloc(size_t nbytes)
1387 {
1388         return ckrealloc(NULL, nbytes);
1389 }
1390
1391 static void *
1392 ckzalloc(size_t nbytes)
1393 {
1394         return memset(ckmalloc(nbytes), 0, nbytes);
1395 }
1396
1397 static char *
1398 ckstrdup(const char *s)
1399 {
1400         char *p = strdup(s);
1401         if (!p)
1402                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1403         return p;
1404 }
1405 #else
1406 /* Using bbox equivalents. They exit if out of memory */
1407 # define ckrealloc xrealloc
1408 # define ckmalloc  xmalloc
1409 # define ckzalloc  xzalloc
1410 # define ckstrdup  xstrdup
1411 #endif
1412
1413 /*
1414  * It appears that grabstackstr() will barf with such alignments
1415  * because stalloc() will return a string allocated in a new stackblock.
1416  */
1417 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1418 enum {
1419         /* Most machines require the value returned from malloc to be aligned
1420          * in some way.  The following macro will get this right
1421          * on many machines.  */
1422         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1423         /* Minimum size of a block */
1424         MINSIZE = SHELL_ALIGN(504),
1425 };
1426
1427 struct stack_block {
1428         struct stack_block *prev;
1429         char space[MINSIZE];
1430 };
1431
1432 struct stackmark {
1433         struct stack_block *stackp;
1434         char *stacknxt;
1435         size_t stacknleft;
1436 };
1437
1438
1439 struct globals_memstack {
1440         struct stack_block *g_stackp; // = &stackbase;
1441         char *g_stacknxt; // = stackbase.space;
1442         char *sstrend; // = stackbase.space + MINSIZE;
1443         size_t g_stacknleft; // = MINSIZE;
1444         struct stack_block stackbase;
1445 };
1446 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1447 #define G_memstack (*ash_ptr_to_globals_memstack)
1448 #define g_stackp     (G_memstack.g_stackp    )
1449 #define g_stacknxt   (G_memstack.g_stacknxt  )
1450 #define sstrend      (G_memstack.sstrend     )
1451 #define g_stacknleft (G_memstack.g_stacknleft)
1452 #define stackbase    (G_memstack.stackbase   )
1453 #define INIT_G_memstack() do { \
1454         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1455         barrier(); \
1456         g_stackp = &stackbase; \
1457         g_stacknxt = stackbase.space; \
1458         g_stacknleft = MINSIZE; \
1459         sstrend = stackbase.space + MINSIZE; \
1460 } while (0)
1461
1462
1463 #define stackblock()     ((void *)g_stacknxt)
1464 #define stackblocksize() g_stacknleft
1465
1466 /*
1467  * Parse trees for commands are allocated in lifo order, so we use a stack
1468  * to make this more efficient, and also to avoid all sorts of exception
1469  * handling code to handle interrupts in the middle of a parse.
1470  *
1471  * The size 504 was chosen because the Ultrix malloc handles that size
1472  * well.
1473  */
1474 static void *
1475 stalloc(size_t nbytes)
1476 {
1477         char *p;
1478         size_t aligned;
1479
1480         aligned = SHELL_ALIGN(nbytes);
1481         if (aligned > g_stacknleft) {
1482                 size_t len;
1483                 size_t blocksize;
1484                 struct stack_block *sp;
1485
1486                 blocksize = aligned;
1487                 if (blocksize < MINSIZE)
1488                         blocksize = MINSIZE;
1489                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1490                 if (len < blocksize)
1491                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1492                 INT_OFF;
1493                 sp = ckmalloc(len);
1494                 sp->prev = g_stackp;
1495                 g_stacknxt = sp->space;
1496                 g_stacknleft = blocksize;
1497                 sstrend = g_stacknxt + blocksize;
1498                 g_stackp = sp;
1499                 INT_ON;
1500         }
1501         p = g_stacknxt;
1502         g_stacknxt += aligned;
1503         g_stacknleft -= aligned;
1504         return p;
1505 }
1506
1507 static void *
1508 stzalloc(size_t nbytes)
1509 {
1510         return memset(stalloc(nbytes), 0, nbytes);
1511 }
1512
1513 static void
1514 stunalloc(void *p)
1515 {
1516 #if DEBUG
1517         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1518                 write(STDERR_FILENO, "stunalloc\n", 10);
1519                 abort();
1520         }
1521 #endif
1522         g_stacknleft += g_stacknxt - (char *)p;
1523         g_stacknxt = p;
1524 }
1525
1526 /*
1527  * Like strdup but works with the ash stack.
1528  */
1529 static char *
1530 sstrdup(const char *p)
1531 {
1532         size_t len = strlen(p) + 1;
1533         return memcpy(stalloc(len), p, len);
1534 }
1535
1536 static inline void
1537 grabstackblock(size_t len)
1538 {
1539         stalloc(len);
1540 }
1541
1542 static void
1543 pushstackmark(struct stackmark *mark, size_t len)
1544 {
1545         mark->stackp = g_stackp;
1546         mark->stacknxt = g_stacknxt;
1547         mark->stacknleft = g_stacknleft;
1548         grabstackblock(len);
1549 }
1550
1551 static void
1552 setstackmark(struct stackmark *mark)
1553 {
1554         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1555 }
1556
1557 static void
1558 popstackmark(struct stackmark *mark)
1559 {
1560         struct stack_block *sp;
1561
1562         if (!mark->stackp)
1563                 return;
1564
1565         INT_OFF;
1566         while (g_stackp != mark->stackp) {
1567                 sp = g_stackp;
1568                 g_stackp = sp->prev;
1569                 free(sp);
1570         }
1571         g_stacknxt = mark->stacknxt;
1572         g_stacknleft = mark->stacknleft;
1573         sstrend = mark->stacknxt + mark->stacknleft;
1574         INT_ON;
1575 }
1576
1577 /*
1578  * When the parser reads in a string, it wants to stick the string on the
1579  * stack and only adjust the stack pointer when it knows how big the
1580  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1581  * of space on top of the stack and stackblocklen returns the length of
1582  * this block.  Growstackblock will grow this space by at least one byte,
1583  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1584  * part of the block that has been used.
1585  */
1586 static void
1587 growstackblock(void)
1588 {
1589         size_t newlen;
1590
1591         newlen = g_stacknleft * 2;
1592         if (newlen < g_stacknleft)
1593                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1594         if (newlen < 128)
1595                 newlen += 128;
1596
1597         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1598                 struct stack_block *sp;
1599                 struct stack_block *prevstackp;
1600                 size_t grosslen;
1601
1602                 INT_OFF;
1603                 sp = g_stackp;
1604                 prevstackp = sp->prev;
1605                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1606                 sp = ckrealloc(sp, grosslen);
1607                 sp->prev = prevstackp;
1608                 g_stackp = sp;
1609                 g_stacknxt = sp->space;
1610                 g_stacknleft = newlen;
1611                 sstrend = sp->space + newlen;
1612                 INT_ON;
1613         } else {
1614                 char *oldspace = g_stacknxt;
1615                 size_t oldlen = g_stacknleft;
1616                 char *p = stalloc(newlen);
1617
1618                 /* free the space we just allocated */
1619                 g_stacknxt = memcpy(p, oldspace, oldlen);
1620                 g_stacknleft += newlen;
1621         }
1622 }
1623
1624 /*
1625  * The following routines are somewhat easier to use than the above.
1626  * The user declares a variable of type STACKSTR, which may be declared
1627  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1628  * the user uses the macro STPUTC to add characters to the string.  In
1629  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1630  * grown as necessary.  When the user is done, she can just leave the
1631  * string there and refer to it using stackblock().  Or she can allocate
1632  * the space for it using grabstackstr().  If it is necessary to allow
1633  * someone else to use the stack temporarily and then continue to grow
1634  * the string, the user should use grabstack to allocate the space, and
1635  * then call ungrabstr(p) to return to the previous mode of operation.
1636  *
1637  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1638  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1639  * is space for at least one character.
1640  */
1641 static void *
1642 growstackstr(void)
1643 {
1644         size_t len = stackblocksize();
1645         growstackblock();
1646         return (char *)stackblock() + len;
1647 }
1648
1649 /*
1650  * Called from CHECKSTRSPACE.
1651  */
1652 static char *
1653 makestrspace(size_t newlen, char *p)
1654 {
1655         size_t len = p - g_stacknxt;
1656         size_t size;
1657
1658         for (;;) {
1659                 size_t nleft;
1660
1661                 size = stackblocksize();
1662                 nleft = size - len;
1663                 if (nleft >= newlen)
1664                         break;
1665                 growstackblock();
1666         }
1667         return (char *)stackblock() + len;
1668 }
1669
1670 static char *
1671 stack_nputstr(const char *s, size_t n, char *p)
1672 {
1673         p = makestrspace(n, p);
1674         p = (char *)mempcpy(p, s, n);
1675         return p;
1676 }
1677
1678 static char *
1679 stack_putstr(const char *s, char *p)
1680 {
1681         return stack_nputstr(s, strlen(s), p);
1682 }
1683
1684 static char *
1685 _STPUTC(int c, char *p)
1686 {
1687         if (p == sstrend)
1688                 p = growstackstr();
1689         *p++ = c;
1690         return p;
1691 }
1692
1693 #define STARTSTACKSTR(p)        ((p) = stackblock())
1694 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1695 #define CHECKSTRSPACE(n, p) do { \
1696         char *q = (p); \
1697         size_t l = (n); \
1698         size_t m = sstrend - q; \
1699         if (l > m) \
1700                 (p) = makestrspace(l, q); \
1701 } while (0)
1702 #define USTPUTC(c, p)           (*(p)++ = (c))
1703 #define STACKSTRNUL(p) do { \
1704         if ((p) == sstrend) \
1705                 (p) = growstackstr(); \
1706         *(p) = '\0'; \
1707 } while (0)
1708 #define STUNPUTC(p)             (--(p))
1709 #define STTOPC(p)               ((p)[-1])
1710 #define STADJUST(amount, p)     ((p) += (amount))
1711
1712 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1713 #define ungrabstackstr(s, p)    stunalloc(s)
1714 #define stackstrend()           ((void *)sstrend)
1715
1716
1717 /* ============ String helpers */
1718
1719 /*
1720  * prefix -- see if pfx is a prefix of string.
1721  */
1722 static char *
1723 prefix(const char *string, const char *pfx)
1724 {
1725         while (*pfx) {
1726                 if (*pfx++ != *string++)
1727                         return NULL;
1728         }
1729         return (char *) string;
1730 }
1731
1732 /*
1733  * Check for a valid number.  This should be elsewhere.
1734  */
1735 static int
1736 is_number(const char *p)
1737 {
1738         do {
1739                 if (!isdigit(*p))
1740                         return 0;
1741         } while (*++p != '\0');
1742         return 1;
1743 }
1744
1745 /*
1746  * Convert a string of digits to an integer, printing an error message on
1747  * failure.
1748  */
1749 static int
1750 number(const char *s)
1751 {
1752         if (!is_number(s))
1753                 ash_msg_and_raise_error(msg_illnum, s);
1754         return atoi(s);
1755 }
1756
1757 /*
1758  * Produce a single quoted string suitable as input to the shell.
1759  * The return string is allocated on the stack.
1760  */
1761 static char *
1762 single_quote(const char *s)
1763 {
1764         char *p;
1765
1766         STARTSTACKSTR(p);
1767
1768         do {
1769                 char *q;
1770                 size_t len;
1771
1772                 len = strchrnul(s, '\'') - s;
1773
1774                 q = p = makestrspace(len + 3, p);
1775
1776                 *q++ = '\'';
1777                 q = (char *)mempcpy(q, s, len);
1778                 *q++ = '\'';
1779                 s += len;
1780
1781                 STADJUST(q - p, p);
1782
1783                 if (*s != '\'')
1784                         break;
1785                 len = 0;
1786                 do len++; while (*++s == '\'');
1787
1788                 q = p = makestrspace(len + 3, p);
1789
1790                 *q++ = '"';
1791                 q = (char *)mempcpy(q, s - len, len);
1792                 *q++ = '"';
1793
1794                 STADJUST(q - p, p);
1795         } while (*s);
1796
1797         USTPUTC('\0', p);
1798
1799         return stackblock();
1800 }
1801
1802 /*
1803  * Produce a possibly single quoted string suitable as input to the shell.
1804  * If quoting was done, the return string is allocated on the stack,
1805  * otherwise a pointer to the original string is returned.
1806  */
1807 static const char *
1808 maybe_single_quote(const char *s)
1809 {
1810         const char *p = s;
1811
1812         while (*p) {
1813                 /* Assuming ACSII */
1814                 /* quote ctrl_chars space !"#$%&'()* */
1815                 if (*p < '+')
1816                         goto need_quoting;
1817                 /* quote ;<=>? */
1818                 if (*p >= ';' && *p <= '?')
1819                         goto need_quoting;
1820                 /* quote `[\ */
1821                 if (*p == '`')
1822                         goto need_quoting;
1823                 if (*p == '[')
1824                         goto need_quoting;
1825                 if (*p == '\\')
1826                         goto need_quoting;
1827                 /* quote {|}~ DEL and high bytes */
1828                 if (*p > 'z')
1829                         goto need_quoting;
1830                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1831                 /* TODO: maybe avoid quoting % */
1832                 p++;
1833         }
1834         return s;
1835
1836  need_quoting:
1837         return single_quote(s);
1838 }
1839
1840
1841 /* ============ nextopt */
1842
1843 static char **argptr;                  /* argument list for builtin commands */
1844 static char *optionarg;                /* set by nextopt (like getopt) */
1845 static char *optptr;                   /* used by nextopt */
1846
1847 /*
1848  * XXX - should get rid of. Have all builtins use getopt(3).
1849  * The library getopt must have the BSD extension static variable
1850  * "optreset", otherwise it can't be used within the shell safely.
1851  *
1852  * Standard option processing (a la getopt) for builtin routines.
1853  * The only argument that is passed to nextopt is the option string;
1854  * the other arguments are unnecessary. It returns the character,
1855  * or '\0' on end of input.
1856  */
1857 static int
1858 nextopt(const char *optstring)
1859 {
1860         char *p;
1861         const char *q;
1862         char c;
1863
1864         p = optptr;
1865         if (p == NULL || *p == '\0') {
1866                 /* We ate entire "-param", take next one */
1867                 p = *argptr;
1868                 if (p == NULL)
1869                         return '\0';
1870                 if (*p != '-')
1871                         return '\0';
1872                 if (*++p == '\0') /* just "-" ? */
1873                         return '\0';
1874                 argptr++;
1875                 if (LONE_DASH(p)) /* "--" ? */
1876                         return '\0';
1877                 /* p => next "-param" */
1878         }
1879         /* p => some option char in the middle of a "-param" */
1880         c = *p++;
1881         for (q = optstring; *q != c;) {
1882                 if (*q == '\0')
1883                         ash_msg_and_raise_error("illegal option -%c", c);
1884                 if (*++q == ':')
1885                         q++;
1886         }
1887         if (*++q == ':') {
1888                 if (*p == '\0') {
1889                         p = *argptr++;
1890                         if (p == NULL)
1891                                 ash_msg_and_raise_error("no arg for -%c option", c);
1892                 }
1893                 optionarg = p;
1894                 p = NULL;
1895         }
1896         optptr = p;
1897         return c;
1898 }
1899
1900
1901 /* ============ Shell variables */
1902
1903 /*
1904  * The parsefile structure pointed to by the global variable parsefile
1905  * contains information about the current file being read.
1906  */
1907 struct shparam {
1908         int nparam;             /* # of positional parameters (without $0) */
1909 #if ENABLE_ASH_GETOPTS
1910         int optind;             /* next parameter to be processed by getopts */
1911         int optoff;             /* used by getopts */
1912 #endif
1913         unsigned char malloced; /* if parameter list dynamically allocated */
1914         char **p;               /* parameter list */
1915 };
1916
1917 /*
1918  * Free the list of positional parameters.
1919  */
1920 static void
1921 freeparam(volatile struct shparam *param)
1922 {
1923         if (param->malloced) {
1924                 char **ap, **ap1;
1925                 ap = ap1 = param->p;
1926                 while (*ap)
1927                         free(*ap++);
1928                 free(ap1);
1929         }
1930 }
1931
1932 #if ENABLE_ASH_GETOPTS
1933 static void FAST_FUNC getoptsreset(const char *value);
1934 #endif
1935
1936 struct var {
1937         struct var *next;               /* next entry in hash list */
1938         int flags;                      /* flags are defined above */
1939         const char *var_text;           /* name=value */
1940         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1941                                         /* the variable gets set/unset */
1942 };
1943
1944 struct localvar {
1945         struct localvar *next;          /* next local variable in list */
1946         struct var *vp;                 /* the variable that was made local */
1947         int flags;                      /* saved flags */
1948         const char *text;               /* saved text */
1949 };
1950
1951 /* flags */
1952 #define VEXPORT         0x01    /* variable is exported */
1953 #define VREADONLY       0x02    /* variable cannot be modified */
1954 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1955 #define VTEXTFIXED      0x08    /* text is statically allocated */
1956 #define VSTACK          0x10    /* text is allocated on the stack */
1957 #define VUNSET          0x20    /* the variable is not set */
1958 #define VNOFUNC         0x40    /* don't call the callback function */
1959 #define VNOSET          0x80    /* do not set variable - just readonly test */
1960 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1961 #if ENABLE_ASH_RANDOM_SUPPORT
1962 # define VDYNAMIC       0x200   /* dynamic variable */
1963 #else
1964 # define VDYNAMIC       0
1965 #endif
1966
1967
1968 /* Need to be before varinit_data[] */
1969 #if ENABLE_LOCALE_SUPPORT
1970 static void FAST_FUNC
1971 change_lc_all(const char *value)
1972 {
1973         if (value && *value != '\0')
1974                 setlocale(LC_ALL, value);
1975 }
1976 static void FAST_FUNC
1977 change_lc_ctype(const char *value)
1978 {
1979         if (value && *value != '\0')
1980                 setlocale(LC_CTYPE, value);
1981 }
1982 #endif
1983 #if ENABLE_ASH_MAIL
1984 static void chkmail(void);
1985 static void changemail(const char *var_value) FAST_FUNC;
1986 #else
1987 # define chkmail()  ((void)0)
1988 #endif
1989 static void changepath(const char *) FAST_FUNC;
1990 #if ENABLE_ASH_RANDOM_SUPPORT
1991 static void change_random(const char *) FAST_FUNC;
1992 #endif
1993
1994 static const struct {
1995         int flags;
1996         const char *var_text;
1997         void (*var_func)(const char *) FAST_FUNC;
1998 } varinit_data[] = {
1999         /*
2000          * Note: VEXPORT would not work correctly here for NOFORK applets:
2001          * some environment strings may be constant.
2002          */
2003         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2004 #if ENABLE_ASH_MAIL
2005         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2007 #endif
2008         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2009         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2010         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2011         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2012 #if ENABLE_ASH_GETOPTS
2013         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2014 #endif
2015 #if ENABLE_ASH_RANDOM_SUPPORT
2016         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2017 #endif
2018 #if ENABLE_LOCALE_SUPPORT
2019         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2020         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2021 #endif
2022 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2023         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2024 #endif
2025 };
2026
2027 struct redirtab;
2028
2029 struct globals_var {
2030         struct shparam shellparam;      /* $@ current positional parameters */
2031         struct redirtab *redirlist;
2032         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2033         struct var *vartab[VTABSIZE];
2034         struct var varinit[ARRAY_SIZE(varinit_data)];
2035 };
2036 extern struct globals_var *const ash_ptr_to_globals_var;
2037 #define G_var (*ash_ptr_to_globals_var)
2038 #define shellparam    (G_var.shellparam   )
2039 //#define redirlist     (G_var.redirlist    )
2040 #define preverrout_fd (G_var.preverrout_fd)
2041 #define vartab        (G_var.vartab       )
2042 #define varinit       (G_var.varinit      )
2043 #define INIT_G_var() do { \
2044         unsigned i; \
2045         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2046         barrier(); \
2047         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2048                 varinit[i].flags    = varinit_data[i].flags; \
2049                 varinit[i].var_text = varinit_data[i].var_text; \
2050                 varinit[i].var_func = varinit_data[i].var_func; \
2051         } \
2052 } while (0)
2053
2054 #define vifs      varinit[0]
2055 #if ENABLE_ASH_MAIL
2056 # define vmail    (&vifs)[1]
2057 # define vmpath   (&vmail)[1]
2058 # define vpath    (&vmpath)[1]
2059 #else
2060 # define vpath    (&vifs)[1]
2061 #endif
2062 #define vps1      (&vpath)[1]
2063 #define vps2      (&vps1)[1]
2064 #define vps4      (&vps2)[1]
2065 #if ENABLE_ASH_GETOPTS
2066 # define voptind  (&vps4)[1]
2067 # if ENABLE_ASH_RANDOM_SUPPORT
2068 #  define vrandom (&voptind)[1]
2069 # endif
2070 #else
2071 # if ENABLE_ASH_RANDOM_SUPPORT
2072 #  define vrandom (&vps4)[1]
2073 # endif
2074 #endif
2075
2076 /*
2077  * The following macros access the values of the above variables.
2078  * They have to skip over the name.  They return the null string
2079  * for unset variables.
2080  */
2081 #define ifsval()        (vifs.var_text + 4)
2082 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2083 #if ENABLE_ASH_MAIL
2084 # define mailval()      (vmail.var_text + 5)
2085 # define mpathval()     (vmpath.var_text + 9)
2086 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2087 #endif
2088 #define pathval()       (vpath.var_text + 5)
2089 #define ps1val()        (vps1.var_text + 4)
2090 #define ps2val()        (vps2.var_text + 4)
2091 #define ps4val()        (vps4.var_text + 4)
2092 #if ENABLE_ASH_GETOPTS
2093 # define optindval()    (voptind.var_text + 7)
2094 #endif
2095
2096 #if ENABLE_ASH_GETOPTS
2097 static void FAST_FUNC
2098 getoptsreset(const char *value)
2099 {
2100         shellparam.optind = number(value) ?: 1;
2101         shellparam.optoff = -1;
2102 }
2103 #endif
2104
2105 /*
2106  * Compares two strings up to the first = or '\0'.  The first
2107  * string must be terminated by '='; the second may be terminated by
2108  * either '=' or '\0'.
2109  */
2110 static int
2111 varcmp(const char *p, const char *q)
2112 {
2113         int c, d;
2114
2115         while ((c = *p) == (d = *q)) {
2116                 if (c == '\0' || c == '=')
2117                         goto out;
2118                 p++;
2119                 q++;
2120         }
2121         if (c == '=')
2122                 c = '\0';
2123         if (d == '=')
2124                 d = '\0';
2125  out:
2126         return c - d;
2127 }
2128
2129 /*
2130  * Find the appropriate entry in the hash table from the name.
2131  */
2132 static struct var **
2133 hashvar(const char *p)
2134 {
2135         unsigned hashval;
2136
2137         hashval = ((unsigned char) *p) << 4;
2138         while (*p && *p != '=')
2139                 hashval += (unsigned char) *p++;
2140         return &vartab[hashval % VTABSIZE];
2141 }
2142
2143 static int
2144 vpcmp(const void *a, const void *b)
2145 {
2146         return varcmp(*(const char **)a, *(const char **)b);
2147 }
2148
2149 /*
2150  * This routine initializes the builtin variables.
2151  */
2152 static void
2153 initvar(void)
2154 {
2155         struct var *vp;
2156         struct var *end;
2157         struct var **vpp;
2158
2159         /*
2160          * PS1 depends on uid
2161          */
2162 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2163         vps1.var_text = "PS1=\\w \\$ ";
2164 #else
2165         if (!geteuid())
2166                 vps1.var_text = "PS1=# ";
2167 #endif
2168         vp = varinit;
2169         end = vp + ARRAY_SIZE(varinit);
2170         do {
2171                 vpp = hashvar(vp->var_text);
2172                 vp->next = *vpp;
2173                 *vpp = vp;
2174         } while (++vp < end);
2175 }
2176
2177 static struct var **
2178 findvar(struct var **vpp, const char *name)
2179 {
2180         for (; *vpp; vpp = &(*vpp)->next) {
2181                 if (varcmp((*vpp)->var_text, name) == 0) {
2182                         break;
2183                 }
2184         }
2185         return vpp;
2186 }
2187
2188 /*
2189  * Find the value of a variable.  Returns NULL if not set.
2190  */
2191 static const char* FAST_FUNC
2192 lookupvar(const char *name)
2193 {
2194         struct var *v;
2195
2196         v = *findvar(hashvar(name), name);
2197         if (v) {
2198 #if ENABLE_ASH_RANDOM_SUPPORT
2199         /*
2200          * Dynamic variables are implemented roughly the same way they are
2201          * in bash. Namely, they're "special" so long as they aren't unset.
2202          * As soon as they're unset, they're no longer dynamic, and dynamic
2203          * lookup will no longer happen at that point. -- PFM.
2204          */
2205                 if (v->flags & VDYNAMIC)
2206                         v->var_func(NULL);
2207 #endif
2208                 if (!(v->flags & VUNSET))
2209                         return var_end(v->var_text);
2210         }
2211         return NULL;
2212 }
2213
2214 #if ENABLE_UNICODE_SUPPORT
2215 static void
2216 reinit_unicode_for_ash(void)
2217 {
2218         /* Unicode support should be activated even if LANG is set
2219          * _during_ shell execution, not only if it was set when
2220          * shell was started. Therefore, re-check LANG every time:
2221          */
2222         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2223          || ENABLE_UNICODE_USING_LOCALE
2224         ) {
2225                 const char *s = lookupvar("LC_ALL");
2226                 if (!s) s = lookupvar("LC_CTYPE");
2227                 if (!s) s = lookupvar("LANG");
2228                 reinit_unicode(s);
2229         }
2230 }
2231 #else
2232 # define reinit_unicode_for_ash() ((void)0)
2233 #endif
2234
2235 /*
2236  * Search the environment of a builtin command.
2237  */
2238 static ALWAYS_INLINE const char *
2239 bltinlookup(const char *name)
2240 {
2241         return lookupvar(name);
2242 }
2243
2244 /*
2245  * Same as setvar except that the variable and value are passed in
2246  * the first argument as name=value.  Since the first argument will
2247  * be actually stored in the table, it should not be a string that
2248  * will go away.
2249  * Called with interrupts off.
2250  */
2251 static struct var *
2252 setvareq(char *s, int flags)
2253 {
2254         struct var *vp, **vpp;
2255
2256         vpp = hashvar(s);
2257         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2258         vpp = findvar(vpp, s);
2259         vp = *vpp;
2260         if (vp) {
2261                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2262                         const char *n;
2263
2264                         if (flags & VNOSAVE)
2265                                 free(s);
2266                         n = vp->var_text;
2267                         exitstatus = 1;
2268                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2269                 }
2270
2271                 if (flags & VNOSET)
2272                         goto out;
2273
2274                 if (vp->var_func && !(flags & VNOFUNC))
2275                         vp->var_func(var_end(s));
2276
2277                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2278                         free((char*)vp->var_text);
2279
2280                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2281                         *vpp = vp->next;
2282                         free(vp);
2283  out_free:
2284                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2285                                 free(s);
2286                         goto out;
2287                 }
2288
2289                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2290         } else {
2291                 /* variable s is not found */
2292                 if (flags & VNOSET)
2293                         goto out;
2294                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2295                         goto out_free;
2296                 vp = ckzalloc(sizeof(*vp));
2297                 vp->next = *vpp;
2298                 /*vp->func = NULL; - ckzalloc did it */
2299                 *vpp = vp;
2300         }
2301         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2302                 s = ckstrdup(s);
2303         vp->var_text = s;
2304         vp->flags = flags;
2305
2306  out:
2307         return vp;
2308 }
2309
2310 /*
2311  * Set the value of a variable.  The flags argument is ored with the
2312  * flags of the variable.  If val is NULL, the variable is unset.
2313  */
2314 static struct var *
2315 setvar(const char *name, const char *val, int flags)
2316 {
2317         const char *q;
2318         char *p;
2319         char *nameeq;
2320         size_t namelen;
2321         size_t vallen;
2322         struct var *vp;
2323
2324         q = endofname(name);
2325         p = strchrnul(q, '=');
2326         namelen = p - name;
2327         if (!namelen || p != q)
2328                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2329         vallen = 0;
2330         if (val == NULL) {
2331                 flags |= VUNSET;
2332         } else {
2333                 vallen = strlen(val);
2334         }
2335
2336         INT_OFF;
2337         nameeq = ckmalloc(namelen + vallen + 2);
2338         p = mempcpy(nameeq, name, namelen);
2339         if (val) {
2340                 *p++ = '=';
2341                 p = mempcpy(p, val, vallen);
2342         }
2343         *p = '\0';
2344         vp = setvareq(nameeq, flags | VNOSAVE);
2345         INT_ON;
2346
2347         return vp;
2348 }
2349
2350 static void FAST_FUNC
2351 setvar0(const char *name, const char *val)
2352 {
2353         setvar(name, val, 0);
2354 }
2355
2356 /*
2357  * Unset the specified variable.
2358  */
2359 static void
2360 unsetvar(const char *s)
2361 {
2362         setvar(s, NULL, 0);
2363 }
2364
2365 /*
2366  * Process a linked list of variable assignments.
2367  */
2368 static void
2369 listsetvar(struct strlist *list_set_var, int flags)
2370 {
2371         struct strlist *lp = list_set_var;
2372
2373         if (!lp)
2374                 return;
2375         INT_OFF;
2376         do {
2377                 setvareq(lp->text, flags);
2378                 lp = lp->next;
2379         } while (lp);
2380         INT_ON;
2381 }
2382
2383 /*
2384  * Generate a list of variables satisfying the given conditions.
2385  */
2386 static char **
2387 listvars(int on, int off, char ***end)
2388 {
2389         struct var **vpp;
2390         struct var *vp;
2391         char **ep;
2392         int mask;
2393
2394         STARTSTACKSTR(ep);
2395         vpp = vartab;
2396         mask = on | off;
2397         do {
2398                 for (vp = *vpp; vp; vp = vp->next) {
2399                         if ((vp->flags & mask) == on) {
2400                                 if (ep == stackstrend())
2401                                         ep = growstackstr();
2402                                 *ep++ = (char*)vp->var_text;
2403                         }
2404                 }
2405         } while (++vpp < vartab + VTABSIZE);
2406         if (ep == stackstrend())
2407                 ep = growstackstr();
2408         if (end)
2409                 *end = ep;
2410         *ep++ = NULL;
2411         return grabstackstr(ep);
2412 }
2413
2414
2415 /* ============ Path search helper
2416  *
2417  * The variable path (passed by reference) should be set to the start
2418  * of the path before the first call; path_advance will update
2419  * this value as it proceeds.  Successive calls to path_advance will return
2420  * the possible path expansions in sequence.  If an option (indicated by
2421  * a percent sign) appears in the path entry then the global variable
2422  * pathopt will be set to point to it; otherwise pathopt will be set to
2423  * NULL.
2424  */
2425 static const char *pathopt;     /* set by path_advance */
2426
2427 static char *
2428 path_advance(const char **path, const char *name)
2429 {
2430         const char *p;
2431         char *q;
2432         const char *start;
2433         size_t len;
2434
2435         if (*path == NULL)
2436                 return NULL;
2437         start = *path;
2438         for (p = start; *p && *p != ':' && *p != '%'; p++)
2439                 continue;
2440         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2441         while (stackblocksize() < len)
2442                 growstackblock();
2443         q = stackblock();
2444         if (p != start) {
2445                 q = mempcpy(q, start, p - start);
2446                 *q++ = '/';
2447         }
2448         strcpy(q, name);
2449         pathopt = NULL;
2450         if (*p == '%') {
2451                 pathopt = ++p;
2452                 while (*p && *p != ':')
2453                         p++;
2454         }
2455         if (*p == ':')
2456                 *path = p + 1;
2457         else
2458                 *path = NULL;
2459         return stalloc(len);
2460 }
2461
2462
2463 /* ============ Prompt */
2464
2465 static smallint doprompt;                   /* if set, prompt the user */
2466 static smallint needprompt;                 /* true if interactive and at start of line */
2467
2468 #if ENABLE_FEATURE_EDITING
2469 static line_input_t *line_input_state;
2470 static const char *cmdedit_prompt;
2471 static void
2472 putprompt(const char *s)
2473 {
2474         if (ENABLE_ASH_EXPAND_PRMT) {
2475                 free((char*)cmdedit_prompt);
2476                 cmdedit_prompt = ckstrdup(s);
2477                 return;
2478         }
2479         cmdedit_prompt = s;
2480 }
2481 #else
2482 static void
2483 putprompt(const char *s)
2484 {
2485         out2str(s);
2486 }
2487 #endif
2488
2489 /* expandstr() needs parsing machinery, so it is far away ahead... */
2490 static const char *expandstr(const char *ps, int syntax_type);
2491 /* Values for syntax param */
2492 #define BASESYNTAX 0    /* not in quotes */
2493 #define DQSYNTAX   1    /* in double quotes */
2494 #define SQSYNTAX   2    /* in single quotes */
2495 #define ARISYNTAX  3    /* in arithmetic */
2496 #if ENABLE_ASH_EXPAND_PRMT
2497 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2498 #endif
2499 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2500
2501 /*
2502  * called by editline -- any expansions to the prompt should be added here.
2503  */
2504 static void
2505 setprompt_if(smallint do_set, int whichprompt)
2506 {
2507         const char *prompt;
2508         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2509
2510         if (!do_set)
2511                 return;
2512
2513         needprompt = 0;
2514
2515         switch (whichprompt) {
2516         case 1:
2517                 prompt = ps1val();
2518                 break;
2519         case 2:
2520                 prompt = ps2val();
2521                 break;
2522         default:                        /* 0 */
2523                 prompt = nullstr;
2524         }
2525 #if ENABLE_ASH_EXPAND_PRMT
2526         pushstackmark(&smark, stackblocksize());
2527         putprompt(expandstr(prompt, PSSYNTAX));
2528         popstackmark(&smark);
2529 #else
2530         putprompt(prompt);
2531 #endif
2532 }
2533
2534
2535 /* ============ The cd and pwd commands */
2536
2537 #define CD_PHYSICAL 1
2538 #define CD_PRINT 2
2539
2540 static int
2541 cdopt(void)
2542 {
2543         int flags = 0;
2544         int i, j;
2545
2546         j = 'L';
2547         while ((i = nextopt("LP")) != '\0') {
2548                 if (i != j) {
2549                         flags ^= CD_PHYSICAL;
2550                         j = i;
2551                 }
2552         }
2553
2554         return flags;
2555 }
2556
2557 /*
2558  * Update curdir (the name of the current directory) in response to a
2559  * cd command.
2560  */
2561 static const char *
2562 updatepwd(const char *dir)
2563 {
2564         char *new;
2565         char *p;
2566         char *cdcomppath;
2567         const char *lim;
2568
2569         cdcomppath = sstrdup(dir);
2570         STARTSTACKSTR(new);
2571         if (*dir != '/') {
2572                 if (curdir == nullstr)
2573                         return 0;
2574                 new = stack_putstr(curdir, new);
2575         }
2576         new = makestrspace(strlen(dir) + 2, new);
2577         lim = (char *)stackblock() + 1;
2578         if (*dir != '/') {
2579                 if (new[-1] != '/')
2580                         USTPUTC('/', new);
2581                 if (new > lim && *lim == '/')
2582                         lim++;
2583         } else {
2584                 USTPUTC('/', new);
2585                 cdcomppath++;
2586                 if (dir[1] == '/' && dir[2] != '/') {
2587                         USTPUTC('/', new);
2588                         cdcomppath++;
2589                         lim++;
2590                 }
2591         }
2592         p = strtok(cdcomppath, "/");
2593         while (p) {
2594                 switch (*p) {
2595                 case '.':
2596                         if (p[1] == '.' && p[2] == '\0') {
2597                                 while (new > lim) {
2598                                         STUNPUTC(new);
2599                                         if (new[-1] == '/')
2600                                                 break;
2601                                 }
2602                                 break;
2603                         }
2604                         if (p[1] == '\0')
2605                                 break;
2606                         /* fall through */
2607                 default:
2608                         new = stack_putstr(p, new);
2609                         USTPUTC('/', new);
2610                 }
2611                 p = strtok(NULL, "/");
2612         }
2613         if (new > lim)
2614                 STUNPUTC(new);
2615         *new = 0;
2616         return stackblock();
2617 }
2618
2619 /*
2620  * Find out what the current directory is. If we already know the current
2621  * directory, this routine returns immediately.
2622  */
2623 static char *
2624 getpwd(void)
2625 {
2626         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2627         return dir ? dir : nullstr;
2628 }
2629
2630 static void
2631 setpwd(const char *val, int setold)
2632 {
2633         char *oldcur, *dir;
2634
2635         oldcur = dir = curdir;
2636
2637         if (setold) {
2638                 setvar("OLDPWD", oldcur, VEXPORT);
2639         }
2640         INT_OFF;
2641         if (physdir != nullstr) {
2642                 if (physdir != oldcur)
2643                         free(physdir);
2644                 physdir = nullstr;
2645         }
2646         if (oldcur == val || !val) {
2647                 char *s = getpwd();
2648                 physdir = s;
2649                 if (!val)
2650                         dir = s;
2651         } else
2652                 dir = ckstrdup(val);
2653         if (oldcur != dir && oldcur != nullstr) {
2654                 free(oldcur);
2655         }
2656         curdir = dir;
2657         INT_ON;
2658         setvar("PWD", dir, VEXPORT);
2659 }
2660
2661 static void hashcd(void);
2662
2663 /*
2664  * Actually do the chdir.  We also call hashcd to let other routines
2665  * know that the current directory has changed.
2666  */
2667 static int
2668 docd(const char *dest, int flags)
2669 {
2670         const char *dir = NULL;
2671         int err;
2672
2673         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2674
2675         INT_OFF;
2676         if (!(flags & CD_PHYSICAL)) {
2677                 dir = updatepwd(dest);
2678                 if (dir)
2679                         dest = dir;
2680         }
2681         err = chdir(dest);
2682         if (err)
2683                 goto out;
2684         setpwd(dir, 1);
2685         hashcd();
2686  out:
2687         INT_ON;
2688         return err;
2689 }
2690
2691 static int FAST_FUNC
2692 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2693 {
2694         const char *dest;
2695         const char *path;
2696         const char *p;
2697         char c;
2698         struct stat statb;
2699         int flags;
2700
2701         flags = cdopt();
2702         dest = *argptr;
2703         if (!dest)
2704                 dest = bltinlookup("HOME");
2705         else if (LONE_DASH(dest)) {
2706                 dest = bltinlookup("OLDPWD");
2707                 flags |= CD_PRINT;
2708         }
2709         if (!dest)
2710                 dest = nullstr;
2711         if (*dest == '/')
2712                 goto step6;
2713         if (*dest == '.') {
2714                 c = dest[1];
2715  dotdot:
2716                 switch (c) {
2717                 case '\0':
2718                 case '/':
2719                         goto step6;
2720                 case '.':
2721                         c = dest[2];
2722                         if (c != '.')
2723                                 goto dotdot;
2724                 }
2725         }
2726         if (!*dest)
2727                 dest = ".";
2728         path = bltinlookup("CDPATH");
2729         while (path) {
2730                 c = *path;
2731                 p = path_advance(&path, dest);
2732                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2733                         if (c && c != ':')
2734                                 flags |= CD_PRINT;
2735  docd:
2736                         if (!docd(p, flags))
2737                                 goto out;
2738                         goto err;
2739                 }
2740         }
2741
2742  step6:
2743         p = dest;
2744         goto docd;
2745
2746  err:
2747         ash_msg_and_raise_error("can't cd to %s", dest);
2748         /* NOTREACHED */
2749  out:
2750         if (flags & CD_PRINT)
2751                 out1fmt("%s\n", curdir);
2752         return 0;
2753 }
2754
2755 static int FAST_FUNC
2756 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2757 {
2758         int flags;
2759         const char *dir = curdir;
2760
2761         flags = cdopt();
2762         if (flags) {
2763                 if (physdir == nullstr)
2764                         setpwd(dir, 0);
2765                 dir = physdir;
2766         }
2767         out1fmt("%s\n", dir);
2768         return 0;
2769 }
2770
2771
2772 /* ============ ... */
2773
2774
2775 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2776
2777 /* Syntax classes */
2778 #define CWORD     0             /* character is nothing special */
2779 #define CNL       1             /* newline character */
2780 #define CBACK     2             /* a backslash character */
2781 #define CSQUOTE   3             /* single quote */
2782 #define CDQUOTE   4             /* double quote */
2783 #define CENDQUOTE 5             /* a terminating quote */
2784 #define CBQUOTE   6             /* backwards single quote */
2785 #define CVAR      7             /* a dollar sign */
2786 #define CENDVAR   8             /* a '}' character */
2787 #define CLP       9             /* a left paren in arithmetic */
2788 #define CRP      10             /* a right paren in arithmetic */
2789 #define CENDFILE 11             /* end of file */
2790 #define CCTL     12             /* like CWORD, except it must be escaped */
2791 #define CSPCL    13             /* these terminate a word */
2792 #define CIGN     14             /* character should be ignored */
2793
2794 #define PEOF     256
2795 #if ENABLE_ASH_ALIAS
2796 # define PEOA    257
2797 #endif
2798
2799 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2800
2801 #if ENABLE_FEATURE_SH_MATH
2802 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2803 #else
2804 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2805 #endif
2806 static const uint16_t S_I_T[] ALIGN2 = {
2807 #if ENABLE_ASH_ALIAS
2808         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2809 #endif
2810         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2811         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2812         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2813         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2814         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2815         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2816         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2817         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2818         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2819         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2820         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2821 #if !USE_SIT_FUNCTION
2822         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2823         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2824         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2825 #endif
2826 #undef SIT_ITEM
2827 };
2828 /* Constants below must match table above */
2829 enum {
2830 #if ENABLE_ASH_ALIAS
2831         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2832 #endif
2833         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2834         CNL_CNL_CNL_CNL                    , /*  2 */
2835         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2836         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2837         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2838         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2839         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2840         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2841         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2842         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2843         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2844         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2845         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2846         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2847 };
2848
2849 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2850  * caller must ensure proper cast on it if c is *char_ptr!
2851  */
2852 #if USE_SIT_FUNCTION
2853
2854 static int
2855 SIT(int c, int syntax)
2856 {
2857         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2858         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2859         /*
2860          * This causes '/' to be prepended with CTLESC in dquoted string,
2861          * making "./file"* treated incorrectly because we feed
2862          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2863          * The "homegrown" glob implementation is okay with that,
2864          * but glibc one isn't. With '/' always treated as CWORD,
2865          * both work fine.
2866          */
2867 # if ENABLE_ASH_ALIAS
2868         static const uint8_t syntax_index_table[] ALIGN1 = {
2869                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2870                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2871                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2872                 11, 3                           /* "}~" */
2873         };
2874 # else
2875         static const uint8_t syntax_index_table[] ALIGN1 = {
2876                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2877                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2878                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2879                 10, 2                           /* "}~" */
2880         };
2881 # endif
2882         const char *s;
2883         int indx;
2884
2885         if (c == PEOF)
2886                 return CENDFILE;
2887 # if ENABLE_ASH_ALIAS
2888         if (c == PEOA)
2889                 indx = 0;
2890         else
2891 # endif
2892         {
2893                 /* Cast is purely for paranoia here,
2894                  * just in case someone passed signed char to us */
2895                 if ((unsigned char)c >= CTL_FIRST
2896                  && (unsigned char)c <= CTL_LAST
2897                 ) {
2898                         return CCTL;
2899                 }
2900                 s = strchrnul(spec_symbls, c);
2901                 if (*s == '\0')
2902                         return CWORD;
2903                 indx = syntax_index_table[s - spec_symbls];
2904         }
2905         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2906 }
2907
2908 #else   /* !USE_SIT_FUNCTION */
2909
2910 static const uint8_t syntax_index_table[] ALIGN1 = {
2911         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2912         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2913         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2914         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2915         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2916         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2918         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2919         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2921         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2922         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2923         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2924         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2926         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2927         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2944         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2945         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2946         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2947         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2948         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2949         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2950         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2951         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2952         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2953         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2954         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2955         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2956         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2957         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2958         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2959 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2960         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2972         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2973         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2974         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2975         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2976         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2977         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3005         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3006         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3007         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3009         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3010         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3011         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3012         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3013         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3037         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3038         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3039         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3040         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3041         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3042         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3043         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3044         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3045         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3046         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3047         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3048         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3049         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3050         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3169         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3170 # if ENABLE_ASH_ALIAS
3171         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3172 # endif
3173 };
3174
3175 #if 1
3176 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3177 #else /* debug version, caught one signed char bug */
3178 # define SIT(c, syntax) \
3179         ({ \
3180                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3181                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3182                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3183                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3184                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3185         })
3186 #endif
3187
3188 #endif  /* !USE_SIT_FUNCTION */
3189
3190
3191 /* ============ Alias handling */
3192
3193 #if ENABLE_ASH_ALIAS
3194
3195 #define ALIASINUSE 1
3196 #define ALIASDEAD  2
3197
3198 struct alias {
3199         struct alias *next;
3200         char *name;
3201         char *val;
3202         int flag;
3203 };
3204
3205
3206 static struct alias **atab; // [ATABSIZE];
3207 #define INIT_G_alias() do { \
3208         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3209 } while (0)
3210
3211
3212 static struct alias **
3213 __lookupalias(const char *name)
3214 {
3215         unsigned int hashval;
3216         struct alias **app;
3217         const char *p;
3218         unsigned int ch;
3219
3220         p = name;
3221
3222         ch = (unsigned char)*p;
3223         hashval = ch << 4;
3224         while (ch) {
3225                 hashval += ch;
3226                 ch = (unsigned char)*++p;
3227         }
3228         app = &atab[hashval % ATABSIZE];
3229
3230         for (; *app; app = &(*app)->next) {
3231                 if (strcmp(name, (*app)->name) == 0) {
3232                         break;
3233                 }
3234         }
3235
3236         return app;
3237 }
3238
3239 static struct alias *
3240 lookupalias(const char *name, int check)
3241 {
3242         struct alias *ap = *__lookupalias(name);
3243
3244         if (check && ap && (ap->flag & ALIASINUSE))
3245                 return NULL;
3246         return ap;
3247 }
3248
3249 static struct alias *
3250 freealias(struct alias *ap)
3251 {
3252         struct alias *next;
3253
3254         if (ap->flag & ALIASINUSE) {
3255                 ap->flag |= ALIASDEAD;
3256                 return ap;
3257         }
3258
3259         next = ap->next;
3260         free(ap->name);
3261         free(ap->val);
3262         free(ap);
3263         return next;
3264 }
3265
3266 static void
3267 setalias(const char *name, const char *val)
3268 {
3269         struct alias *ap, **app;
3270
3271         app = __lookupalias(name);
3272         ap = *app;
3273         INT_OFF;
3274         if (ap) {
3275                 if (!(ap->flag & ALIASINUSE)) {
3276                         free(ap->val);
3277                 }
3278                 ap->val = ckstrdup(val);
3279                 ap->flag &= ~ALIASDEAD;
3280         } else {
3281                 /* not found */
3282                 ap = ckzalloc(sizeof(struct alias));
3283                 ap->name = ckstrdup(name);
3284                 ap->val = ckstrdup(val);
3285                 /*ap->flag = 0; - ckzalloc did it */
3286                 /*ap->next = NULL;*/
3287                 *app = ap;
3288         }
3289         INT_ON;
3290 }
3291
3292 static int
3293 unalias(const char *name)
3294 {
3295         struct alias **app;
3296
3297         app = __lookupalias(name);
3298
3299         if (*app) {
3300                 INT_OFF;
3301                 *app = freealias(*app);
3302                 INT_ON;
3303                 return 0;
3304         }
3305
3306         return 1;
3307 }
3308
3309 static void
3310 rmaliases(void)
3311 {
3312         struct alias *ap, **app;
3313         int i;
3314
3315         INT_OFF;
3316         for (i = 0; i < ATABSIZE; i++) {
3317                 app = &atab[i];
3318                 for (ap = *app; ap; ap = *app) {
3319                         *app = freealias(*app);
3320                         if (ap == *app) {
3321                                 app = &ap->next;
3322                         }
3323                 }
3324         }
3325         INT_ON;
3326 }
3327
3328 static void
3329 printalias(const struct alias *ap)
3330 {
3331         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3332 }
3333
3334 /*
3335  * TODO - sort output
3336  */
3337 static int FAST_FUNC
3338 aliascmd(int argc UNUSED_PARAM, char **argv)
3339 {
3340         char *n, *v;
3341         int ret = 0;
3342         struct alias *ap;
3343
3344         if (!argv[1]) {
3345                 int i;
3346
3347                 for (i = 0; i < ATABSIZE; i++) {
3348                         for (ap = atab[i]; ap; ap = ap->next) {
3349                                 printalias(ap);
3350                         }
3351                 }
3352                 return 0;
3353         }
3354         while ((n = *++argv) != NULL) {
3355                 v = strchr(n+1, '=');
3356                 if (v == NULL) { /* n+1: funny ksh stuff */
3357                         ap = *__lookupalias(n);
3358                         if (ap == NULL) {
3359                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3360                                 ret = 1;
3361                         } else
3362                                 printalias(ap);
3363                 } else {
3364                         *v++ = '\0';
3365                         setalias(n, v);
3366                 }
3367         }
3368
3369         return ret;
3370 }
3371
3372 static int FAST_FUNC
3373 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3374 {
3375         int i;
3376
3377         while (nextopt("a") != '\0') {
3378                 rmaliases();
3379                 return 0;
3380         }
3381         for (i = 0; *argptr; argptr++) {
3382                 if (unalias(*argptr)) {
3383                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3384                         i = 1;
3385                 }
3386         }
3387
3388         return i;
3389 }
3390
3391 #endif /* ASH_ALIAS */
3392
3393
3394 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3395 #define FORK_FG    0
3396 #define FORK_BG    1
3397 #define FORK_NOJOB 2
3398
3399 /* mode flags for showjob(s) */
3400 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3401 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3402 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3403 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3404
3405 /*
3406  * A job structure contains information about a job.  A job is either a
3407  * single process or a set of processes contained in a pipeline.  In the
3408  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3409  * array of pids.
3410  */
3411 struct procstat {
3412         pid_t   ps_pid;         /* process id */
3413         int     ps_status;      /* last process status from wait() */
3414         char    *ps_cmd;        /* text of command being run */
3415 };
3416
3417 struct job {
3418         struct procstat ps0;    /* status of process */
3419         struct procstat *ps;    /* status or processes when more than one */
3420 #if JOBS
3421         int stopstatus;         /* status of a stopped job */
3422 #endif
3423         unsigned nprocs;        /* number of processes */
3424
3425 #define JOBRUNNING      0       /* at least one proc running */
3426 #define JOBSTOPPED      1       /* all procs are stopped */
3427 #define JOBDONE         2       /* all procs are completed */
3428         unsigned
3429                 state: 8,
3430 #if JOBS
3431                 sigint: 1,      /* job was killed by SIGINT */
3432                 jobctl: 1,      /* job running under job control */
3433 #endif
3434                 waited: 1,      /* true if this entry has been waited for */
3435                 used: 1,        /* true if this entry is in used */
3436                 changed: 1;     /* true if status has changed */
3437         struct job *prev_job;   /* previous job */
3438 };
3439
3440 static struct job *makejob(/*union node *,*/ int);
3441 static int forkshell(struct job *, union node *, int);
3442 static int waitforjob(struct job *);
3443
3444 #if !JOBS
3445 enum { doing_jobctl = 0 };
3446 #define setjobctl(on) do {} while (0)
3447 #else
3448 static smallint doing_jobctl; //references:8
3449 static void setjobctl(int);
3450 #endif
3451
3452 /*
3453  * Ignore a signal.
3454  */
3455 static void
3456 ignoresig(int signo)
3457 {
3458         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3459         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3460                 /* No, need to do it */
3461                 signal(signo, SIG_IGN);
3462         }
3463         sigmode[signo - 1] = S_HARD_IGN;
3464 }
3465
3466 /*
3467  * Only one usage site - in setsignal()
3468  */
3469 static void
3470 signal_handler(int signo)
3471 {
3472         if (signo == SIGCHLD) {
3473                 got_sigchld = 1;
3474                 if (!trap[SIGCHLD])
3475                         return;
3476         }
3477
3478         gotsig[signo - 1] = 1;
3479         pending_sig = signo;
3480
3481         if (signo == SIGINT && !trap[SIGINT]) {
3482                 if (!suppress_int) {
3483                         pending_sig = 0;
3484                         raise_interrupt(); /* does not return */
3485                 }
3486                 pending_int = 1;
3487         }
3488 }
3489
3490 /*
3491  * Set the signal handler for the specified signal.  The routine figures
3492  * out what it should be set to.
3493  */
3494 static void
3495 setsignal(int signo)
3496 {
3497         char *t;
3498         char cur_act, new_act;
3499         struct sigaction act;
3500
3501         t = trap[signo];
3502         new_act = S_DFL;
3503         if (t != NULL) { /* trap for this sig is set */
3504                 new_act = S_CATCH;
3505                 if (t[0] == '\0') /* trap is "": ignore this sig */
3506                         new_act = S_IGN;
3507         }
3508
3509         if (rootshell && new_act == S_DFL) {
3510                 switch (signo) {
3511                 case SIGINT:
3512                         if (iflag || minusc || sflag == 0)
3513                                 new_act = S_CATCH;
3514                         break;
3515                 case SIGQUIT:
3516 #if DEBUG
3517                         if (debug)
3518                                 break;
3519 #endif
3520                         /* man bash:
3521                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3522                          * commands run by bash have signal handlers
3523                          * set to the values inherited by the shell
3524                          * from its parent". */
3525                         new_act = S_IGN;
3526                         break;
3527                 case SIGTERM:
3528                         if (iflag)
3529                                 new_act = S_IGN;
3530                         break;
3531 #if JOBS
3532                 case SIGTSTP:
3533                 case SIGTTOU:
3534                         if (mflag)
3535                                 new_act = S_IGN;
3536                         break;
3537 #endif
3538                 }
3539         }
3540         /* if !rootshell, we reset SIGQUIT to DFL,
3541          * whereas we have to restore it to what shell got on entry.
3542          * This is handled by the fact that if signal was IGNored on entry,
3543          * then cur_act is S_HARD_IGN and we never change its sigaction
3544          * (see code below).
3545          */
3546
3547         if (signo == SIGCHLD)
3548                 new_act = S_CATCH;
3549
3550         t = &sigmode[signo - 1];
3551         cur_act = *t;
3552         if (cur_act == 0) {
3553                 /* current setting is not yet known */
3554                 if (sigaction(signo, NULL, &act)) {
3555                         /* pretend it worked; maybe we should give a warning,
3556                          * but other shells don't. We don't alter sigmode,
3557                          * so we retry every time.
3558                          * btw, in Linux it never fails. --vda */
3559                         return;
3560                 }
3561                 if (act.sa_handler == SIG_IGN) {
3562                         cur_act = S_HARD_IGN;
3563                         if (mflag
3564                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3565                         ) {
3566                                 cur_act = S_IGN;   /* don't hard ignore these */
3567                         }
3568                 }
3569                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3570                         /* installing SIG_DFL over SIG_DFL is a no-op */
3571                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3572                         *t = S_DFL;
3573                         return;
3574                 }
3575         }
3576         if (cur_act == S_HARD_IGN || cur_act == new_act)
3577                 return;
3578
3579         *t = new_act;
3580
3581         act.sa_handler = SIG_DFL;
3582         switch (new_act) {
3583         case S_CATCH:
3584                 act.sa_handler = signal_handler;
3585                 break;
3586         case S_IGN:
3587                 act.sa_handler = SIG_IGN;
3588                 break;
3589         }
3590         /* flags and mask matter only if !DFL and !IGN, but we do it
3591          * for all cases for more deterministic behavior:
3592          */
3593         act.sa_flags = 0; //TODO: why not SA_RESTART?
3594         sigfillset(&act.sa_mask);
3595
3596         sigaction_set(signo, &act);
3597 }
3598
3599 /* mode flags for set_curjob */
3600 #define CUR_DELETE 2
3601 #define CUR_RUNNING 1
3602 #define CUR_STOPPED 0
3603
3604 #if JOBS
3605 /* pgrp of shell on invocation */
3606 static int initialpgrp; //references:2
3607 static int ttyfd = -1; //5
3608 #endif
3609 /* array of jobs */
3610 static struct job *jobtab; //5
3611 /* size of array */
3612 static unsigned njobs; //4
3613 /* current job */
3614 static struct job *curjob; //lots
3615 /* number of presumed living untracked jobs */
3616 static int jobless; //4
3617
3618 #if 0
3619 /* Bash has a feature: it restores termios after a successful wait for
3620  * a foreground job which had at least one stopped or sigkilled member.
3621  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3622  * properly restoring tty state. Should we do this too?
3623  * A reproducer: ^Z an interactive python:
3624  *
3625  * # python
3626  * Python 2.7.12 (...)
3627  * >>> ^Z
3628  *      { python leaves tty in -icanon -echo state. We do survive that... }
3629  *  [1]+  Stopped                    python
3630  *      { ...however, next program (python #2) does not survive it well: }
3631  * # python
3632  * Python 2.7.12 (...)
3633  * >>> Traceback (most recent call last):
3634  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3635  *   File "<stdin>", line 1, in <module>
3636  * NameError: name 'qwerty' is not defined
3637  *
3638  * The implementation below is modeled on bash code and seems to work.
3639  * However, I'm not sure we should do this. For one: what if I'd fg
3640  * the stopped python instead? It'll be confused by "restored" tty state.
3641  */
3642 static struct termios shell_tty_info;
3643 static void
3644 get_tty_state(void)
3645 {
3646         if (rootshell && ttyfd >= 0)
3647                 tcgetattr(ttyfd, &shell_tty_info);
3648 }
3649 static void
3650 set_tty_state(void)
3651 {
3652         /* if (rootshell) - caller ensures this */
3653         if (ttyfd >= 0)
3654                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3655 }
3656 static int
3657 job_signal_status(struct job *jp)
3658 {
3659         int status;
3660         unsigned i;
3661         struct procstat *ps = jp->ps;
3662         for (i = 0; i < jp->nprocs; i++) {
3663                 status = ps[i].ps_status;
3664                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3665                         return status;
3666         }
3667         return 0;
3668 }
3669 static void
3670 restore_tty_if_stopped_or_signaled(struct job *jp)
3671 {
3672 //TODO: check what happens if we come from waitforjob() in expbackq()
3673         if (rootshell) {
3674                 int s = job_signal_status(jp);
3675                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3676                         set_tty_state();
3677         }
3678 }
3679 #else
3680 # define get_tty_state() ((void)0)
3681 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3682 #endif
3683
3684 static void
3685 set_curjob(struct job *jp, unsigned mode)
3686 {
3687         struct job *jp1;
3688         struct job **jpp, **curp;
3689
3690         /* first remove from list */
3691         jpp = curp = &curjob;
3692         while (1) {
3693                 jp1 = *jpp;
3694                 if (jp1 == jp)
3695                         break;
3696                 jpp = &jp1->prev_job;
3697         }
3698         *jpp = jp1->prev_job;
3699
3700         /* Then re-insert in correct position */
3701         jpp = curp;
3702         switch (mode) {
3703         default:
3704 #if DEBUG
3705                 abort();
3706 #endif
3707         case CUR_DELETE:
3708                 /* job being deleted */
3709                 break;
3710         case CUR_RUNNING:
3711                 /* newly created job or backgrounded job,
3712                  * put after all stopped jobs.
3713                  */
3714                 while (1) {
3715                         jp1 = *jpp;
3716 #if JOBS
3717                         if (!jp1 || jp1->state != JOBSTOPPED)
3718 #endif
3719                                 break;
3720                         jpp = &jp1->prev_job;
3721                 }
3722                 /* FALLTHROUGH */
3723 #if JOBS
3724         case CUR_STOPPED:
3725 #endif
3726                 /* newly stopped job - becomes curjob */
3727                 jp->prev_job = *jpp;
3728                 *jpp = jp;
3729                 break;
3730         }
3731 }
3732
3733 #if JOBS || DEBUG
3734 static int
3735 jobno(const struct job *jp)
3736 {
3737         return jp - jobtab + 1;
3738 }
3739 #endif
3740
3741 /*
3742  * Convert a job name to a job structure.
3743  */
3744 #if !JOBS
3745 #define getjob(name, getctl) getjob(name)
3746 #endif
3747 static struct job *
3748 getjob(const char *name, int getctl)
3749 {
3750         struct job *jp;
3751         struct job *found;
3752         const char *err_msg = "%s: no such job";
3753         unsigned num;
3754         int c;
3755         const char *p;
3756         char *(*match)(const char *, const char *);
3757
3758         jp = curjob;
3759         p = name;
3760         if (!p)
3761                 goto currentjob;
3762
3763         if (*p != '%')
3764                 goto err;
3765
3766         c = *++p;
3767         if (!c)
3768                 goto currentjob;
3769
3770         if (!p[1]) {
3771                 if (c == '+' || c == '%') {
3772  currentjob:
3773                         err_msg = "No current job";
3774                         goto check;
3775                 }
3776                 if (c == '-') {
3777                         if (jp)
3778                                 jp = jp->prev_job;
3779                         err_msg = "No previous job";
3780  check:
3781                         if (!jp)
3782                                 goto err;
3783                         goto gotit;
3784                 }
3785         }
3786
3787         if (is_number(p)) {
3788                 num = atoi(p);
3789                 if (num > 0 && num <= njobs) {
3790                         jp = jobtab + num - 1;
3791                         if (jp->used)
3792                                 goto gotit;
3793                         goto err;
3794                 }
3795         }
3796
3797         match = prefix;
3798         if (*p == '?') {
3799                 match = strstr;
3800                 p++;
3801         }
3802
3803         found = NULL;
3804         while (jp) {
3805                 if (match(jp->ps[0].ps_cmd, p)) {
3806                         if (found)
3807                                 goto err;
3808                         found = jp;
3809                         err_msg = "%s: ambiguous";
3810                 }
3811                 jp = jp->prev_job;
3812         }
3813         if (!found)
3814                 goto err;
3815         jp = found;
3816
3817  gotit:
3818 #if JOBS
3819         err_msg = "job %s not created under job control";
3820         if (getctl && jp->jobctl == 0)
3821                 goto err;
3822 #endif
3823         return jp;
3824  err:
3825         ash_msg_and_raise_error(err_msg, name);
3826 }
3827
3828 /*
3829  * Mark a job structure as unused.
3830  */
3831 static void
3832 freejob(struct job *jp)
3833 {
3834         struct procstat *ps;
3835         int i;
3836
3837         INT_OFF;
3838         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3839                 if (ps->ps_cmd != nullstr)
3840                         free(ps->ps_cmd);
3841         }
3842         if (jp->ps != &jp->ps0)
3843                 free(jp->ps);
3844         jp->used = 0;
3845         set_curjob(jp, CUR_DELETE);
3846         INT_ON;
3847 }
3848
3849 #if JOBS
3850 static void
3851 xtcsetpgrp(int fd, pid_t pgrp)
3852 {
3853         if (tcsetpgrp(fd, pgrp))
3854                 ash_msg_and_raise_perror("can't set tty process group");
3855 }
3856
3857 /*
3858  * Turn job control on and off.
3859  *
3860  * Note:  This code assumes that the third arg to ioctl is a character
3861  * pointer, which is true on Berkeley systems but not System V.  Since
3862  * System V doesn't have job control yet, this isn't a problem now.
3863  *
3864  * Called with interrupts off.
3865  */
3866 static void
3867 setjobctl(int on)
3868 {
3869         int fd;
3870         int pgrp;
3871
3872         if (on == doing_jobctl || rootshell == 0)
3873                 return;
3874         if (on) {
3875                 int ofd;
3876                 ofd = fd = open(_PATH_TTY, O_RDWR);
3877                 if (fd < 0) {
3878         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3879          * That sometimes helps to acquire controlling tty.
3880          * Obviously, a workaround for bugs when someone
3881          * failed to provide a controlling tty to bash! :) */
3882                         fd = 2;
3883                         while (!isatty(fd))
3884                                 if (--fd < 0)
3885                                         goto out;
3886                 }
3887                 /* fd is a tty at this point */
3888                 fd = fcntl(fd, F_DUPFD, 10);
3889                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3890                         close(ofd);
3891                 if (fd < 0)
3892                         goto out; /* F_DUPFD failed */
3893                 close_on_exec_on(fd);
3894                 while (1) { /* while we are in the background */
3895                         pgrp = tcgetpgrp(fd);
3896                         if (pgrp < 0) {
3897  out:
3898                                 ash_msg("can't access tty; job control turned off");
3899                                 mflag = on = 0;
3900                                 goto close;
3901                         }
3902                         if (pgrp == getpgrp())
3903                                 break;
3904                         killpg(0, SIGTTIN);
3905                 }
3906                 initialpgrp = pgrp;
3907
3908                 setsignal(SIGTSTP);
3909                 setsignal(SIGTTOU);
3910                 setsignal(SIGTTIN);
3911                 pgrp = rootpid;
3912                 setpgid(0, pgrp);
3913                 xtcsetpgrp(fd, pgrp);
3914         } else {
3915                 /* turning job control off */
3916                 fd = ttyfd;
3917                 pgrp = initialpgrp;
3918                 /* was xtcsetpgrp, but this can make exiting ash
3919                  * loop forever if pty is already deleted */
3920                 tcsetpgrp(fd, pgrp);
3921                 setpgid(0, pgrp);
3922                 setsignal(SIGTSTP);
3923                 setsignal(SIGTTOU);
3924                 setsignal(SIGTTIN);
3925  close:
3926                 if (fd >= 0)
3927                         close(fd);
3928                 fd = -1;
3929         }
3930         ttyfd = fd;
3931         doing_jobctl = on;
3932 }
3933
3934 static int FAST_FUNC
3935 killcmd(int argc, char **argv)
3936 {
3937         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3938                 int i = 1;
3939                 do {
3940                         if (argv[i][0] == '%') {
3941                                 /*
3942                                  * "kill %N" - job kill
3943                                  * Converting to pgrp / pid kill
3944                                  */
3945                                 struct job *jp;
3946                                 char *dst;
3947                                 int j, n;
3948
3949                                 jp = getjob(argv[i], 0);
3950                                 /*
3951                                  * In jobs started under job control, we signal
3952                                  * entire process group by kill -PGRP_ID.
3953                                  * This happens, f.e., in interactive shell.
3954                                  *
3955                                  * Otherwise, we signal each child via
3956                                  * kill PID1 PID2 PID3.
3957                                  * Testcases:
3958                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3959                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3960                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3961                                  */
3962                                 n = jp->nprocs; /* can't be 0 (I hope) */
3963                                 if (jp->jobctl)
3964                                         n = 1;
3965                                 dst = alloca(n * sizeof(int)*4);
3966                                 argv[i] = dst;
3967                                 for (j = 0; j < n; j++) {
3968                                         struct procstat *ps = &jp->ps[j];
3969                                         /* Skip non-running and not-stopped members
3970                                          * (i.e. dead members) of the job
3971                                          */
3972                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3973                                                 continue;
3974                                         /*
3975                                          * kill_main has matching code to expect
3976                                          * leading space. Needed to not confuse
3977                                          * negative pids with "kill -SIGNAL_NO" syntax
3978                                          */
3979                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3980                                 }
3981                                 *dst = '\0';
3982                         }
3983                 } while (argv[++i]);
3984         }
3985         return kill_main(argc, argv);
3986 }
3987
3988 static void
3989 showpipe(struct job *jp /*, FILE *out*/)
3990 {
3991         struct procstat *ps;
3992         struct procstat *psend;
3993
3994         psend = jp->ps + jp->nprocs;
3995         for (ps = jp->ps + 1; ps < psend; ps++)
3996                 printf(" | %s", ps->ps_cmd);
3997         newline_and_flush(stdout);
3998         flush_stdout_stderr();
3999 }
4000
4001
4002 static int
4003 restartjob(struct job *jp, int mode)
4004 {
4005         struct procstat *ps;
4006         int i;
4007         int status;
4008         pid_t pgid;
4009
4010         INT_OFF;
4011         if (jp->state == JOBDONE)
4012                 goto out;
4013         jp->state = JOBRUNNING;
4014         pgid = jp->ps[0].ps_pid;
4015         if (mode == FORK_FG) {
4016                 get_tty_state();
4017                 xtcsetpgrp(ttyfd, pgid);
4018         }
4019         killpg(pgid, SIGCONT);
4020         ps = jp->ps;
4021         i = jp->nprocs;
4022         do {
4023                 if (WIFSTOPPED(ps->ps_status)) {
4024                         ps->ps_status = -1;
4025                 }
4026                 ps++;
4027         } while (--i);
4028  out:
4029         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4030         INT_ON;
4031         return status;
4032 }
4033
4034 static int FAST_FUNC
4035 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4036 {
4037         struct job *jp;
4038         int mode;
4039         int retval;
4040
4041         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4042         nextopt(nullstr);
4043         argv = argptr;
4044         do {
4045                 jp = getjob(*argv, 1);
4046                 if (mode == FORK_BG) {
4047                         set_curjob(jp, CUR_RUNNING);
4048                         printf("[%d] ", jobno(jp));
4049                 }
4050                 out1str(jp->ps[0].ps_cmd);
4051                 showpipe(jp /*, stdout*/);
4052                 retval = restartjob(jp, mode);
4053         } while (*argv && *++argv);
4054         return retval;
4055 }
4056 #endif
4057
4058 static int
4059 sprint_status48(char *s, int status, int sigonly)
4060 {
4061         int col;
4062         int st;
4063
4064         col = 0;
4065         if (!WIFEXITED(status)) {
4066 #if JOBS
4067                 if (WIFSTOPPED(status))
4068                         st = WSTOPSIG(status);
4069                 else
4070 #endif
4071                         st = WTERMSIG(status);
4072                 if (sigonly) {
4073                         if (st == SIGINT || st == SIGPIPE)
4074                                 goto out;
4075 #if JOBS
4076                         if (WIFSTOPPED(status))
4077                                 goto out;
4078 #endif
4079                 }
4080                 st &= 0x7f;
4081 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4082                 col = fmtstr(s, 32, strsignal(st));
4083                 if (WCOREDUMP(status)) {
4084                         strcpy(s + col, " (core dumped)");
4085                         col += sizeof(" (core dumped)")-1;
4086                 }
4087         } else if (!sigonly) {
4088                 st = WEXITSTATUS(status);
4089                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4090         }
4091  out:
4092         return col;
4093 }
4094
4095 static int
4096 wait_block_or_sig(int *status)
4097 {
4098         int pid;
4099
4100         do {
4101                 sigset_t mask;
4102
4103                 /* Poll all children for changes in their state */
4104                 got_sigchld = 0;
4105                 /* if job control is active, accept stopped processes too */
4106                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4107                 if (pid != 0)
4108                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4109
4110                 /* Children exist, but none are ready. Sleep until interesting signal */
4111 #if 1
4112                 sigfillset(&mask);
4113                 sigprocmask(SIG_SETMASK, &mask, &mask);
4114                 while (!got_sigchld && !pending_sig)
4115                         sigsuspend(&mask);
4116                 sigprocmask(SIG_SETMASK, &mask, NULL);
4117 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4118                 while (!got_sigchld && !pending_sig)
4119                         pause();
4120 #endif
4121
4122                 /* If it was SIGCHLD, poll children again */
4123         } while (got_sigchld);
4124
4125         return pid;
4126 }
4127
4128 #define DOWAIT_NONBLOCK 0
4129 #define DOWAIT_BLOCK    1
4130 #define DOWAIT_BLOCK_OR_SIG 2
4131
4132 static int
4133 dowait(int block, struct job *job)
4134 {
4135         int pid;
4136         int status;
4137         struct job *jp;
4138         struct job *thisjob = NULL;
4139
4140         TRACE(("dowait(0x%x) called\n", block));
4141
4142         /* It's wrong to call waitpid() outside of INT_OFF region:
4143          * signal can arrive just after syscall return and handler can
4144          * longjmp away, losing stop/exit notification processing.
4145          * Thus, for "jobs" builtin, and for waiting for a fg job,
4146          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4147          *
4148          * However, for "wait" builtin it is wrong to simply call waitpid()
4149          * in INT_OFF region: "wait" needs to wait for any running job
4150          * to change state, but should exit on any trap too.
4151          * In INT_OFF region, a signal just before syscall entry can set
4152          * pending_sig variables, but we can't check them, and we would
4153          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4154          *
4155          * Because of this, we run inside INT_OFF, but use a special routine
4156          * which combines waitpid() and sigsuspend().
4157          * This is the reason why we need to have a handler for SIGCHLD:
4158          * SIG_DFL handler does not wake sigsuspend().
4159          */
4160         INT_OFF;
4161         if (block == DOWAIT_BLOCK_OR_SIG) {
4162                 pid = wait_block_or_sig(&status);
4163         } else {
4164                 int wait_flags = 0;
4165                 if (block == DOWAIT_NONBLOCK)
4166                         wait_flags = WNOHANG;
4167                 /* if job control is active, accept stopped processes too */
4168                 if (doing_jobctl)
4169                         wait_flags |= WUNTRACED;
4170                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4171                 pid = waitpid(-1, &status, wait_flags);
4172         }
4173         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4174                                 pid, status, errno, strerror(errno)));
4175         if (pid <= 0)
4176                 goto out;
4177
4178         thisjob = NULL;
4179         for (jp = curjob; jp; jp = jp->prev_job) {
4180                 int jobstate;
4181                 struct procstat *ps;
4182                 struct procstat *psend;
4183                 if (jp->state == JOBDONE)
4184                         continue;
4185                 jobstate = JOBDONE;
4186                 ps = jp->ps;
4187                 psend = ps + jp->nprocs;
4188                 do {
4189                         if (ps->ps_pid == pid) {
4190                                 TRACE(("Job %d: changing status of proc %d "
4191                                         "from 0x%x to 0x%x\n",
4192                                         jobno(jp), pid, ps->ps_status, status));
4193                                 ps->ps_status = status;
4194                                 thisjob = jp;
4195                         }
4196                         if (ps->ps_status == -1)
4197                                 jobstate = JOBRUNNING;
4198 #if JOBS
4199                         if (jobstate == JOBRUNNING)
4200                                 continue;
4201                         if (WIFSTOPPED(ps->ps_status)) {
4202                                 jp->stopstatus = ps->ps_status;
4203                                 jobstate = JOBSTOPPED;
4204                         }
4205 #endif
4206                 } while (++ps < psend);
4207                 if (!thisjob)
4208                         continue;
4209
4210                 /* Found the job where one of its processes changed its state.
4211                  * Is there at least one live and running process in this job? */
4212                 if (jobstate != JOBRUNNING) {
4213                         /* No. All live processes in the job are stopped
4214                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4215                          */
4216                         thisjob->changed = 1;
4217                         if (thisjob->state != jobstate) {
4218                                 TRACE(("Job %d: changing state from %d to %d\n",
4219                                         jobno(thisjob), thisjob->state, jobstate));
4220                                 thisjob->state = jobstate;
4221 #if JOBS
4222                                 if (jobstate == JOBSTOPPED)
4223                                         set_curjob(thisjob, CUR_STOPPED);
4224 #endif
4225                         }
4226                 }
4227                 goto out;
4228         }
4229         /* The process wasn't found in job list */
4230 #if JOBS
4231         if (!WIFSTOPPED(status))
4232                 jobless--;
4233 #endif
4234  out:
4235         INT_ON;
4236
4237         if (thisjob && thisjob == job) {
4238                 char s[48 + 1];
4239                 int len;
4240
4241                 len = sprint_status48(s, status, 1);
4242                 if (len) {
4243                         s[len] = '\n';
4244                         s[len + 1] = '\0';
4245                         out2str(s);
4246                 }
4247         }
4248         return pid;
4249 }
4250
4251 #if JOBS
4252 static void
4253 showjob(struct job *jp, int mode)
4254 {
4255         struct procstat *ps;
4256         struct procstat *psend;
4257         int col;
4258         int indent_col;
4259         char s[16 + 16 + 48];
4260         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4261
4262         ps = jp->ps;
4263
4264         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4265                 /* just output process (group) id of pipeline */
4266                 fprintf(out, "%d\n", ps->ps_pid);
4267                 return;
4268         }
4269
4270         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4271         indent_col = col;
4272
4273         if (jp == curjob)
4274                 s[col - 3] = '+';
4275         else if (curjob && jp == curjob->prev_job)
4276                 s[col - 3] = '-';
4277
4278         if (mode & SHOW_PIDS)
4279                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4280
4281         psend = ps + jp->nprocs;
4282
4283         if (jp->state == JOBRUNNING) {
4284                 strcpy(s + col, "Running");
4285                 col += sizeof("Running") - 1;
4286         } else {
4287                 int status = psend[-1].ps_status;
4288                 if (jp->state == JOBSTOPPED)
4289                         status = jp->stopstatus;
4290                 col += sprint_status48(s + col, status, 0);
4291         }
4292         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4293
4294         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4295          * or prints several "PID             | <cmdN>" lines,
4296          * depending on SHOW_PIDS bit.
4297          * We do not print status of individual processes
4298          * between PID and <cmdN>. bash does it, but not very well:
4299          * first line shows overall job status, not process status,
4300          * making it impossible to know 1st process status.
4301          */
4302         goto start;
4303         do {
4304                 /* for each process */
4305                 s[0] = '\0';
4306                 col = 33;
4307                 if (mode & SHOW_PIDS)
4308                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4309  start:
4310                 fprintf(out, "%s%*c%s%s",
4311                                 s,
4312                                 33 - col >= 0 ? 33 - col : 0, ' ',
4313                                 ps == jp->ps ? "" : "| ",
4314                                 ps->ps_cmd
4315                 );
4316         } while (++ps != psend);
4317         newline_and_flush(out);
4318
4319         jp->changed = 0;
4320
4321         if (jp->state == JOBDONE) {
4322                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4323                 freejob(jp);
4324         }
4325 }
4326
4327 /*
4328  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4329  * statuses have changed since the last call to showjobs.
4330  */
4331 static void
4332 showjobs(int mode)
4333 {
4334         struct job *jp;
4335
4336         TRACE(("showjobs(0x%x) called\n", mode));
4337
4338         /* Handle all finished jobs */
4339         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4340                 continue;
4341
4342         for (jp = curjob; jp; jp = jp->prev_job) {
4343                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4344                         showjob(jp, mode);
4345                 }
4346         }
4347 }
4348
4349 static int FAST_FUNC
4350 jobscmd(int argc UNUSED_PARAM, char **argv)
4351 {
4352         int mode, m;
4353
4354         mode = 0;
4355         while ((m = nextopt("lp")) != '\0') {
4356                 if (m == 'l')
4357                         mode |= SHOW_PIDS;
4358                 else
4359                         mode |= SHOW_ONLY_PGID;
4360         }
4361
4362         argv = argptr;
4363         if (*argv) {
4364                 do
4365                         showjob(getjob(*argv, 0), mode);
4366                 while (*++argv);
4367         } else {
4368                 showjobs(mode);
4369         }
4370
4371         return 0;
4372 }
4373 #endif /* JOBS */
4374
4375 /* Called only on finished or stopped jobs (no members are running) */
4376 static int
4377 getstatus(struct job *job)
4378 {
4379         int status;
4380         int retval;
4381         struct procstat *ps;
4382
4383         /* Fetch last member's status */
4384         ps = job->ps + job->nprocs - 1;
4385         status = ps->ps_status;
4386         if (pipefail) {
4387                 /* "set -o pipefail" mode: use last _nonzero_ status */
4388                 while (status == 0 && --ps >= job->ps)
4389                         status = ps->ps_status;
4390         }
4391
4392         retval = WEXITSTATUS(status);
4393         if (!WIFEXITED(status)) {
4394 #if JOBS
4395                 retval = WSTOPSIG(status);
4396                 if (!WIFSTOPPED(status))
4397 #endif
4398                 {
4399                         /* XXX: limits number of signals */
4400                         retval = WTERMSIG(status);
4401 #if JOBS
4402                         if (retval == SIGINT)
4403                                 job->sigint = 1;
4404 #endif
4405                 }
4406                 retval += 128;
4407         }
4408         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4409                 jobno(job), job->nprocs, status, retval));
4410         return retval;
4411 }
4412
4413 static int FAST_FUNC
4414 waitcmd(int argc UNUSED_PARAM, char **argv)
4415 {
4416         struct job *job;
4417         int retval;
4418         struct job *jp;
4419
4420         nextopt(nullstr);
4421         retval = 0;
4422
4423         argv = argptr;
4424         if (!*argv) {
4425                 /* wait for all jobs */
4426                 for (;;) {
4427                         jp = curjob;
4428                         while (1) {
4429                                 if (!jp) /* no running procs */
4430                                         goto ret;
4431                                 if (jp->state == JOBRUNNING)
4432                                         break;
4433                                 jp->waited = 1;
4434                                 jp = jp->prev_job;
4435                         }
4436         /* man bash:
4437          * "When bash is waiting for an asynchronous command via
4438          * the wait builtin, the reception of a signal for which a trap
4439          * has been set will cause the wait builtin to return immediately
4440          * with an exit status greater than 128, immediately after which
4441          * the trap is executed."
4442          */
4443                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4444         /* if child sends us a signal *and immediately exits*,
4445          * dowait() returns pid > 0. Check this case,
4446          * not "if (dowait() < 0)"!
4447          */
4448                         if (pending_sig)
4449                                 goto sigout;
4450                 }
4451         }
4452
4453         retval = 127;
4454         do {
4455                 if (**argv != '%') {
4456                         pid_t pid = number(*argv);
4457                         job = curjob;
4458                         while (1) {
4459                                 if (!job)
4460                                         goto repeat;
4461                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4462                                         break;
4463                                 job = job->prev_job;
4464                         }
4465                 } else {
4466                         job = getjob(*argv, 0);
4467                 }
4468                 /* loop until process terminated or stopped */
4469                 while (job->state == JOBRUNNING) {
4470                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4471                         if (pending_sig)
4472                                 goto sigout;
4473                 }
4474                 job->waited = 1;
4475                 retval = getstatus(job);
4476  repeat: ;
4477         } while (*++argv);
4478
4479  ret:
4480         return retval;
4481  sigout:
4482         retval = 128 + pending_sig;
4483         return retval;
4484 }
4485
4486 static struct job *
4487 growjobtab(void)
4488 {
4489         size_t len;
4490         ptrdiff_t offset;
4491         struct job *jp, *jq;
4492
4493         len = njobs * sizeof(*jp);
4494         jq = jobtab;
4495         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4496
4497         offset = (char *)jp - (char *)jq;
4498         if (offset) {
4499                 /* Relocate pointers */
4500                 size_t l = len;
4501
4502                 jq = (struct job *)((char *)jq + l);
4503                 while (l) {
4504                         l -= sizeof(*jp);
4505                         jq--;
4506 #define joff(p) ((struct job *)((char *)(p) + l))
4507 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4508                         if (joff(jp)->ps == &jq->ps0)
4509                                 jmove(joff(jp)->ps);
4510                         if (joff(jp)->prev_job)
4511                                 jmove(joff(jp)->prev_job);
4512                 }
4513                 if (curjob)
4514                         jmove(curjob);
4515 #undef joff
4516 #undef jmove
4517         }
4518
4519         njobs += 4;
4520         jobtab = jp;
4521         jp = (struct job *)((char *)jp + len);
4522         jq = jp + 3;
4523         do {
4524                 jq->used = 0;
4525         } while (--jq >= jp);
4526         return jp;
4527 }
4528
4529 /*
4530  * Return a new job structure.
4531  * Called with interrupts off.
4532  */
4533 static struct job *
4534 makejob(/*union node *node,*/ int nprocs)
4535 {
4536         int i;
4537         struct job *jp;
4538
4539         for (i = njobs, jp = jobtab; ; jp++) {
4540                 if (--i < 0) {
4541                         jp = growjobtab();
4542                         break;
4543                 }
4544                 if (jp->used == 0)
4545                         break;
4546                 if (jp->state != JOBDONE || !jp->waited)
4547                         continue;
4548 #if JOBS
4549                 if (doing_jobctl)
4550                         continue;
4551 #endif
4552                 freejob(jp);
4553                 break;
4554         }
4555         memset(jp, 0, sizeof(*jp));
4556 #if JOBS
4557         /* jp->jobctl is a bitfield.
4558          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4559         if (doing_jobctl)
4560                 jp->jobctl = 1;
4561 #endif
4562         jp->prev_job = curjob;
4563         curjob = jp;
4564         jp->used = 1;
4565         jp->ps = &jp->ps0;
4566         if (nprocs > 1) {
4567                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4568         }
4569         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4570                                 jobno(jp)));
4571         return jp;
4572 }
4573
4574 #if JOBS
4575 /*
4576  * Return a string identifying a command (to be printed by the
4577  * jobs command).
4578  */
4579 static char *cmdnextc;
4580
4581 static void
4582 cmdputs(const char *s)
4583 {
4584         static const char vstype[VSTYPE + 1][3] = {
4585                 "", "}", "-", "+", "?", "=",
4586                 "%", "%%", "#", "##"
4587                 IF_BASH_SUBSTR(, ":")
4588                 IF_BASH_PATTERN_SUBST(, "/", "//")
4589         };
4590
4591         const char *p, *str;
4592         char cc[2];
4593         char *nextc;
4594         unsigned char c;
4595         unsigned char subtype = 0;
4596         int quoted = 0;
4597
4598         cc[1] = '\0';
4599         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4600         p = s;
4601         while ((c = *p++) != '\0') {
4602                 str = NULL;
4603                 switch (c) {
4604                 case CTLESC:
4605                         c = *p++;
4606                         break;
4607                 case CTLVAR:
4608                         subtype = *p++;
4609                         if ((subtype & VSTYPE) == VSLENGTH)
4610                                 str = "${#";
4611                         else
4612                                 str = "${";
4613                         goto dostr;
4614                 case CTLENDVAR:
4615                         str = "\"}" + !(quoted & 1);
4616                         quoted >>= 1;
4617                         subtype = 0;
4618                         goto dostr;
4619                 case CTLBACKQ:
4620                         str = "$(...)";
4621                         goto dostr;
4622 #if ENABLE_FEATURE_SH_MATH
4623                 case CTLARI:
4624                         str = "$((";
4625                         goto dostr;
4626                 case CTLENDARI:
4627                         str = "))";
4628                         goto dostr;
4629 #endif
4630                 case CTLQUOTEMARK:
4631                         quoted ^= 1;
4632                         c = '"';
4633                         break;
4634                 case '=':
4635                         if (subtype == 0)
4636                                 break;
4637                         if ((subtype & VSTYPE) != VSNORMAL)
4638                                 quoted <<= 1;
4639                         str = vstype[subtype & VSTYPE];
4640                         if (subtype & VSNUL)
4641                                 c = ':';
4642                         else
4643                                 goto checkstr;
4644                         break;
4645                 case '\'':
4646                 case '\\':
4647                 case '"':
4648                 case '$':
4649                         /* These can only happen inside quotes */
4650                         cc[0] = c;
4651                         str = cc;
4652 //FIXME:
4653 // $ true $$ &
4654 // $ <cr>
4655 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4656                         c = '\\';
4657                         break;
4658                 default:
4659                         break;
4660                 }
4661                 USTPUTC(c, nextc);
4662  checkstr:
4663                 if (!str)
4664                         continue;
4665  dostr:
4666                 while ((c = *str++) != '\0') {
4667                         USTPUTC(c, nextc);
4668                 }
4669         } /* while *p++ not NUL */
4670
4671         if (quoted & 1) {
4672                 USTPUTC('"', nextc);
4673         }
4674         *nextc = 0;
4675         cmdnextc = nextc;
4676 }
4677
4678 /* cmdtxt() and cmdlist() call each other */
4679 static void cmdtxt(union node *n);
4680
4681 static void
4682 cmdlist(union node *np, int sep)
4683 {
4684         for (; np; np = np->narg.next) {
4685                 if (!sep)
4686                         cmdputs(" ");
4687                 cmdtxt(np);
4688                 if (sep && np->narg.next)
4689                         cmdputs(" ");
4690         }
4691 }
4692
4693 static void
4694 cmdtxt(union node *n)
4695 {
4696         union node *np;
4697         struct nodelist *lp;
4698         const char *p;
4699
4700         if (!n)
4701                 return;
4702         switch (n->type) {
4703         default:
4704 #if DEBUG
4705                 abort();
4706 #endif
4707         case NPIPE:
4708                 lp = n->npipe.cmdlist;
4709                 for (;;) {
4710                         cmdtxt(lp->n);
4711                         lp = lp->next;
4712                         if (!lp)
4713                                 break;
4714                         cmdputs(" | ");
4715                 }
4716                 break;
4717         case NSEMI:
4718                 p = "; ";
4719                 goto binop;
4720         case NAND:
4721                 p = " && ";
4722                 goto binop;
4723         case NOR:
4724                 p = " || ";
4725  binop:
4726                 cmdtxt(n->nbinary.ch1);
4727                 cmdputs(p);
4728                 n = n->nbinary.ch2;
4729                 goto donode;
4730         case NREDIR:
4731         case NBACKGND:
4732                 n = n->nredir.n;
4733                 goto donode;
4734         case NNOT:
4735                 cmdputs("!");
4736                 n = n->nnot.com;
4737  donode:
4738                 cmdtxt(n);
4739                 break;
4740         case NIF:
4741                 cmdputs("if ");
4742                 cmdtxt(n->nif.test);
4743                 cmdputs("; then ");
4744                 if (n->nif.elsepart) {
4745                         cmdtxt(n->nif.ifpart);
4746                         cmdputs("; else ");
4747                         n = n->nif.elsepart;
4748                 } else {
4749                         n = n->nif.ifpart;
4750                 }
4751                 p = "; fi";
4752                 goto dotail;
4753         case NSUBSHELL:
4754                 cmdputs("(");
4755                 n = n->nredir.n;
4756                 p = ")";
4757                 goto dotail;
4758         case NWHILE:
4759                 p = "while ";
4760                 goto until;
4761         case NUNTIL:
4762                 p = "until ";
4763  until:
4764                 cmdputs(p);
4765                 cmdtxt(n->nbinary.ch1);
4766                 n = n->nbinary.ch2;
4767                 p = "; done";
4768  dodo:
4769                 cmdputs("; do ");
4770  dotail:
4771                 cmdtxt(n);
4772                 goto dotail2;
4773         case NFOR:
4774                 cmdputs("for ");
4775                 cmdputs(n->nfor.var);
4776                 cmdputs(" in ");
4777                 cmdlist(n->nfor.args, 1);
4778                 n = n->nfor.body;
4779                 p = "; done";
4780                 goto dodo;
4781         case NDEFUN:
4782                 cmdputs(n->narg.text);
4783                 p = "() { ... }";
4784                 goto dotail2;
4785         case NCMD:
4786                 cmdlist(n->ncmd.args, 1);
4787                 cmdlist(n->ncmd.redirect, 0);
4788                 break;
4789         case NARG:
4790                 p = n->narg.text;
4791  dotail2:
4792                 cmdputs(p);
4793                 break;
4794         case NHERE:
4795         case NXHERE:
4796                 p = "<<...";
4797                 goto dotail2;
4798         case NCASE:
4799                 cmdputs("case ");
4800                 cmdputs(n->ncase.expr->narg.text);
4801                 cmdputs(" in ");
4802                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4803                         cmdtxt(np->nclist.pattern);
4804                         cmdputs(") ");
4805                         cmdtxt(np->nclist.body);
4806                         cmdputs(";; ");
4807                 }
4808                 p = "esac";
4809                 goto dotail2;
4810         case NTO:
4811                 p = ">";
4812                 goto redir;
4813         case NCLOBBER:
4814                 p = ">|";
4815                 goto redir;
4816         case NAPPEND:
4817                 p = ">>";
4818                 goto redir;
4819 #if BASH_REDIR_OUTPUT
4820         case NTO2:
4821 #endif
4822         case NTOFD:
4823                 p = ">&";
4824                 goto redir;
4825         case NFROM:
4826                 p = "<";
4827                 goto redir;
4828         case NFROMFD:
4829                 p = "<&";
4830                 goto redir;
4831         case NFROMTO:
4832                 p = "<>";
4833  redir:
4834                 cmdputs(utoa(n->nfile.fd));
4835                 cmdputs(p);
4836                 if (n->type == NTOFD || n->type == NFROMFD) {
4837                         if (n->ndup.dupfd >= 0)
4838                                 cmdputs(utoa(n->ndup.dupfd));
4839                         else
4840                                 cmdputs("-");
4841                         break;
4842                 }
4843                 n = n->nfile.fname;
4844                 goto donode;
4845         }
4846 }
4847
4848 static char *
4849 commandtext(union node *n)
4850 {
4851         char *name;
4852
4853         STARTSTACKSTR(cmdnextc);
4854         cmdtxt(n);
4855         name = stackblock();
4856         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4857         return ckstrdup(name);
4858 }
4859 #endif /* JOBS */
4860
4861 /*
4862  * Fork off a subshell.  If we are doing job control, give the subshell its
4863  * own process group.  Jp is a job structure that the job is to be added to.
4864  * N is the command that will be evaluated by the child.  Both jp and n may
4865  * be NULL.  The mode parameter can be one of the following:
4866  *      FORK_FG - Fork off a foreground process.
4867  *      FORK_BG - Fork off a background process.
4868  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4869  *                   process group even if job control is on.
4870  *
4871  * When job control is turned off, background processes have their standard
4872  * input redirected to /dev/null (except for the second and later processes
4873  * in a pipeline).
4874  *
4875  * Called with interrupts off.
4876  */
4877 /*
4878  * Clear traps on a fork.
4879  */
4880 static void
4881 clear_traps(void)
4882 {
4883         char **tp;
4884
4885         INT_OFF;
4886         for (tp = trap; tp < &trap[NSIG]; tp++) {
4887                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4888                         if (trap_ptr == trap)
4889                                 free(*tp);
4890                         /* else: it "belongs" to trap_ptr vector, don't free */
4891                         *tp = NULL;
4892                         if ((tp - trap) != 0)
4893                                 setsignal(tp - trap);
4894                 }
4895         }
4896         may_have_traps = 0;
4897         INT_ON;
4898 }
4899
4900 /* Lives far away from here, needed for forkchild */
4901 static void closescript(void);
4902
4903 /* Called after fork(), in child */
4904 /* jp and n are NULL when called by openhere() for heredoc support */
4905 static NOINLINE void
4906 forkchild(struct job *jp, union node *n, int mode)
4907 {
4908         int oldlvl;
4909
4910         TRACE(("Child shell %d\n", getpid()));
4911         oldlvl = shlvl;
4912         shlvl++;
4913
4914         /* man bash: "Non-builtin commands run by bash have signal handlers
4915          * set to the values inherited by the shell from its parent".
4916          * Do we do it correctly? */
4917
4918         closescript();
4919
4920         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4921          && n && n->type == NCMD        /* is it single cmd? */
4922         /* && n->ncmd.args->type == NARG - always true? */
4923          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4924          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4925         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4926         ) {
4927                 TRACE(("Trap hack\n"));
4928                 /* Awful hack for `trap` or $(trap).
4929                  *
4930                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4931                  * contains an example where "trap" is executed in a subshell:
4932                  *
4933                  * save_traps=$(trap)
4934                  * ...
4935                  * eval "$save_traps"
4936                  *
4937                  * Standard does not say that "trap" in subshell shall print
4938                  * parent shell's traps. It only says that its output
4939                  * must have suitable form, but then, in the above example
4940                  * (which is not supposed to be normative), it implies that.
4941                  *
4942                  * bash (and probably other shell) does implement it
4943                  * (traps are reset to defaults, but "trap" still shows them),
4944                  * but as a result, "trap" logic is hopelessly messed up:
4945                  *
4946                  * # trap
4947                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4948                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4949                  * # true | trap   <--- trap is in subshell - no output (ditto)
4950                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4951                  * trap -- 'echo Ho' SIGWINCH
4952                  * # echo `(trap)`         <--- in subshell in subshell - output
4953                  * trap -- 'echo Ho' SIGWINCH
4954                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4955                  * trap -- 'echo Ho' SIGWINCH
4956                  *
4957                  * The rules when to forget and when to not forget traps
4958                  * get really complex and nonsensical.
4959                  *
4960                  * Our solution: ONLY bare $(trap) or `trap` is special.
4961                  */
4962                 /* Save trap handler strings for trap builtin to print */
4963                 trap_ptr = xmemdup(trap, sizeof(trap));
4964                 /* Fall through into clearing traps */
4965         }
4966         clear_traps();
4967 #if JOBS
4968         /* do job control only in root shell */
4969         doing_jobctl = 0;
4970         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4971                 pid_t pgrp;
4972
4973                 if (jp->nprocs == 0)
4974                         pgrp = getpid();
4975                 else
4976                         pgrp = jp->ps[0].ps_pid;
4977                 /* this can fail because we are doing it in the parent also */
4978                 setpgid(0, pgrp);
4979                 if (mode == FORK_FG)
4980                         xtcsetpgrp(ttyfd, pgrp);
4981                 setsignal(SIGTSTP);
4982                 setsignal(SIGTTOU);
4983         } else
4984 #endif
4985         if (mode == FORK_BG) {
4986                 /* man bash: "When job control is not in effect,
4987                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4988                 ignoresig(SIGINT);
4989                 ignoresig(SIGQUIT);
4990                 if (jp->nprocs == 0) {
4991                         close(0);
4992                         if (open(bb_dev_null, O_RDONLY) != 0)
4993                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4994                 }
4995         }
4996         if (oldlvl == 0) {
4997                 if (iflag) { /* why if iflag only? */
4998                         setsignal(SIGINT);
4999                         setsignal(SIGTERM);
5000                 }
5001                 /* man bash:
5002                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5003                  * commands run by bash have signal handlers
5004                  * set to the values inherited by the shell
5005                  * from its parent".
5006                  * Take care of the second rule: */
5007                 setsignal(SIGQUIT);
5008         }
5009 #if JOBS
5010         if (n && n->type == NCMD
5011          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5012         ) {
5013                 TRACE(("Job hack\n"));
5014                 /* "jobs": we do not want to clear job list for it,
5015                  * instead we remove only _its_ own_ job from job list.
5016                  * This makes "jobs .... | cat" more useful.
5017                  */
5018                 freejob(curjob);
5019                 return;
5020         }
5021 #endif
5022         for (jp = curjob; jp; jp = jp->prev_job)
5023                 freejob(jp);
5024         jobless = 0;
5025 }
5026
5027 /* Called after fork(), in parent */
5028 #if !JOBS
5029 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5030 #endif
5031 static void
5032 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5033 {
5034         TRACE(("In parent shell: child = %d\n", pid));
5035         if (!jp) {
5036                 /* jp is NULL when called by openhere() for heredoc support */
5037                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5038                         continue;
5039                 jobless++;
5040                 return;
5041         }
5042 #if JOBS
5043         if (mode != FORK_NOJOB && jp->jobctl) {
5044                 int pgrp;
5045
5046                 if (jp->nprocs == 0)
5047                         pgrp = pid;
5048                 else
5049                         pgrp = jp->ps[0].ps_pid;
5050                 /* This can fail because we are doing it in the child also */
5051                 setpgid(pid, pgrp);
5052         }
5053 #endif
5054         if (mode == FORK_BG) {
5055                 backgndpid = pid;               /* set $! */
5056                 set_curjob(jp, CUR_RUNNING);
5057         }
5058         if (jp) {
5059                 struct procstat *ps = &jp->ps[jp->nprocs++];
5060                 ps->ps_pid = pid;
5061                 ps->ps_status = -1;
5062                 ps->ps_cmd = nullstr;
5063 #if JOBS
5064                 if (doing_jobctl && n)
5065                         ps->ps_cmd = commandtext(n);
5066 #endif
5067         }
5068 }
5069
5070 /* jp and n are NULL when called by openhere() for heredoc support */
5071 static int
5072 forkshell(struct job *jp, union node *n, int mode)
5073 {
5074         int pid;
5075
5076         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5077         pid = fork();
5078         if (pid < 0) {
5079                 TRACE(("Fork failed, errno=%d", errno));
5080                 if (jp)
5081                         freejob(jp);
5082                 ash_msg_and_raise_error("can't fork");
5083         }
5084         if (pid == 0) {
5085                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5086                 forkchild(jp, n, mode);
5087         } else {
5088                 forkparent(jp, n, mode, pid);
5089         }
5090         return pid;
5091 }
5092
5093 /*
5094  * Wait for job to finish.
5095  *
5096  * Under job control we have the problem that while a child process
5097  * is running interrupts generated by the user are sent to the child
5098  * but not to the shell.  This means that an infinite loop started by
5099  * an interactive user may be hard to kill.  With job control turned off,
5100  * an interactive user may place an interactive program inside a loop.
5101  * If the interactive program catches interrupts, the user doesn't want
5102  * these interrupts to also abort the loop.  The approach we take here
5103  * is to have the shell ignore interrupt signals while waiting for a
5104  * foreground process to terminate, and then send itself an interrupt
5105  * signal if the child process was terminated by an interrupt signal.
5106  * Unfortunately, some programs want to do a bit of cleanup and then
5107  * exit on interrupt; unless these processes terminate themselves by
5108  * sending a signal to themselves (instead of calling exit) they will
5109  * confuse this approach.
5110  *
5111  * Called with interrupts off.
5112  */
5113 static int
5114 waitforjob(struct job *jp)
5115 {
5116         int st;
5117
5118         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5119
5120         INT_OFF;
5121         while (jp->state == JOBRUNNING) {
5122                 /* In non-interactive shells, we _can_ get
5123                  * a keyboard signal here and be EINTRed,
5124                  * but we just loop back, waiting for command to complete.
5125                  *
5126                  * man bash:
5127                  * "If bash is waiting for a command to complete and receives
5128                  * a signal for which a trap has been set, the trap
5129                  * will not be executed until the command completes."
5130                  *
5131                  * Reality is that even if trap is not set, bash
5132                  * will not act on the signal until command completes.
5133                  * Try this. sleep5intoff.c:
5134                  * #include <signal.h>
5135                  * #include <unistd.h>
5136                  * int main() {
5137                  *         sigset_t set;
5138                  *         sigemptyset(&set);
5139                  *         sigaddset(&set, SIGINT);
5140                  *         sigaddset(&set, SIGQUIT);
5141                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5142                  *         sleep(5);
5143                  *         return 0;
5144                  * }
5145                  * $ bash -c './sleep5intoff; echo hi'
5146                  * ^C^C^C^C <--- pressing ^C once a second
5147                  * $ _
5148                  * $ bash -c './sleep5intoff; echo hi'
5149                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5150                  * $ _
5151                  */
5152                 dowait(DOWAIT_BLOCK, jp);
5153         }
5154         INT_ON;
5155
5156         st = getstatus(jp);
5157 #if JOBS
5158         if (jp->jobctl) {
5159                 xtcsetpgrp(ttyfd, rootpid);
5160                 restore_tty_if_stopped_or_signaled(jp);
5161
5162                 /*
5163                  * This is truly gross.
5164                  * If we're doing job control, then we did a TIOCSPGRP which
5165                  * caused us (the shell) to no longer be in the controlling
5166                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5167                  * intuit from the subprocess exit status whether a SIGINT
5168                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5169                  */
5170                 if (jp->sigint) /* TODO: do the same with all signals */
5171                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5172         }
5173         if (jp->state == JOBDONE)
5174 #endif
5175                 freejob(jp);
5176         return st;
5177 }
5178
5179 /*
5180  * return 1 if there are stopped jobs, otherwise 0
5181  */
5182 static int
5183 stoppedjobs(void)
5184 {
5185         struct job *jp;
5186         int retval;
5187
5188         retval = 0;
5189         if (job_warning)
5190                 goto out;
5191         jp = curjob;
5192         if (jp && jp->state == JOBSTOPPED) {
5193                 out2str("You have stopped jobs.\n");
5194                 job_warning = 2;
5195                 retval++;
5196         }
5197  out:
5198         return retval;
5199 }
5200
5201
5202 /*
5203  * Code for dealing with input/output redirection.
5204  */
5205
5206 #undef EMPTY
5207 #undef CLOSED
5208 #define EMPTY -2                /* marks an unused slot in redirtab */
5209 #define CLOSED -1               /* marks a slot of previously-closed fd */
5210
5211 /*
5212  * Handle here documents.  Normally we fork off a process to write the
5213  * data to a pipe.  If the document is short, we can stuff the data in
5214  * the pipe without forking.
5215  */
5216 /* openhere needs this forward reference */
5217 static void expandhere(union node *arg, int fd);
5218 static int
5219 openhere(union node *redir)
5220 {
5221         int pip[2];
5222         size_t len = 0;
5223
5224         if (pipe(pip) < 0)
5225                 ash_msg_and_raise_error("pipe call failed");
5226         if (redir->type == NHERE) {
5227                 len = strlen(redir->nhere.doc->narg.text);
5228                 if (len <= PIPE_BUF) {
5229                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5230                         goto out;
5231                 }
5232         }
5233         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5234                 /* child */
5235                 close(pip[0]);
5236                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5237                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5238                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5239                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5240                 signal(SIGPIPE, SIG_DFL);
5241                 if (redir->type == NHERE)
5242                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5243                 else /* NXHERE */
5244                         expandhere(redir->nhere.doc, pip[1]);
5245                 _exit(EXIT_SUCCESS);
5246         }
5247  out:
5248         close(pip[1]);
5249         return pip[0];
5250 }
5251
5252 static int
5253 openredirect(union node *redir)
5254 {
5255         struct stat sb;
5256         char *fname;
5257         int f;
5258
5259         switch (redir->nfile.type) {
5260 /* Can't happen, our single caller does this itself */
5261 //      case NTOFD:
5262 //      case NFROMFD:
5263 //              return -1;
5264         case NHERE:
5265         case NXHERE:
5266                 return openhere(redir);
5267         }
5268
5269         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5270          * allocated space. Do it only when we know it is safe.
5271          */
5272         fname = redir->nfile.expfname;
5273
5274         switch (redir->nfile.type) {
5275         default:
5276 #if DEBUG
5277                 abort();
5278 #endif
5279         case NFROM:
5280                 f = open(fname, O_RDONLY);
5281                 if (f < 0)
5282                         goto eopen;
5283                 break;
5284         case NFROMTO:
5285                 f = open(fname, O_RDWR|O_CREAT, 0666);
5286                 if (f < 0)
5287                         goto ecreate;
5288                 break;
5289         case NTO:
5290 #if BASH_REDIR_OUTPUT
5291         case NTO2:
5292 #endif
5293                 /* Take care of noclobber mode. */
5294                 if (Cflag) {
5295                         if (stat(fname, &sb) < 0) {
5296                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5297                                 if (f < 0)
5298                                         goto ecreate;
5299                         } else if (!S_ISREG(sb.st_mode)) {
5300                                 f = open(fname, O_WRONLY, 0666);
5301                                 if (f < 0)
5302                                         goto ecreate;
5303                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5304                                         close(f);
5305                                         errno = EEXIST;
5306                                         goto ecreate;
5307                                 }
5308                         } else {
5309                                 errno = EEXIST;
5310                                 goto ecreate;
5311                         }
5312                         break;
5313                 }
5314                 /* FALLTHROUGH */
5315         case NCLOBBER:
5316                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5317                 if (f < 0)
5318                         goto ecreate;
5319                 break;
5320         case NAPPEND:
5321                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5322                 if (f < 0)
5323                         goto ecreate;
5324                 break;
5325         }
5326
5327         return f;
5328  ecreate:
5329         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5330  eopen:
5331         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5332 }
5333
5334 /*
5335  * Copy a file descriptor to be >= 10. Throws exception on error.
5336  */
5337 static int
5338 savefd(int from)
5339 {
5340         int newfd;
5341         int err;
5342
5343         newfd = fcntl(from, F_DUPFD, 10);
5344         err = newfd < 0 ? errno : 0;
5345         if (err != EBADF) {
5346                 if (err)
5347                         ash_msg_and_raise_perror("%d", from);
5348                 close(from);
5349                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5350         }
5351
5352         return newfd;
5353 }
5354 static int
5355 dup2_or_raise(int from, int to)
5356 {
5357         int newfd;
5358
5359         newfd = (from != to) ? dup2(from, to) : to;
5360         if (newfd < 0) {
5361                 /* Happens when source fd is not open: try "echo >&99" */
5362                 ash_msg_and_raise_perror("%d", from);
5363         }
5364         return newfd;
5365 }
5366 static int
5367 fcntl_F_DUPFD(int fd, int avoid_fd)
5368 {
5369         int newfd;
5370  repeat:
5371         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5372         if (newfd < 0) {
5373                 if (errno == EBUSY)
5374                         goto repeat;
5375                 if (errno == EINTR)
5376                         goto repeat;
5377         }
5378         return newfd;
5379 }
5380 static int
5381 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5382 {
5383         int newfd;
5384  repeat:
5385         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5386         if (newfd < 0) {
5387                 if (errno == EBUSY)
5388                         goto repeat;
5389                 if (errno == EINTR)
5390                         goto repeat;
5391                 /* fd was not open? */
5392                 if (errno == EBADF)
5393                         return fd;
5394                 ash_msg_and_raise_perror("%d", newfd);
5395         }
5396         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5397         close(fd);
5398         return newfd;
5399 }
5400
5401 /* Struct def and variable are moved down to the first usage site */
5402 struct squirrel {
5403         int orig_fd;
5404         int moved_to;
5405 };
5406 struct redirtab {
5407         struct redirtab *next;
5408         int pair_count;
5409         struct squirrel two_fd[];
5410 };
5411 #define redirlist (G_var.redirlist)
5412
5413 static void
5414 add_squirrel_closed(struct redirtab *sq, int fd)
5415 {
5416         int i;
5417
5418         if (!sq)
5419                 return;
5420
5421         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5422                 /* If we collide with an already moved fd... */
5423                 if (fd == sq->two_fd[i].orig_fd) {
5424                         /* Examples:
5425                          * "echo 3>FILE 3>&- 3>FILE"
5426                          * "echo 3>&- 3>FILE"
5427                          * No need for last redirect to insert
5428                          * another "need to close 3" indicator.
5429                          */
5430                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5431                         return;
5432                 }
5433         }
5434         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5435         sq->two_fd[i].orig_fd = fd;
5436         sq->two_fd[i].moved_to = CLOSED;
5437 }
5438
5439 static int
5440 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5441 {
5442         int i, new_fd;
5443
5444         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5445                 avoid_fd = 9;
5446
5447 #if JOBS
5448         if (fd == ttyfd) {
5449                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5450                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5451                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5452                 return 1; /* "we closed fd" */
5453         }
5454 #endif
5455         /* Are we called from redirect(0)? E.g. redirect
5456          * in a forked child. No need to save fds,
5457          * we aren't going to use them anymore, ok to trash.
5458          */
5459         if (!sq)
5460                 return 0;
5461
5462         /* If this one of script's fds? */
5463         if (fd != 0) {
5464                 struct parsefile *pf = g_parsefile;
5465                 while (pf) {
5466                         /* We skip fd == 0 case because of the following:
5467                          * $ ash  # running ash interactively
5468                          * $ . ./script.sh
5469                          * and in script.sh: "exec 9>&0".
5470                          * Even though top-level pf_fd _is_ 0,
5471                          * it's still ok to use it: "read" builtin uses it,
5472                          * why should we cripple "exec" builtin?
5473                          */
5474                         if (fd == pf->pf_fd) {
5475                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5476                                 return 1; /* "we closed fd" */
5477                         }
5478                         pf = pf->prev;
5479                 }
5480         }
5481
5482         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5483
5484         /* First: do we collide with some already moved fds? */
5485         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5486                 /* If we collide with an already moved fd... */
5487                 if (fd == sq->two_fd[i].moved_to) {
5488                         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5489                         sq->two_fd[i].moved_to = new_fd;
5490                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5491                         if (new_fd < 0) /* what? */
5492                                 xfunc_die();
5493                         return 0; /* "we did not close fd" */
5494                 }
5495                 if (fd == sq->two_fd[i].orig_fd) {
5496                         /* Example: echo Hello >/dev/null 1>&2 */
5497                         TRACE(("redirect_fd %d: already moved\n", fd));
5498                         return 0; /* "we did not close fd" */
5499                 }
5500         }
5501
5502         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5503         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5504         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5505         if (new_fd < 0) {
5506                 if (errno != EBADF)
5507                         xfunc_die();
5508                 /* new_fd = CLOSED; - already is -1 */
5509         }
5510         sq->two_fd[i].moved_to = new_fd;
5511         sq->two_fd[i].orig_fd = fd;
5512
5513         /* if we move stderr, let "set -x" code know */
5514         if (fd == preverrout_fd)
5515                 preverrout_fd = new_fd;
5516
5517         return 0; /* "we did not close fd" */
5518 }
5519
5520 static int
5521 internally_opened_fd(int fd, struct redirtab *sq)
5522 {
5523         int i;
5524 #if JOBS
5525         if (fd == ttyfd)
5526                 return 1;
5527 #endif
5528         /* If this one of script's fds? */
5529         if (fd != 0) {
5530                 struct parsefile *pf = g_parsefile;
5531                 while (pf) {
5532                         if (fd == pf->pf_fd)
5533                                 return 1;
5534                         pf = pf->prev;
5535                 }
5536         }
5537
5538         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5539                 if (fd == sq->two_fd[i].moved_to)
5540                         return 1;
5541         }
5542         return 0;
5543 }
5544
5545 /*
5546  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5547  * old file descriptors are stashed away so that the redirection can be
5548  * undone by calling popredir.
5549  */
5550 /* flags passed to redirect */
5551 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5552 static void
5553 redirect(union node *redir, int flags)
5554 {
5555         struct redirtab *sv;
5556
5557         if (!redir)
5558                 return;
5559
5560         sv = NULL;
5561         INT_OFF;
5562         if (flags & REDIR_PUSH)
5563                 sv = redirlist;
5564         do {
5565                 int fd;
5566                 int newfd;
5567                 int close_fd;
5568                 int closed;
5569
5570                 fd = redir->nfile.fd;
5571                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5572                         //bb_error_msg("doing %d > %d", fd, newfd);
5573                         newfd = redir->ndup.dupfd;
5574                         close_fd = -1;
5575                 } else {
5576                         newfd = openredirect(redir); /* always >= 0 */
5577                         if (fd == newfd) {
5578                                 /* open() gave us precisely the fd we wanted.
5579                                  * This means that this fd was not busy
5580                                  * (not opened to anywhere).
5581                                  * Remember to close it on restore:
5582                                  */
5583                                 add_squirrel_closed(sv, fd);
5584                                 continue;
5585                         }
5586                         close_fd = newfd;
5587                 }
5588
5589                 if (fd == newfd)
5590                         continue;
5591
5592                 /* if "N>FILE": move newfd to fd */
5593                 /* if "N>&M": dup newfd to fd */
5594                 /* if "N>&-": close fd (newfd is -1) */
5595
5596  IF_BASH_REDIR_OUTPUT(redirect_more:)
5597
5598                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5599                 if (newfd == -1) {
5600                         /* "N>&-" means "close me" */
5601                         if (!closed) {
5602                                 /* ^^^ optimization: saving may already
5603                                  * have closed it. If not... */
5604                                 close(fd);
5605                         }
5606                 } else {
5607                         /* if newfd is a script fd or saved fd, simulate EBADF */
5608                         if (internally_opened_fd(newfd, sv)) {
5609                                 errno = EBADF;
5610                                 ash_msg_and_raise_perror("%d", newfd);
5611                         }
5612                         dup2_or_raise(newfd, fd);
5613                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5614                                 close(close_fd);
5615 #if BASH_REDIR_OUTPUT
5616                         if (redir->nfile.type == NTO2 && fd == 1) {
5617                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5618                                 fd = 2;
5619                                 newfd = 1;
5620                                 close_fd = -1;
5621                                 goto redirect_more;
5622                         }
5623 #endif
5624                 }
5625         } while ((redir = redir->nfile.next) != NULL);
5626         INT_ON;
5627
5628 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5629 #define REDIR_SAVEFD2 0
5630         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5631         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5632         // not only for calls with flags containing REDIR_SAVEFD2.
5633         // We do this unconditionally (see save_fd_on_redirect()).
5634         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5635         //      preverrout_fd = copied_fd2;
5636 }
5637
5638 static int
5639 redirectsafe(union node *redir, int flags)
5640 {
5641         int err;
5642         volatile int saveint;
5643         struct jmploc *volatile savehandler = exception_handler;
5644         struct jmploc jmploc;
5645
5646         SAVE_INT(saveint);
5647         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5648         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5649         if (!err) {
5650                 exception_handler = &jmploc;
5651                 redirect(redir, flags);
5652         }
5653         exception_handler = savehandler;
5654         if (err && exception_type != EXERROR)
5655                 longjmp(exception_handler->loc, 1);
5656         RESTORE_INT(saveint);
5657         return err;
5658 }
5659
5660 static struct redirtab*
5661 pushredir(union node *redir)
5662 {
5663         struct redirtab *sv;
5664         int i;
5665
5666         if (!redir)
5667                 return redirlist;
5668
5669         i = 0;
5670         do {
5671                 i++;
5672 #if BASH_REDIR_OUTPUT
5673                 if (redir->nfile.type == NTO2)
5674                         i++;
5675 #endif
5676                 redir = redir->nfile.next;
5677         } while (redir);
5678
5679         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5680         sv->pair_count = i;
5681         while (--i >= 0)
5682                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5683         sv->next = redirlist;
5684         redirlist = sv;
5685         return sv->next;
5686 }
5687
5688 /*
5689  * Undo the effects of the last redirection.
5690  */
5691 static void
5692 popredir(int drop)
5693 {
5694         struct redirtab *rp;
5695         int i;
5696
5697         if (redirlist == NULL)
5698                 return;
5699         INT_OFF;
5700         rp = redirlist;
5701         for (i = 0; i < rp->pair_count; i++) {
5702                 int fd = rp->two_fd[i].orig_fd;
5703                 int copy = rp->two_fd[i].moved_to;
5704                 if (copy == CLOSED) {
5705                         if (!drop)
5706                                 close(fd);
5707                         continue;
5708                 }
5709                 if (copy != EMPTY) {
5710                         if (!drop) {
5711                                 /*close(fd);*/
5712                                 dup2_or_raise(copy, fd);
5713                         }
5714                         close(copy);
5715                 }
5716         }
5717         redirlist = rp->next;
5718         free(rp);
5719         INT_ON;
5720 }
5721
5722 static void
5723 unwindredir(struct redirtab *stop)
5724 {
5725         while (redirlist != stop)
5726                 popredir(/*drop:*/ 0);
5727 }
5728
5729
5730 /* ============ Routines to expand arguments to commands
5731  *
5732  * We have to deal with backquotes, shell variables, and file metacharacters.
5733  */
5734
5735 #if ENABLE_FEATURE_SH_MATH
5736 static arith_t
5737 ash_arith(const char *s)
5738 {
5739         arith_state_t math_state;
5740         arith_t result;
5741
5742         math_state.lookupvar = lookupvar;
5743         math_state.setvar    = setvar0;
5744         //math_state.endofname = endofname;
5745
5746         INT_OFF;
5747         result = arith(&math_state, s);
5748         if (math_state.errmsg)
5749                 ash_msg_and_raise_error(math_state.errmsg);
5750         INT_ON;
5751
5752         return result;
5753 }
5754 #endif
5755
5756 /*
5757  * expandarg flags
5758  */
5759 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5760 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5761 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5762 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5763 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5764  * POSIX says for this case:
5765  *  Pathname expansion shall not be performed on the word by a
5766  *  non-interactive shell; an interactive shell may perform it, but shall
5767  *  do so only when the expansion would result in one word.
5768  * Currently, our code complies to the above rule by never globbing
5769  * redirection filenames.
5770  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5771  * (this means that on a typical Linux distro, bash almost always
5772  * performs globbing, and thus diverges from what we do).
5773  */
5774 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5775 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5776 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5777 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5778 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5779 /*
5780  * rmescape() flags
5781  */
5782 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5783 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5784 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5785 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5786 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5787
5788 /* Add CTLESC when necessary. */
5789 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5790 /* Do not skip NUL characters. */
5791 #define QUOTES_KEEPNUL EXP_TILDE
5792
5793 /*
5794  * Structure specifying which parts of the string should be searched
5795  * for IFS characters.
5796  */
5797 struct ifsregion {
5798         struct ifsregion *next; /* next region in list */
5799         int begoff;             /* offset of start of region */
5800         int endoff;             /* offset of end of region */
5801         int nulonly;            /* search for nul bytes only */
5802 };
5803
5804 struct arglist {
5805         struct strlist *list;
5806         struct strlist **lastp;
5807 };
5808
5809 /* output of current string */
5810 static char *expdest;
5811 /* list of back quote expressions */
5812 static struct nodelist *argbackq;
5813 /* first struct in list of ifs regions */
5814 static struct ifsregion ifsfirst;
5815 /* last struct in list */
5816 static struct ifsregion *ifslastp;
5817 /* holds expanded arg list */
5818 static struct arglist exparg;
5819
5820 /*
5821  * Our own itoa().
5822  * cvtnum() is used even if math support is off (to prepare $? values and such).
5823  */
5824 static int
5825 cvtnum(arith_t num)
5826 {
5827         int len;
5828
5829         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5830         len = sizeof(arith_t) * 3;
5831         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5832         if (sizeof(arith_t) < 4) len += 2;
5833
5834         expdest = makestrspace(len, expdest);
5835         len = fmtstr(expdest, len, ARITH_FMT, num);
5836         STADJUST(len, expdest);
5837         return len;
5838 }
5839
5840 /*
5841  * Break the argument string into pieces based upon IFS and add the
5842  * strings to the argument list.  The regions of the string to be
5843  * searched for IFS characters have been stored by recordregion.
5844  */
5845 static void
5846 ifsbreakup(char *string, struct arglist *arglist)
5847 {
5848         struct ifsregion *ifsp;
5849         struct strlist *sp;
5850         char *start;
5851         char *p;
5852         char *q;
5853         const char *ifs, *realifs;
5854         int ifsspc;
5855         int nulonly;
5856
5857         start = string;
5858         if (ifslastp != NULL) {
5859                 ifsspc = 0;
5860                 nulonly = 0;
5861                 realifs = ifsset() ? ifsval() : defifs;
5862                 ifsp = &ifsfirst;
5863                 do {
5864                         p = string + ifsp->begoff;
5865                         nulonly = ifsp->nulonly;
5866                         ifs = nulonly ? nullstr : realifs;
5867                         ifsspc = 0;
5868                         while (p < string + ifsp->endoff) {
5869                                 q = p;
5870                                 if ((unsigned char)*p == CTLESC)
5871                                         p++;
5872                                 if (!strchr(ifs, *p)) {
5873                                         p++;
5874                                         continue;
5875                                 }
5876                                 if (!nulonly)
5877                                         ifsspc = (strchr(defifs, *p) != NULL);
5878                                 /* Ignore IFS whitespace at start */
5879                                 if (q == start && ifsspc) {
5880                                         p++;
5881                                         start = p;
5882                                         continue;
5883                                 }
5884                                 *q = '\0';
5885                                 sp = stzalloc(sizeof(*sp));
5886                                 sp->text = start;
5887                                 *arglist->lastp = sp;
5888                                 arglist->lastp = &sp->next;
5889                                 p++;
5890                                 if (!nulonly) {
5891                                         for (;;) {
5892                                                 if (p >= string + ifsp->endoff) {
5893                                                         break;
5894                                                 }
5895                                                 q = p;
5896                                                 if ((unsigned char)*p == CTLESC)
5897                                                         p++;
5898                                                 if (strchr(ifs, *p) == NULL) {
5899                                                         p = q;
5900                                                         break;
5901                                                 }
5902                                                 if (strchr(defifs, *p) == NULL) {
5903                                                         if (ifsspc) {
5904                                                                 p++;
5905                                                                 ifsspc = 0;
5906                                                         } else {
5907                                                                 p = q;
5908                                                                 break;
5909                                                         }
5910                                                 } else
5911                                                         p++;
5912                                         }
5913                                 }
5914                                 start = p;
5915                         } /* while */
5916                         ifsp = ifsp->next;
5917                 } while (ifsp != NULL);
5918                 if (nulonly)
5919                         goto add;
5920         }
5921
5922         if (!*start)
5923                 return;
5924
5925  add:
5926         sp = stzalloc(sizeof(*sp));
5927         sp->text = start;
5928         *arglist->lastp = sp;
5929         arglist->lastp = &sp->next;
5930 }
5931
5932 static void
5933 ifsfree(void)
5934 {
5935         struct ifsregion *p = ifsfirst.next;
5936
5937         if (!p)
5938                 goto out;
5939
5940         INT_OFF;
5941         do {
5942                 struct ifsregion *ifsp;
5943                 ifsp = p->next;
5944                 free(p);
5945                 p = ifsp;
5946         } while (p);
5947         ifsfirst.next = NULL;
5948         INT_ON;
5949  out:
5950         ifslastp = NULL;
5951 }
5952
5953 static size_t
5954 esclen(const char *start, const char *p)
5955 {
5956         size_t esc = 0;
5957
5958         while (p > start && (unsigned char)*--p == CTLESC) {
5959                 esc++;
5960         }
5961         return esc;
5962 }
5963
5964 /*
5965  * Remove any CTLESC characters from a string.
5966  */
5967 static char *
5968 rmescapes(char *str, int flag)
5969 {
5970         static const char qchars[] ALIGN1 = {
5971                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5972
5973         char *p, *q, *r;
5974         unsigned inquotes;
5975         unsigned protect_against_glob;
5976         unsigned globbing;
5977         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5978
5979         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5980         if (!p)
5981                 return str;
5982
5983         q = p;
5984         r = str;
5985         if (flag & RMESCAPE_ALLOC) {
5986                 size_t len = p - str;
5987                 size_t fulllen = len + strlen(p) + 1;
5988
5989                 if (flag & RMESCAPE_GROW) {
5990                         int strloc = str - (char *)stackblock();
5991                         r = makestrspace(fulllen, expdest);
5992                         /* p and str may be invalidated by makestrspace */
5993                         str = (char *)stackblock() + strloc;
5994                         p = str + len;
5995                 } else if (flag & RMESCAPE_HEAP) {
5996                         r = ckmalloc(fulllen);
5997                 } else {
5998                         r = stalloc(fulllen);
5999                 }
6000                 q = r;
6001                 if (len > 0) {
6002                         q = (char *)mempcpy(q, str, len);
6003                 }
6004         }
6005
6006         inquotes = 0;
6007         globbing = flag & RMESCAPE_GLOB;
6008         protect_against_glob = globbing;
6009         while (*p) {
6010                 if ((unsigned char)*p == CTLQUOTEMARK) {
6011 // Note: both inquotes and protect_against_glob only affect whether
6012 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6013                         inquotes = ~inquotes;
6014                         p++;
6015                         protect_against_glob = globbing;
6016                         continue;
6017                 }
6018                 if ((unsigned char)*p == CTLESC) {
6019                         p++;
6020 #if DEBUG
6021                         if (*p == '\0')
6022                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6023 #endif
6024                         if (protect_against_glob) {
6025                                 /*
6026                                  * We used to trust glob() and fnmatch() to eat
6027                                  * superfluous escapes (\z where z has no
6028                                  * special meaning anyway). But this causes
6029                                  * bugs such as string of one greek letter rho
6030                                  * (unicode-encoded as two bytes "cf,81")
6031                                  * getting encoded as "cf,CTLESC,81"
6032                                  * and here, converted to "cf,\,81" -
6033                                  * which does not go well with some flavors
6034                                  * of fnmatch() in unicode locales
6035                                  * (for example, glibc <= 2.22).
6036                                  *
6037                                  * Lets add "\" only on the chars which need it.
6038                                  * Testcases for less obvious chars are shown.
6039                                  */
6040                                 if (*p == '*'
6041                                  || *p == '?'
6042                                  || *p == '['
6043                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6044                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6045                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6046                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6047                                 /* Some libc support [^negate], that's why "^" also needs love */
6048                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6049                                 ) {
6050                                         *q++ = '\\';
6051                                 }
6052                         }
6053                 } else if (*p == '\\' && !inquotes) {
6054                         /* naked back slash */
6055                         protect_against_glob = 0;
6056                         goto copy;
6057                 }
6058 #if BASH_PATTERN_SUBST
6059                 else if (*p == '/' && slash) {
6060                         /* stop handling globbing and mark location of slash */
6061                         globbing = slash = 0;
6062                         *p = CTLESC;
6063                 }
6064 #endif
6065                 protect_against_glob = globbing;
6066  copy:
6067                 *q++ = *p++;
6068         }
6069         *q = '\0';
6070         if (flag & RMESCAPE_GROW) {
6071                 expdest = r;
6072                 STADJUST(q - r + 1, expdest);
6073         }
6074         return r;
6075 }
6076 #define pmatch(a, b) !fnmatch((a), (b), 0)
6077
6078 /*
6079  * Prepare a pattern for a expmeta (internal glob(3)) call.
6080  *
6081  * Returns an stalloced string.
6082  */
6083 static char *
6084 preglob(const char *pattern, int flag)
6085 {
6086         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
6087 }
6088
6089 /*
6090  * Put a string on the stack.
6091  */
6092 static void
6093 memtodest(const char *p, size_t len, int syntax, int quotes)
6094 {
6095         char *q;
6096
6097         if (!len)
6098                 return;
6099
6100         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6101
6102         do {
6103                 unsigned char c = *p++;
6104                 if (c) {
6105                         if (quotes & QUOTES_ESC) {
6106                                 int n = SIT(c, syntax);
6107                                 if (n == CCTL
6108                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6109                                      && n == CBACK
6110                                     )
6111                                 ) {
6112                                         USTPUTC(CTLESC, q);
6113                                 }
6114                         }
6115                 } else if (!(quotes & QUOTES_KEEPNUL))
6116                         continue;
6117                 USTPUTC(c, q);
6118         } while (--len);
6119
6120         expdest = q;
6121 }
6122
6123 static size_t
6124 strtodest(const char *p, int syntax, int quotes)
6125 {
6126         size_t len = strlen(p);
6127         memtodest(p, len, syntax, quotes);
6128         return len;
6129 }
6130
6131 /*
6132  * Record the fact that we have to scan this region of the
6133  * string for IFS characters.
6134  */
6135 static void
6136 recordregion(int start, int end, int nulonly)
6137 {
6138         struct ifsregion *ifsp;
6139
6140         if (ifslastp == NULL) {
6141                 ifsp = &ifsfirst;
6142         } else {
6143                 INT_OFF;
6144                 ifsp = ckzalloc(sizeof(*ifsp));
6145                 /*ifsp->next = NULL; - ckzalloc did it */
6146                 ifslastp->next = ifsp;
6147                 INT_ON;
6148         }
6149         ifslastp = ifsp;
6150         ifslastp->begoff = start;
6151         ifslastp->endoff = end;
6152         ifslastp->nulonly = nulonly;
6153 }
6154
6155 static void
6156 removerecordregions(int endoff)
6157 {
6158         if (ifslastp == NULL)
6159                 return;
6160
6161         if (ifsfirst.endoff > endoff) {
6162                 while (ifsfirst.next) {
6163                         struct ifsregion *ifsp;
6164                         INT_OFF;
6165                         ifsp = ifsfirst.next->next;
6166                         free(ifsfirst.next);
6167                         ifsfirst.next = ifsp;
6168                         INT_ON;
6169                 }
6170                 if (ifsfirst.begoff > endoff) {
6171                         ifslastp = NULL;
6172                 } else {
6173                         ifslastp = &ifsfirst;
6174                         ifsfirst.endoff = endoff;
6175                 }
6176                 return;
6177         }
6178
6179         ifslastp = &ifsfirst;
6180         while (ifslastp->next && ifslastp->next->begoff < endoff)
6181                 ifslastp = ifslastp->next;
6182         while (ifslastp->next) {
6183                 struct ifsregion *ifsp;
6184                 INT_OFF;
6185                 ifsp = ifslastp->next->next;
6186                 free(ifslastp->next);
6187                 ifslastp->next = ifsp;
6188                 INT_ON;
6189         }
6190         if (ifslastp->endoff > endoff)
6191                 ifslastp->endoff = endoff;
6192 }
6193
6194 static char *
6195 exptilde(char *startp, char *p, int flags)
6196 {
6197         unsigned char c;
6198         char *name;
6199         struct passwd *pw;
6200         const char *home;
6201         int quotes = flags & QUOTES_ESC;
6202
6203         name = p + 1;
6204
6205         while ((c = *++p) != '\0') {
6206                 switch (c) {
6207                 case CTLESC:
6208                         return startp;
6209                 case CTLQUOTEMARK:
6210                         return startp;
6211                 case ':':
6212                         if (flags & EXP_VARTILDE)
6213                                 goto done;
6214                         break;
6215                 case '/':
6216                 case CTLENDVAR:
6217                         goto done;
6218                 }
6219         }
6220  done:
6221         *p = '\0';
6222         if (*name == '\0') {
6223                 home = lookupvar("HOME");
6224         } else {
6225                 pw = getpwnam(name);
6226                 if (pw == NULL)
6227                         goto lose;
6228                 home = pw->pw_dir;
6229         }
6230         if (!home || !*home)
6231                 goto lose;
6232         *p = c;
6233         strtodest(home, SQSYNTAX, quotes);
6234         return p;
6235  lose:
6236         *p = c;
6237         return startp;
6238 }
6239
6240 /*
6241  * Execute a command inside back quotes.  If it's a builtin command, we
6242  * want to save its output in a block obtained from malloc.  Otherwise
6243  * we fork off a subprocess and get the output of the command via a pipe.
6244  * Should be called with interrupts off.
6245  */
6246 struct backcmd {                /* result of evalbackcmd */
6247         int fd;                 /* file descriptor to read from */
6248         int nleft;              /* number of chars in buffer */
6249         char *buf;              /* buffer */
6250         struct job *jp;         /* job structure for command */
6251 };
6252
6253 /* These forward decls are needed to use "eval" code for backticks handling: */
6254 /* flags in argument to evaltree */
6255 #define EV_EXIT    01           /* exit after evaluating tree */
6256 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6257 static int evaltree(union node *, int);
6258
6259 /* An evaltree() which is known to never return.
6260  * Used to use an alias:
6261  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6262  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6263  */
6264 static ALWAYS_INLINE NORETURN void
6265 evaltreenr(union node *n, int flags)
6266 {
6267         evaltree(n, flags);
6268         bb_unreachable(abort());
6269         /* NOTREACHED */
6270 }
6271
6272 static void FAST_FUNC
6273 evalbackcmd(union node *n, struct backcmd *result)
6274 {
6275         int pip[2];
6276         struct job *jp;
6277
6278         result->fd = -1;
6279         result->buf = NULL;
6280         result->nleft = 0;
6281         result->jp = NULL;
6282         if (n == NULL) {
6283                 goto out;
6284         }
6285
6286         if (pipe(pip) < 0)
6287                 ash_msg_and_raise_error("pipe call failed");
6288         jp = makejob(/*n,*/ 1);
6289         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6290                 /* child */
6291                 FORCE_INT_ON;
6292                 close(pip[0]);
6293                 if (pip[1] != 1) {
6294                         /*close(1);*/
6295                         dup2_or_raise(pip[1], 1);
6296                         close(pip[1]);
6297                 }
6298 /* TODO: eflag clearing makes the following not abort:
6299  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6300  * which is what bash does (unless it is in POSIX mode).
6301  * dash deleted "eflag = 0" line in the commit
6302  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6303  *  [EVAL] Don't clear eflag in evalbackcmd
6304  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6305  */
6306                 eflag = 0;
6307                 ifsfree();
6308                 evaltreenr(n, EV_EXIT);
6309                 /* NOTREACHED */
6310         }
6311         /* parent */
6312         close(pip[1]);
6313         result->fd = pip[0];
6314         result->jp = jp;
6315
6316  out:
6317         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6318                 result->fd, result->buf, result->nleft, result->jp));
6319 }
6320
6321 /*
6322  * Expand stuff in backwards quotes.
6323  */
6324 static void
6325 expbackq(union node *cmd, int flag)
6326 {
6327         struct backcmd in;
6328         int i;
6329         char buf[128];
6330         char *p;
6331         char *dest;
6332         int startloc;
6333         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6334         struct stackmark smark;
6335
6336         INT_OFF;
6337         startloc = expdest - (char *)stackblock();
6338         pushstackmark(&smark, startloc);
6339         evalbackcmd(cmd, &in);
6340         popstackmark(&smark);
6341
6342         p = in.buf;
6343         i = in.nleft;
6344         if (i == 0)
6345                 goto read;
6346         for (;;) {
6347                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6348  read:
6349                 if (in.fd < 0)
6350                         break;
6351                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6352                 TRACE(("expbackq: read returns %d\n", i));
6353                 if (i <= 0)
6354                         break;
6355                 p = buf;
6356         }
6357
6358         free(in.buf);
6359         if (in.fd >= 0) {
6360                 close(in.fd);
6361                 back_exitstatus = waitforjob(in.jp);
6362         }
6363         INT_ON;
6364
6365         /* Eat all trailing newlines */
6366         dest = expdest;
6367         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6368                 STUNPUTC(dest);
6369         expdest = dest;
6370
6371         if (!(flag & EXP_QUOTED))
6372                 recordregion(startloc, dest - (char *)stackblock(), 0);
6373         TRACE(("evalbackq: size:%d:'%.*s'\n",
6374                 (int)((dest - (char *)stackblock()) - startloc),
6375                 (int)((dest - (char *)stackblock()) - startloc),
6376                 stackblock() + startloc));
6377 }
6378
6379 #if ENABLE_FEATURE_SH_MATH
6380 /*
6381  * Expand arithmetic expression.  Backup to start of expression,
6382  * evaluate, place result in (backed up) result, adjust string position.
6383  */
6384 static void
6385 expari(int flag)
6386 {
6387         char *p, *start;
6388         int begoff;
6389         int len;
6390
6391         /* ifsfree(); */
6392
6393         /*
6394          * This routine is slightly over-complicated for
6395          * efficiency.  Next we scan backwards looking for the
6396          * start of arithmetic.
6397          */
6398         start = stackblock();
6399         p = expdest - 1;
6400         *p = '\0';
6401         p--;
6402         while (1) {
6403                 int esc;
6404
6405                 while ((unsigned char)*p != CTLARI) {
6406                         p--;
6407 #if DEBUG
6408                         if (p < start) {
6409                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6410                         }
6411 #endif
6412                 }
6413
6414                 esc = esclen(start, p);
6415                 if (!(esc % 2)) {
6416                         break;
6417                 }
6418
6419                 p -= esc + 1;
6420         }
6421
6422         begoff = p - start;
6423
6424         removerecordregions(begoff);
6425
6426         expdest = p;
6427
6428         if (flag & QUOTES_ESC)
6429                 rmescapes(p + 1, 0);
6430
6431         len = cvtnum(ash_arith(p + 1));
6432
6433         if (!(flag & EXP_QUOTED))
6434                 recordregion(begoff, begoff + len, 0);
6435 }
6436 #endif
6437
6438 /* argstr needs it */
6439 static char *evalvar(char *p, int flags);
6440
6441 /*
6442  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6443  * characters to allow for further processing.  Otherwise treat
6444  * $@ like $* since no splitting will be performed.
6445  */
6446 static void
6447 argstr(char *p, int flags)
6448 {
6449         static const char spclchars[] ALIGN1 = {
6450                 '=',
6451                 ':',
6452                 CTLQUOTEMARK,
6453                 CTLENDVAR,
6454                 CTLESC,
6455                 CTLVAR,
6456                 CTLBACKQ,
6457 #if ENABLE_FEATURE_SH_MATH
6458                 CTLENDARI,
6459 #endif
6460                 '\0'
6461         };
6462         const char *reject = spclchars;
6463         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6464         int inquotes;
6465         size_t length;
6466         int startloc;
6467
6468         if (!(flags & EXP_VARTILDE)) {
6469                 reject += 2;
6470         } else if (flags & EXP_VARTILDE2) {
6471                 reject++;
6472         }
6473         inquotes = 0;
6474         length = 0;
6475         if (flags & EXP_TILDE) {
6476                 char *q;
6477
6478                 flags &= ~EXP_TILDE;
6479  tilde:
6480                 q = p;
6481                 if (*q == '~')
6482                         p = exptilde(p, q, flags);
6483         }
6484  start:
6485         startloc = expdest - (char *)stackblock();
6486         for (;;) {
6487                 unsigned char c;
6488
6489                 length += strcspn(p + length, reject);
6490                 c = p[length];
6491                 if (c) {
6492                         if (!(c & 0x80)
6493                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6494                         ) {
6495                                 /* c == '=' || c == ':' || c == CTLENDARI */
6496                                 length++;
6497                         }
6498                 }
6499                 if (length > 0) {
6500                         int newloc;
6501                         expdest = stack_nputstr(p, length, expdest);
6502                         newloc = expdest - (char *)stackblock();
6503                         if (breakall && !inquotes && newloc > startloc) {
6504                                 recordregion(startloc, newloc, 0);
6505                         }
6506                         startloc = newloc;
6507                 }
6508                 p += length + 1;
6509                 length = 0;
6510
6511                 switch (c) {
6512                 case '\0':
6513                         goto breakloop;
6514                 case '=':
6515                         if (flags & EXP_VARTILDE2) {
6516                                 p--;
6517                                 continue;
6518                         }
6519                         flags |= EXP_VARTILDE2;
6520                         reject++;
6521                         /* fall through */
6522                 case ':':
6523                         /*
6524                          * sort of a hack - expand tildes in variable
6525                          * assignments (after the first '=' and after ':'s).
6526                          */
6527                         if (*--p == '~') {
6528                                 goto tilde;
6529                         }
6530                         continue;
6531                 }
6532
6533                 switch (c) {
6534                 case CTLENDVAR: /* ??? */
6535                         goto breakloop;
6536                 case CTLQUOTEMARK:
6537                         inquotes ^= EXP_QUOTED;
6538                         /* "$@" syntax adherence hack */
6539                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6540                                 p = evalvar(p + 1, flags | inquotes) + 1;
6541                                 goto start;
6542                         }
6543  addquote:
6544                         if (flags & QUOTES_ESC) {
6545                                 p--;
6546                                 length++;
6547                                 startloc++;
6548                         }
6549                         break;
6550                 case CTLESC:
6551                         startloc++;
6552                         length++;
6553
6554                         /*
6555                          * Quoted parameter expansion pattern: remove quote
6556                          * unless inside inner quotes or we have a literal
6557                          * backslash.
6558                          */
6559                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6560                             EXP_QPAT && *p != '\\')
6561                                 break;
6562
6563                         goto addquote;
6564                 case CTLVAR:
6565                         TRACE(("argstr: evalvar('%s')\n", p));
6566                         p = evalvar(p, flags | inquotes);
6567                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6568                         goto start;
6569                 case CTLBACKQ:
6570                         expbackq(argbackq->n, flags | inquotes);
6571                         argbackq = argbackq->next;
6572                         goto start;
6573 #if ENABLE_FEATURE_SH_MATH
6574                 case CTLENDARI:
6575                         p--;
6576                         expari(flags | inquotes);
6577                         goto start;
6578 #endif
6579                 }
6580         }
6581  breakloop: ;
6582 }
6583
6584 static char *
6585 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6586                 char *pattern, int quotes, int zero)
6587 {
6588         char *loc, *loc2;
6589         char c;
6590
6591         loc = startp;
6592         loc2 = rmesc;
6593         do {
6594                 int match;
6595                 const char *s = loc2;
6596
6597                 c = *loc2;
6598                 if (zero) {
6599                         *loc2 = '\0';
6600                         s = rmesc;
6601                 }
6602                 match = pmatch(pattern, s);
6603
6604                 *loc2 = c;
6605                 if (match)
6606                         return loc;
6607                 if (quotes && (unsigned char)*loc == CTLESC)
6608                         loc++;
6609                 loc++;
6610                 loc2++;
6611         } while (c);
6612         return NULL;
6613 }
6614
6615 static char *
6616 scanright(char *startp, char *rmesc, char *rmescend,
6617                 char *pattern, int quotes, int match_at_start)
6618 {
6619 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6620         int try2optimize = match_at_start;
6621 #endif
6622         int esc = 0;
6623         char *loc;
6624         char *loc2;
6625
6626         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6627          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6628          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6629          * Logic:
6630          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6631          * and on each iteration they go back two/one char until they reach the beginning.
6632          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6633          */
6634         /* TODO: document in what other circumstances we are called. */
6635
6636         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6637                 int match;
6638                 char c = *loc2;
6639                 const char *s = loc2;
6640                 if (match_at_start) {
6641                         *loc2 = '\0';
6642                         s = rmesc;
6643                 }
6644                 match = pmatch(pattern, s);
6645                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6646                 *loc2 = c;
6647                 if (match)
6648                         return loc;
6649 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6650                 if (try2optimize) {
6651                         /* Maybe we can optimize this:
6652                          * if pattern ends with unescaped *, we can avoid checking
6653                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6654                          * it won't match truncated "raw_value_of_" strings too.
6655                          */
6656                         unsigned plen = strlen(pattern);
6657                         /* Does it end with "*"? */
6658                         if (plen != 0 && pattern[--plen] == '*') {
6659                                 /* "xxxx*" is not escaped */
6660                                 /* "xxx\*" is escaped */
6661                                 /* "xx\\*" is not escaped */
6662                                 /* "x\\\*" is escaped */
6663                                 int slashes = 0;
6664                                 while (plen != 0 && pattern[--plen] == '\\')
6665                                         slashes++;
6666                                 if (!(slashes & 1))
6667                                         break; /* ends with unescaped "*" */
6668                         }
6669                         try2optimize = 0;
6670                 }
6671 #endif
6672                 loc--;
6673                 if (quotes) {
6674                         if (--esc < 0) {
6675                                 esc = esclen(startp, loc);
6676                         }
6677                         if (esc % 2) {
6678                                 esc--;
6679                                 loc--;
6680                         }
6681                 }
6682         }
6683         return NULL;
6684 }
6685
6686 static void varunset(const char *, const char *, const char *, int) NORETURN;
6687 static void
6688 varunset(const char *end, const char *var, const char *umsg, int varflags)
6689 {
6690         const char *msg;
6691         const char *tail;
6692
6693         tail = nullstr;
6694         msg = "parameter not set";
6695         if (umsg) {
6696                 if ((unsigned char)*end == CTLENDVAR) {
6697                         if (varflags & VSNUL)
6698                                 tail = " or null";
6699                 } else {
6700                         msg = umsg;
6701                 }
6702         }
6703         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6704 }
6705
6706 static const char *
6707 subevalvar(char *p, char *varname, int strloc, int subtype,
6708                 int startloc, int varflags, int flag)
6709 {
6710         struct nodelist *saveargbackq = argbackq;
6711         int quotes = flag & QUOTES_ESC;
6712         char *startp;
6713         char *loc;
6714         char *rmesc, *rmescend;
6715         char *str;
6716         int amount, resetloc;
6717         IF_BASH_PATTERN_SUBST(int workloc;)
6718         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6719         int zero;
6720         char *(*scan)(char*, char*, char*, char*, int, int);
6721
6722         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6723         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6724
6725         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6726                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6727         );
6728         STPUTC('\0', expdest);
6729         argbackq = saveargbackq;
6730         startp = (char *)stackblock() + startloc;
6731
6732         switch (subtype) {
6733         case VSASSIGN:
6734                 setvar0(varname, startp);
6735                 amount = startp - expdest;
6736                 STADJUST(amount, expdest);
6737                 return startp;
6738
6739         case VSQUESTION:
6740                 varunset(p, varname, startp, varflags);
6741                 /* NOTREACHED */
6742
6743 #if BASH_SUBSTR
6744         case VSSUBSTR: {
6745                 int pos, len, orig_len;
6746                 char *colon;
6747
6748                 loc = str = stackblock() + strloc;
6749
6750 # if !ENABLE_FEATURE_SH_MATH
6751 #  define ash_arith number
6752 # endif
6753                 /* Read POS in ${var:POS:LEN} */
6754                 colon = strchr(loc, ':');
6755                 if (colon) *colon = '\0';
6756                 pos = ash_arith(loc);
6757                 if (colon) *colon = ':';
6758
6759                 /* Read LEN in ${var:POS:LEN} */
6760                 len = str - startp - 1;
6761                 /* *loc != '\0', guaranteed by parser */
6762                 if (quotes) {
6763                         char *ptr;
6764
6765                         /* Adjust the length by the number of escapes */
6766                         for (ptr = startp; ptr < (str - 1); ptr++) {
6767                                 if ((unsigned char)*ptr == CTLESC) {
6768                                         len--;
6769                                         ptr++;
6770                                 }
6771                         }
6772                 }
6773                 orig_len = len;
6774                 if (*loc++ == ':') {
6775                         /* ${var::LEN} */
6776                         len = ash_arith(loc);
6777                 } else {
6778                         /* Skip POS in ${var:POS:LEN} */
6779                         len = orig_len;
6780                         while (*loc && *loc != ':') {
6781                                 loc++;
6782                         }
6783                         if (*loc++ == ':') {
6784                                 len = ash_arith(loc);
6785                         }
6786                 }
6787 #  undef ash_arith
6788
6789                 if (pos < 0) {
6790                         /* ${VAR:$((-n)):l} starts n chars from the end */
6791                         pos = orig_len + pos;
6792                 }
6793                 if ((unsigned)pos >= orig_len) {
6794                         /* apart from obvious ${VAR:999999:l},
6795                          * covers ${VAR:$((-9999999)):l} - result is ""
6796                          * (bash compat)
6797                          */
6798                         pos = 0;
6799                         len = 0;
6800                 }
6801                 if (len < 0) {
6802                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6803                         len = (orig_len - pos) + len;
6804                 }
6805                 if ((unsigned)len > (orig_len - pos))
6806                         len = orig_len - pos;
6807
6808                 for (str = startp; pos; str++, pos--) {
6809                         if (quotes && (unsigned char)*str == CTLESC)
6810                                 str++;
6811                 }
6812                 for (loc = startp; len; len--) {
6813                         if (quotes && (unsigned char)*str == CTLESC)
6814                                 *loc++ = *str++;
6815                         *loc++ = *str++;
6816                 }
6817                 *loc = '\0';
6818                 amount = loc - expdest;
6819                 STADJUST(amount, expdest);
6820                 return loc;
6821         }
6822 #endif /* BASH_SUBSTR */
6823         }
6824
6825         resetloc = expdest - (char *)stackblock();
6826
6827 #if BASH_PATTERN_SUBST
6828         /* We'll comeback here if we grow the stack while handling
6829          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6830          * stack will need rebasing, and we'll need to remove our work
6831          * areas each time
6832          */
6833  restart:
6834 #endif
6835
6836         amount = expdest - ((char *)stackblock() + resetloc);
6837         STADJUST(-amount, expdest);
6838         startp = (char *)stackblock() + startloc;
6839
6840         rmesc = startp;
6841         rmescend = (char *)stackblock() + strloc;
6842         if (quotes) {
6843                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6844                 if (rmesc != startp) {
6845                         rmescend = expdest;
6846                         startp = (char *)stackblock() + startloc;
6847                 }
6848         }
6849         rmescend--;
6850         str = (char *)stackblock() + strloc;
6851         /*
6852          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6853          * The result is a_\_z_c (not a\_\_z_c)!
6854          *
6855          * The search pattern and replace string treat backslashes differently!
6856          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6857          * and string.  It's only used on the first call.
6858          */
6859         preglob(str, IF_BASH_PATTERN_SUBST(
6860                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6861                         RMESCAPE_SLASH : ) 0);
6862
6863 #if BASH_PATTERN_SUBST
6864         workloc = expdest - (char *)stackblock();
6865         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6866                 int len;
6867                 char *idx, *end;
6868
6869                 if (!repl) {
6870                         repl = strchr(str, CTLESC);
6871                         if (repl)
6872                                 *repl++ = '\0';
6873                         else
6874                                 repl = nullstr;
6875                 }
6876                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6877
6878                 /* If there's no pattern to match, return the expansion unmolested */
6879                 if (str[0] == '\0')
6880                         return NULL;
6881
6882                 len = 0;
6883                 idx = startp;
6884                 end = str - 1;
6885                 while (idx < end) {
6886  try_to_match:
6887                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6888                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6889                         if (!loc) {
6890                                 /* No match, advance */
6891                                 char *restart_detect = stackblock();
6892  skip_matching:
6893                                 STPUTC(*idx, expdest);
6894                                 if (quotes && (unsigned char)*idx == CTLESC) {
6895                                         idx++;
6896                                         len++;
6897                                         STPUTC(*idx, expdest);
6898                                 }
6899                                 if (stackblock() != restart_detect)
6900                                         goto restart;
6901                                 idx++;
6902                                 len++;
6903                                 rmesc++;
6904                                 /* continue; - prone to quadratic behavior, smarter code: */
6905                                 if (idx >= end)
6906                                         break;
6907                                 if (str[0] == '*') {
6908                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6909                                          * it would never match "ong_string" etc, no point in trying.
6910                                          */
6911                                         goto skip_matching;
6912                                 }
6913                                 goto try_to_match;
6914                         }
6915
6916                         if (subtype == VSREPLACEALL) {
6917                                 while (idx < loc) {
6918                                         if (quotes && (unsigned char)*idx == CTLESC)
6919                                                 idx++;
6920                                         idx++;
6921                                         rmesc++;
6922                                 }
6923                         } else {
6924                                 idx = loc;
6925                         }
6926
6927                         //bb_error_msg("repl:'%s'", repl);
6928                         for (loc = (char*)repl; *loc; loc++) {
6929                                 char *restart_detect = stackblock();
6930                                 if (quotes && *loc == '\\') {
6931                                         STPUTC(CTLESC, expdest);
6932                                         len++;
6933                                 }
6934                                 STPUTC(*loc, expdest);
6935                                 if (stackblock() != restart_detect)
6936                                         goto restart;
6937                                 len++;
6938                         }
6939
6940                         if (subtype == VSREPLACE) {
6941                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6942                                 while (*idx) {
6943                                         char *restart_detect = stackblock();
6944                                         STPUTC(*idx, expdest);
6945                                         if (stackblock() != restart_detect)
6946                                                 goto restart;
6947                                         len++;
6948                                         idx++;
6949                                 }
6950                                 break;
6951                         }
6952                 }
6953
6954                 /* We've put the replaced text into a buffer at workloc, now
6955                  * move it to the right place and adjust the stack.
6956                  */
6957                 STPUTC('\0', expdest);
6958                 startp = (char *)stackblock() + startloc;
6959                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6960                 //bb_error_msg("startp:'%s'", startp);
6961                 amount = expdest - (startp + len);
6962                 STADJUST(-amount, expdest);
6963                 return startp;
6964         }
6965 #endif /* BASH_PATTERN_SUBST */
6966
6967         subtype -= VSTRIMRIGHT;
6968 #if DEBUG
6969         if (subtype < 0 || subtype > 7)
6970                 abort();
6971 #endif
6972         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6973         zero = subtype >> 1;
6974         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6975         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6976
6977         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6978         if (loc) {
6979                 if (zero) {
6980                         memmove(startp, loc, str - loc);
6981                         loc = startp + (str - loc) - 1;
6982                 }
6983                 *loc = '\0';
6984                 amount = loc - expdest;
6985                 STADJUST(amount, expdest);
6986         }
6987         return loc;
6988 }
6989
6990 /*
6991  * Add the value of a specialized variable to the stack string.
6992  * name parameter (examples):
6993  * ash -c 'echo $1'      name:'1='
6994  * ash -c 'echo $qwe'    name:'qwe='
6995  * ash -c 'echo $$'      name:'$='
6996  * ash -c 'echo ${$}'    name:'$='
6997  * ash -c 'echo ${$##q}' name:'$=q'
6998  * ash -c 'echo ${#$}'   name:'$='
6999  * note: examples with bad shell syntax:
7000  * ash -c 'echo ${#$1}'  name:'$=1'
7001  * ash -c 'echo ${#1#}'  name:'1=#'
7002  */
7003 static NOINLINE ssize_t
7004 varvalue(char *name, int varflags, int flags, int *quotedp)
7005 {
7006         const char *p;
7007         int num;
7008         int i;
7009         ssize_t len = 0;
7010         int sep;
7011         int quoted = *quotedp;
7012         int subtype = varflags & VSTYPE;
7013         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7014         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7015         int syntax;
7016
7017         sep = (flags & EXP_FULL) << CHAR_BIT;
7018         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7019
7020         switch (*name) {
7021         case '$':
7022                 num = rootpid;
7023                 goto numvar;
7024         case '?':
7025                 num = exitstatus;
7026                 goto numvar;
7027         case '#':
7028                 num = shellparam.nparam;
7029                 goto numvar;
7030         case '!':
7031                 num = backgndpid;
7032                 if (num == 0)
7033                         return -1;
7034  numvar:
7035                 len = cvtnum(num);
7036                 goto check_1char_name;
7037         case '-':
7038                 expdest = makestrspace(NOPTS, expdest);
7039                 for (i = NOPTS - 1; i >= 0; i--) {
7040                         if (optlist[i]) {
7041                                 USTPUTC(optletters(i), expdest);
7042                                 len++;
7043                         }
7044                 }
7045  check_1char_name:
7046 #if 0
7047                 /* handles cases similar to ${#$1} */
7048                 if (name[2] != '\0')
7049                         raise_error_syntax("bad substitution");
7050 #endif
7051                 break;
7052         case '@':
7053                 if (quoted && sep)
7054                         goto param;
7055                 /* fall through */
7056         case '*': {
7057                 char **ap;
7058                 char sepc;
7059
7060                 if (quoted)
7061                         sep = 0;
7062                 sep |= ifsset() ? ifsval()[0] : ' ';
7063  param:
7064                 sepc = sep;
7065                 *quotedp = !sepc;
7066                 ap = shellparam.p;
7067                 if (!ap)
7068                         return -1;
7069                 while ((p = *ap++) != NULL) {
7070                         len += strtodest(p, syntax, quotes);
7071
7072                         if (*ap && sep) {
7073                                 len++;
7074                                 memtodest(&sepc, 1, syntax, quotes);
7075                         }
7076                 }
7077                 break;
7078         } /* case '*' */
7079         case '0':
7080         case '1':
7081         case '2':
7082         case '3':
7083         case '4':
7084         case '5':
7085         case '6':
7086         case '7':
7087         case '8':
7088         case '9':
7089                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7090                 if (num < 0 || num > shellparam.nparam)
7091                         return -1;
7092                 p = num ? shellparam.p[num - 1] : arg0;
7093                 goto value;
7094         default:
7095                 /* NB: name has form "VAR=..." */
7096                 p = lookupvar(name);
7097  value:
7098                 if (!p)
7099                         return -1;
7100
7101                 len = strtodest(p, syntax, quotes);
7102 #if ENABLE_UNICODE_SUPPORT
7103                 if (subtype == VSLENGTH && len > 0) {
7104                         reinit_unicode_for_ash();
7105                         if (unicode_status == UNICODE_ON) {
7106                                 STADJUST(-len, expdest);
7107                                 discard = 0;
7108                                 len = unicode_strlen(p);
7109                         }
7110                 }
7111 #endif
7112                 break;
7113         }
7114
7115         if (discard)
7116                 STADJUST(-len, expdest);
7117         return len;
7118 }
7119
7120 /*
7121  * Expand a variable, and return a pointer to the next character in the
7122  * input string.
7123  */
7124 static char *
7125 evalvar(char *p, int flag)
7126 {
7127         char varflags;
7128         char subtype;
7129         int quoted;
7130         char easy;
7131         char *var;
7132         int patloc;
7133         int startloc;
7134         ssize_t varlen;
7135
7136         varflags = (unsigned char) *p++;
7137         subtype = varflags & VSTYPE;
7138
7139         if (!subtype)
7140                 raise_error_syntax("bad substitution");
7141
7142         quoted = flag & EXP_QUOTED;
7143         var = p;
7144         easy = (!quoted || (*var == '@' && shellparam.nparam));
7145         startloc = expdest - (char *)stackblock();
7146         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7147
7148  again:
7149         varlen = varvalue(var, varflags, flag, &quoted);
7150         if (varflags & VSNUL)
7151                 varlen--;
7152
7153         if (subtype == VSPLUS) {
7154                 varlen = -1 - varlen;
7155                 goto vsplus;
7156         }
7157
7158         if (subtype == VSMINUS) {
7159  vsplus:
7160                 if (varlen < 0) {
7161                         argstr(
7162                                 p,
7163                                 flag | EXP_TILDE | EXP_WORD
7164                         );
7165                         goto end;
7166                 }
7167                 goto record;
7168         }
7169
7170         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7171                 if (varlen >= 0)
7172                         goto record;
7173
7174                 subevalvar(p, var, 0, subtype, startloc, varflags,
7175                            flag & ~QUOTES_ESC);
7176                 varflags &= ~VSNUL;
7177                 /*
7178                  * Remove any recorded regions beyond
7179                  * start of variable
7180                  */
7181                 removerecordregions(startloc);
7182                 goto again;
7183         }
7184
7185         if (varlen < 0 && uflag)
7186                 varunset(p, var, 0, 0);
7187
7188         if (subtype == VSLENGTH) {
7189                 cvtnum(varlen > 0 ? varlen : 0);
7190                 goto record;
7191         }
7192
7193         if (subtype == VSNORMAL) {
7194  record:
7195                 if (!easy)
7196                         goto end;
7197                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7198                 goto end;
7199         }
7200
7201 #if DEBUG
7202         switch (subtype) {
7203         case VSTRIMLEFT:
7204         case VSTRIMLEFTMAX:
7205         case VSTRIMRIGHT:
7206         case VSTRIMRIGHTMAX:
7207 #if BASH_SUBSTR
7208         case VSSUBSTR:
7209 #endif
7210 #if BASH_PATTERN_SUBST
7211         case VSREPLACE:
7212         case VSREPLACEALL:
7213 #endif
7214                 break;
7215         default:
7216                 abort();
7217         }
7218 #endif
7219
7220         if (varlen >= 0) {
7221                 /*
7222                  * Terminate the string and start recording the pattern
7223                  * right after it
7224                  */
7225                 STPUTC('\0', expdest);
7226                 patloc = expdest - (char *)stackblock();
7227                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7228                                 startloc, varflags, flag)) {
7229                         int amount = expdest - (
7230                                 (char *)stackblock() + patloc - 1
7231                         );
7232                         STADJUST(-amount, expdest);
7233                 }
7234                 /* Remove any recorded regions beyond start of variable */
7235                 removerecordregions(startloc);
7236                 goto record;
7237         }
7238
7239  end:
7240         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7241                 int nesting = 1;
7242                 for (;;) {
7243                         unsigned char c = *p++;
7244                         if (c == CTLESC)
7245                                 p++;
7246                         else if (c == CTLBACKQ) {
7247                                 if (varlen >= 0)
7248                                         argbackq = argbackq->next;
7249                         } else if (c == CTLVAR) {
7250                                 if ((*p++ & VSTYPE) != VSNORMAL)
7251                                         nesting++;
7252                         } else if (c == CTLENDVAR) {
7253                                 if (--nesting == 0)
7254                                         break;
7255                         }
7256                 }
7257         }
7258         return p;
7259 }
7260
7261 /*
7262  * Add a file name to the list.
7263  */
7264 static void
7265 addfname(const char *name)
7266 {
7267         struct strlist *sp;
7268
7269         sp = stzalloc(sizeof(*sp));
7270         sp->text = sstrdup(name);
7271         *exparg.lastp = sp;
7272         exparg.lastp = &sp->next;
7273 }
7274
7275 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7276 static int
7277 hasmeta(const char *p)
7278 {
7279         static const char chars[] ALIGN1 = {
7280                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7281         };
7282
7283         for (;;) {
7284                 p = strpbrk(p, chars);
7285                 if (!p)
7286                         break;
7287                 switch ((unsigned char) *p) {
7288                 case CTLQUOTEMARK:
7289                         for (;;) {
7290                                 p++;
7291                                 if (*p == CTLQUOTEMARK)
7292                                         break;
7293                                 if (*p == CTLESC)
7294                                         p++;
7295                                 if (*p == '\0') /* huh? */
7296                                         return 0;
7297                         }
7298                         break;
7299                 case '\\':
7300                 case CTLESC:
7301                         p++;
7302                         if (*p == '\0')
7303                                 return 0;
7304                         break;
7305                 case '[':
7306                         if (!strchr(p + 1, ']')) {
7307                                 /* It's not a properly closed [] pattern,
7308                                  * but other metas may follow. Continue checking.
7309                                  * my[file* _is_ globbed by bash
7310                                  * and matches filenames like "my[file1".
7311                                  */
7312                                 break;
7313                         }
7314                         /* fallthrough */
7315                 default:
7316                 /* case '*': */
7317                 /* case '?': */
7318                         return 1;
7319                 }
7320                 p++;
7321         }
7322
7323         return 0;
7324 }
7325
7326 /* If we want to use glob() from libc... */
7327 #if !ENABLE_ASH_INTERNAL_GLOB
7328
7329 /* Add the result of glob() to the list */
7330 static void
7331 addglob(const glob_t *pglob)
7332 {
7333         char **p = pglob->gl_pathv;
7334
7335         do {
7336                 addfname(*p);
7337         } while (*++p);
7338 }
7339 static void
7340 expandmeta(struct strlist *str /*, int flag*/)
7341 {
7342         /* TODO - EXP_REDIR */
7343
7344         while (str) {
7345                 char *p;
7346                 glob_t pglob;
7347                 int i;
7348
7349                 if (fflag)
7350                         goto nometa;
7351
7352                 if (!hasmeta(str->text))
7353                         goto nometa;
7354
7355                 INT_OFF;
7356                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7357 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7358 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7359 //
7360 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7361 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7362 // Which means you need to unescape the string, right? Not so fast:
7363 // if there _is_ a file named "file\?" (with backslash), it is returned
7364 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7365 // You DON'T KNOW by looking at the result whether you need to unescape it.
7366 //
7367 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7368 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7369 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7370 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7371 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7372 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7373                 i = glob(p, 0, NULL, &pglob);
7374                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7375                 if (p != str->text)
7376                         free(p);
7377                 switch (i) {
7378                 case 0:
7379 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7380                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7381                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7382                                 goto nometa2;
7383 #endif
7384                         addglob(&pglob);
7385                         globfree(&pglob);
7386                         INT_ON;
7387                         break;
7388                 case GLOB_NOMATCH:
7389  //nometa2:
7390                         globfree(&pglob);
7391                         INT_ON;
7392  nometa:
7393                         *exparg.lastp = str;
7394                         rmescapes(str->text, 0);
7395                         exparg.lastp = &str->next;
7396                         break;
7397                 default:        /* GLOB_NOSPACE */
7398                         globfree(&pglob);
7399                         INT_ON;
7400                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7401                 }
7402                 str = str->next;
7403         }
7404 }
7405
7406 #else
7407 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7408
7409 /*
7410  * Do metacharacter (i.e. *, ?, [...]) expansion.
7411  */
7412 static void
7413 expmeta(char *expdir, char *enddir, char *name)
7414 {
7415         char *p;
7416         const char *cp;
7417         char *start;
7418         char *endname;
7419         int metaflag;
7420         struct stat statb;
7421         DIR *dirp;
7422         struct dirent *dp;
7423         int atend;
7424         int matchdot;
7425         int esc;
7426
7427         metaflag = 0;
7428         start = name;
7429         for (p = name; esc = 0, *p; p += esc + 1) {
7430                 if (*p == '*' || *p == '?')
7431                         metaflag = 1;
7432                 else if (*p == '[') {
7433                         char *q = p + 1;
7434                         if (*q == '!')
7435                                 q++;
7436                         for (;;) {
7437                                 if (*q == '\\')
7438                                         q++;
7439                                 if (*q == '/' || *q == '\0')
7440                                         break;
7441                                 if (*++q == ']') {
7442                                         metaflag = 1;
7443                                         break;
7444                                 }
7445                         }
7446                 } else {
7447                         if (*p == '\\')
7448                                 esc++;
7449                         if (p[esc] == '/') {
7450                                 if (metaflag)
7451                                         break;
7452                                 start = p + esc + 1;
7453                         }
7454                 }
7455         }
7456         if (metaflag == 0) {    /* we've reached the end of the file name */
7457                 if (enddir != expdir)
7458                         metaflag++;
7459                 p = name;
7460                 do {
7461                         if (*p == '\\')
7462                                 p++;
7463                         *enddir++ = *p;
7464                 } while (*p++);
7465                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7466                         addfname(expdir);
7467                 return;
7468         }
7469         endname = p;
7470         if (name < start) {
7471                 p = name;
7472                 do {
7473                         if (*p == '\\')
7474                                 p++;
7475                         *enddir++ = *p++;
7476                 } while (p < start);
7477         }
7478         if (enddir == expdir) {
7479                 cp = ".";
7480         } else if (enddir == expdir + 1 && *expdir == '/') {
7481                 cp = "/";
7482         } else {
7483                 cp = expdir;
7484                 enddir[-1] = '\0';
7485         }
7486         dirp = opendir(cp);
7487         if (dirp == NULL)
7488                 return;
7489         if (enddir != expdir)
7490                 enddir[-1] = '/';
7491         if (*endname == 0) {
7492                 atend = 1;
7493         } else {
7494                 atend = 0;
7495                 *endname = '\0';
7496                 endname += esc + 1;
7497         }
7498         matchdot = 0;
7499         p = start;
7500         if (*p == '\\')
7501                 p++;
7502         if (*p == '.')
7503                 matchdot++;
7504         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7505                 if (dp->d_name[0] == '.' && !matchdot)
7506                         continue;
7507                 if (pmatch(start, dp->d_name)) {
7508                         if (atend) {
7509                                 strcpy(enddir, dp->d_name);
7510                                 addfname(expdir);
7511                         } else {
7512                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7513                                         continue;
7514                                 p[-1] = '/';
7515                                 expmeta(expdir, p, endname);
7516                         }
7517                 }
7518         }
7519         closedir(dirp);
7520         if (!atend)
7521                 endname[-esc - 1] = esc ? '\\' : '/';
7522 }
7523
7524 static struct strlist *
7525 msort(struct strlist *list, int len)
7526 {
7527         struct strlist *p, *q = NULL;
7528         struct strlist **lpp;
7529         int half;
7530         int n;
7531
7532         if (len <= 1)
7533                 return list;
7534         half = len >> 1;
7535         p = list;
7536         for (n = half; --n >= 0;) {
7537                 q = p;
7538                 p = p->next;
7539         }
7540         q->next = NULL;                 /* terminate first half of list */
7541         q = msort(list, half);          /* sort first half of list */
7542         p = msort(p, len - half);               /* sort second half */
7543         lpp = &list;
7544         for (;;) {
7545 #if ENABLE_LOCALE_SUPPORT
7546                 if (strcoll(p->text, q->text) < 0)
7547 #else
7548                 if (strcmp(p->text, q->text) < 0)
7549 #endif
7550                                                 {
7551                         *lpp = p;
7552                         lpp = &p->next;
7553                         p = *lpp;
7554                         if (p == NULL) {
7555                                 *lpp = q;
7556                                 break;
7557                         }
7558                 } else {
7559                         *lpp = q;
7560                         lpp = &q->next;
7561                         q = *lpp;
7562                         if (q == NULL) {
7563                                 *lpp = p;
7564                                 break;
7565                         }
7566                 }
7567         }
7568         return list;
7569 }
7570
7571 /*
7572  * Sort the results of file name expansion.  It calculates the number of
7573  * strings to sort and then calls msort (short for merge sort) to do the
7574  * work.
7575  */
7576 static struct strlist *
7577 expsort(struct strlist *str)
7578 {
7579         int len;
7580         struct strlist *sp;
7581
7582         len = 0;
7583         for (sp = str; sp; sp = sp->next)
7584                 len++;
7585         return msort(str, len);
7586 }
7587
7588 static void
7589 expandmeta(struct strlist *str /*, int flag*/)
7590 {
7591         /* TODO - EXP_REDIR */
7592
7593         while (str) {
7594                 char *expdir;
7595                 struct strlist **savelastp;
7596                 struct strlist *sp;
7597                 char *p;
7598
7599                 if (fflag)
7600                         goto nometa;
7601                 if (!hasmeta(str->text))
7602                         goto nometa;
7603                 savelastp = exparg.lastp;
7604
7605                 INT_OFF;
7606                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7607                 {
7608                         int i = strlen(str->text);
7609 //BUGGY estimation of how long expanded name can be
7610                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7611                 }
7612                 expmeta(expdir, expdir, p);
7613                 free(expdir);
7614                 if (p != str->text)
7615                         free(p);
7616                 INT_ON;
7617                 if (exparg.lastp == savelastp) {
7618                         /*
7619                          * no matches
7620                          */
7621  nometa:
7622                         *exparg.lastp = str;
7623                         rmescapes(str->text, 0);
7624                         exparg.lastp = &str->next;
7625                 } else {
7626                         *exparg.lastp = NULL;
7627                         *savelastp = sp = expsort(*savelastp);
7628                         while (sp->next != NULL)
7629                                 sp = sp->next;
7630                         exparg.lastp = &sp->next;
7631                 }
7632                 str = str->next;
7633         }
7634 }
7635 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7636
7637 /*
7638  * Perform variable substitution and command substitution on an argument,
7639  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7640  * perform splitting and file name expansion.  When arglist is NULL, perform
7641  * here document expansion.
7642  */
7643 static void
7644 expandarg(union node *arg, struct arglist *arglist, int flag)
7645 {
7646         struct strlist *sp;
7647         char *p;
7648
7649         argbackq = arg->narg.backquote;
7650         STARTSTACKSTR(expdest);
7651         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7652         argstr(arg->narg.text, flag);
7653         p = _STPUTC('\0', expdest);
7654         expdest = p - 1;
7655         if (arglist == NULL) {
7656                 /* here document expanded */
7657                 goto out;
7658         }
7659         p = grabstackstr(p);
7660         TRACE(("expandarg: p:'%s'\n", p));
7661         exparg.lastp = &exparg.list;
7662         /*
7663          * TODO - EXP_REDIR
7664          */
7665         if (flag & EXP_FULL) {
7666                 ifsbreakup(p, &exparg);
7667                 *exparg.lastp = NULL;
7668                 exparg.lastp = &exparg.list;
7669                 expandmeta(exparg.list /*, flag*/);
7670         } else {
7671                 sp = stzalloc(sizeof(*sp));
7672                 sp->text = p;
7673                 *exparg.lastp = sp;
7674                 exparg.lastp = &sp->next;
7675         }
7676         *exparg.lastp = NULL;
7677         if (exparg.list) {
7678                 *arglist->lastp = exparg.list;
7679                 arglist->lastp = exparg.lastp;
7680         }
7681
7682  out:
7683         ifsfree();
7684 }
7685
7686 /*
7687  * Expand shell variables and backquotes inside a here document.
7688  */
7689 static void
7690 expandhere(union node *arg, int fd)
7691 {
7692         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7693         full_write(fd, stackblock(), expdest - (char *)stackblock());
7694 }
7695
7696 /*
7697  * Returns true if the pattern matches the string.
7698  */
7699 static int
7700 patmatch(char *pattern, const char *string)
7701 {
7702         char *p = preglob(pattern, 0);
7703         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7704         return pmatch(p, string);
7705 }
7706
7707 /*
7708  * See if a pattern matches in a case statement.
7709  */
7710 static int
7711 casematch(union node *pattern, char *val)
7712 {
7713         struct stackmark smark;
7714         int result;
7715
7716         setstackmark(&smark);
7717         argbackq = pattern->narg.backquote;
7718         STARTSTACKSTR(expdest);
7719         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7720         STACKSTRNUL(expdest);
7721         ifsfree();
7722         result = patmatch(stackblock(), val);
7723         popstackmark(&smark);
7724         return result;
7725 }
7726
7727
7728 /* ============ find_command */
7729
7730 struct builtincmd {
7731         const char *name;
7732         int (*builtin)(int, char **) FAST_FUNC;
7733         /* unsigned flags; */
7734 };
7735 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7736 /* "regular" builtins always take precedence over commands,
7737  * regardless of PATH=....%builtin... position */
7738 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7739 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7740
7741 struct cmdentry {
7742         smallint cmdtype;       /* CMDxxx */
7743         union param {
7744                 int index;
7745                 /* index >= 0 for commands without path (slashes) */
7746                 /* (TODO: what exactly does the value mean? PATH position?) */
7747                 /* index == -1 for commands with slashes */
7748                 /* index == (-2 - applet_no) for NOFORK applets */
7749                 const struct builtincmd *cmd;
7750                 struct funcnode *func;
7751         } u;
7752 };
7753 /* values of cmdtype */
7754 #define CMDUNKNOWN      -1      /* no entry in table for command */
7755 #define CMDNORMAL       0       /* command is an executable program */
7756 #define CMDFUNCTION     1       /* command is a shell function */
7757 #define CMDBUILTIN      2       /* command is a shell builtin */
7758
7759 /* action to find_command() */
7760 #define DO_ERR          0x01    /* prints errors */
7761 #define DO_ABS          0x02    /* checks absolute paths */
7762 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7763 #define DO_ALTPATH      0x08    /* using alternate path */
7764 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7765
7766 static void find_command(char *, struct cmdentry *, int, const char *);
7767
7768
7769 /* ============ Hashing commands */
7770
7771 /*
7772  * When commands are first encountered, they are entered in a hash table.
7773  * This ensures that a full path search will not have to be done for them
7774  * on each invocation.
7775  *
7776  * We should investigate converting to a linear search, even though that
7777  * would make the command name "hash" a misnomer.
7778  */
7779
7780 struct tblentry {
7781         struct tblentry *next;  /* next entry in hash chain */
7782         union param param;      /* definition of builtin function */
7783         smallint cmdtype;       /* CMDxxx */
7784         char rehash;            /* if set, cd done since entry created */
7785         char cmdname[1];        /* name of command */
7786 };
7787
7788 static struct tblentry **cmdtable;
7789 #define INIT_G_cmdtable() do { \
7790         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7791 } while (0)
7792
7793 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7794
7795
7796 static void
7797 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7798 {
7799 #if ENABLE_FEATURE_SH_STANDALONE
7800         if (applet_no >= 0) {
7801                 if (APPLET_IS_NOEXEC(applet_no)) {
7802                         clearenv();
7803                         while (*envp)
7804                                 putenv(*envp++);
7805                         popredir(/*drop:*/ 1);
7806 //TODO: prctl(PR_SET_NAME, (long)argv[0], 0, 0, 0);? [think pidof, pgrep, pkill]
7807 //Rewrite /proc/PID/cmdline? (need to save argv0 and length at init for this to work!)
7808                         run_applet_no_and_exit(applet_no, cmd, argv);
7809                 }
7810                 /* re-exec ourselves with the new arguments */
7811                 execve(bb_busybox_exec_path, argv, envp);
7812                 /* If they called chroot or otherwise made the binary no longer
7813                  * executable, fall through */
7814         }
7815 #endif
7816
7817  repeat:
7818 #ifdef SYSV
7819         do {
7820                 execve(cmd, argv, envp);
7821         } while (errno == EINTR);
7822 #else
7823         execve(cmd, argv, envp);
7824 #endif
7825         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7826                 /* Run "cmd" as a shell script:
7827                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7828                  * "If the execve() function fails with ENOEXEC, the shell
7829                  * shall execute a command equivalent to having a shell invoked
7830                  * with the command name as its first operand,
7831                  * with any remaining arguments passed to the new shell"
7832                  *
7833                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7834                  * just call ourselves.
7835                  *
7836                  * Note that bash reads ~80 chars of the file, and if it sees
7837                  * a zero byte before it sees newline, it doesn't try to
7838                  * interpret it, but fails with "cannot execute binary file"
7839                  * message and exit code 126. For one, this prevents attempts
7840                  * to interpret foreign ELF binaries as shell scripts.
7841                  */
7842                 argv[0] = (char*) cmd;
7843                 cmd = bb_busybox_exec_path;
7844                 /* NB: this is only possible because all callers of shellexec()
7845                  * ensure that the argv[-1] slot exists!
7846                  */
7847                 argv--;
7848                 argv[0] = (char*) "ash";
7849                 goto repeat;
7850         }
7851 }
7852
7853 /*
7854  * Exec a program.  Never returns.  If you change this routine, you may
7855  * have to change the find_command routine as well.
7856  * argv[-1] must exist and be writable! See tryexec() for why.
7857  */
7858 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7859 static void shellexec(char *prog, char **argv, const char *path, int idx)
7860 {
7861         char *cmdname;
7862         int e;
7863         char **envp;
7864         int exerrno;
7865         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7866
7867         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7868         if (strchr(prog, '/') != NULL
7869 #if ENABLE_FEATURE_SH_STANDALONE
7870          || (applet_no = find_applet_by_name(prog)) >= 0
7871 #endif
7872         ) {
7873                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7874                 if (applet_no >= 0) {
7875                         /* We tried execing ourself, but it didn't work.
7876                          * Maybe /proc/self/exe doesn't exist?
7877                          * Try $PATH search.
7878                          */
7879                         goto try_PATH;
7880                 }
7881                 e = errno;
7882         } else {
7883  try_PATH:
7884                 e = ENOENT;
7885                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7886                         if (--idx < 0 && pathopt == NULL) {
7887                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7888                                 if (errno != ENOENT && errno != ENOTDIR)
7889                                         e = errno;
7890                         }
7891                         stunalloc(cmdname);
7892                 }
7893         }
7894
7895         /* Map to POSIX errors */
7896         switch (e) {
7897         case EACCES:
7898                 exerrno = 126;
7899                 break;
7900         case ENOENT:
7901                 exerrno = 127;
7902                 break;
7903         default:
7904                 exerrno = 2;
7905                 break;
7906         }
7907         exitstatus = exerrno;
7908         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7909                 prog, e, suppress_int));
7910         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7911         /* NOTREACHED */
7912 }
7913
7914 static void
7915 printentry(struct tblentry *cmdp)
7916 {
7917         int idx;
7918         const char *path;
7919         char *name;
7920
7921         idx = cmdp->param.index;
7922         path = pathval();
7923         do {
7924                 name = path_advance(&path, cmdp->cmdname);
7925                 stunalloc(name);
7926         } while (--idx >= 0);
7927         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7928 }
7929
7930 /*
7931  * Clear out command entries.  The argument specifies the first entry in
7932  * PATH which has changed.
7933  */
7934 static void
7935 clearcmdentry(int firstchange)
7936 {
7937         struct tblentry **tblp;
7938         struct tblentry **pp;
7939         struct tblentry *cmdp;
7940
7941         INT_OFF;
7942         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7943                 pp = tblp;
7944                 while ((cmdp = *pp) != NULL) {
7945                         if ((cmdp->cmdtype == CMDNORMAL &&
7946                              cmdp->param.index >= firstchange)
7947                          || (cmdp->cmdtype == CMDBUILTIN &&
7948                              builtinloc >= firstchange)
7949                         ) {
7950                                 *pp = cmdp->next;
7951                                 free(cmdp);
7952                         } else {
7953                                 pp = &cmdp->next;
7954                         }
7955                 }
7956         }
7957         INT_ON;
7958 }
7959
7960 /*
7961  * Locate a command in the command hash table.  If "add" is nonzero,
7962  * add the command to the table if it is not already present.  The
7963  * variable "lastcmdentry" is set to point to the address of the link
7964  * pointing to the entry, so that delete_cmd_entry can delete the
7965  * entry.
7966  *
7967  * Interrupts must be off if called with add != 0.
7968  */
7969 static struct tblentry **lastcmdentry;
7970
7971 static struct tblentry *
7972 cmdlookup(const char *name, int add)
7973 {
7974         unsigned int hashval;
7975         const char *p;
7976         struct tblentry *cmdp;
7977         struct tblentry **pp;
7978
7979         p = name;
7980         hashval = (unsigned char)*p << 4;
7981         while (*p)
7982                 hashval += (unsigned char)*p++;
7983         hashval &= 0x7FFF;
7984         pp = &cmdtable[hashval % CMDTABLESIZE];
7985         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7986                 if (strcmp(cmdp->cmdname, name) == 0)
7987                         break;
7988                 pp = &cmdp->next;
7989         }
7990         if (add && cmdp == NULL) {
7991                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7992                                 + strlen(name)
7993                                 /* + 1 - already done because
7994                                  * tblentry::cmdname is char[1] */);
7995                 /*cmdp->next = NULL; - ckzalloc did it */
7996                 cmdp->cmdtype = CMDUNKNOWN;
7997                 strcpy(cmdp->cmdname, name);
7998         }
7999         lastcmdentry = pp;
8000         return cmdp;
8001 }
8002
8003 /*
8004  * Delete the command entry returned on the last lookup.
8005  */
8006 static void
8007 delete_cmd_entry(void)
8008 {
8009         struct tblentry *cmdp;
8010
8011         INT_OFF;
8012         cmdp = *lastcmdentry;
8013         *lastcmdentry = cmdp->next;
8014         if (cmdp->cmdtype == CMDFUNCTION)
8015                 freefunc(cmdp->param.func);
8016         free(cmdp);
8017         INT_ON;
8018 }
8019
8020 /*
8021  * Add a new command entry, replacing any existing command entry for
8022  * the same name - except special builtins.
8023  */
8024 static void
8025 addcmdentry(char *name, struct cmdentry *entry)
8026 {
8027         struct tblentry *cmdp;
8028
8029         cmdp = cmdlookup(name, 1);
8030         if (cmdp->cmdtype == CMDFUNCTION) {
8031                 freefunc(cmdp->param.func);
8032         }
8033         cmdp->cmdtype = entry->cmdtype;
8034         cmdp->param = entry->u;
8035         cmdp->rehash = 0;
8036 }
8037
8038 static int FAST_FUNC
8039 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8040 {
8041         struct tblentry **pp;
8042         struct tblentry *cmdp;
8043         int c;
8044         struct cmdentry entry;
8045         char *name;
8046
8047         if (nextopt("r") != '\0') {
8048                 clearcmdentry(0);
8049                 return 0;
8050         }
8051
8052         if (*argptr == NULL) {
8053                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8054                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8055                                 if (cmdp->cmdtype == CMDNORMAL)
8056                                         printentry(cmdp);
8057                         }
8058                 }
8059                 return 0;
8060         }
8061
8062         c = 0;
8063         while ((name = *argptr) != NULL) {
8064                 cmdp = cmdlookup(name, 0);
8065                 if (cmdp != NULL
8066                  && (cmdp->cmdtype == CMDNORMAL
8067                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8068                 ) {
8069                         delete_cmd_entry();
8070                 }
8071                 find_command(name, &entry, DO_ERR, pathval());
8072                 if (entry.cmdtype == CMDUNKNOWN)
8073                         c = 1;
8074                 argptr++;
8075         }
8076         return c;
8077 }
8078
8079 /*
8080  * Called when a cd is done.  Marks all commands so the next time they
8081  * are executed they will be rehashed.
8082  */
8083 static void
8084 hashcd(void)
8085 {
8086         struct tblentry **pp;
8087         struct tblentry *cmdp;
8088
8089         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8090                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8091                         if (cmdp->cmdtype == CMDNORMAL
8092                          || (cmdp->cmdtype == CMDBUILTIN
8093                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8094                              && builtinloc > 0)
8095                         ) {
8096                                 cmdp->rehash = 1;
8097                         }
8098                 }
8099         }
8100 }
8101
8102 /*
8103  * Fix command hash table when PATH changed.
8104  * Called before PATH is changed.  The argument is the new value of PATH;
8105  * pathval() still returns the old value at this point.
8106  * Called with interrupts off.
8107  */
8108 static void FAST_FUNC
8109 changepath(const char *new)
8110 {
8111         const char *old;
8112         int firstchange;
8113         int idx;
8114         int idx_bltin;
8115
8116         old = pathval();
8117         firstchange = 9999;     /* assume no change */
8118         idx = 0;
8119         idx_bltin = -1;
8120         for (;;) {
8121                 if (*old != *new) {
8122                         firstchange = idx;
8123                         if ((*old == '\0' && *new == ':')
8124                          || (*old == ':' && *new == '\0')
8125                         ) {
8126                                 firstchange++;
8127                         }
8128                         old = new;      /* ignore subsequent differences */
8129                 }
8130                 if (*new == '\0')
8131                         break;
8132                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8133                         idx_bltin = idx;
8134                 if (*new == ':')
8135                         idx++;
8136                 new++;
8137                 old++;
8138         }
8139         if (builtinloc < 0 && idx_bltin >= 0)
8140                 builtinloc = idx_bltin;             /* zap builtins */
8141         if (builtinloc >= 0 && idx_bltin < 0)
8142                 firstchange = 0;
8143         clearcmdentry(firstchange);
8144         builtinloc = idx_bltin;
8145 }
8146 enum {
8147         TEOF,
8148         TNL,
8149         TREDIR,
8150         TWORD,
8151         TSEMI,
8152         TBACKGND,
8153         TAND,
8154         TOR,
8155         TPIPE,
8156         TLP,
8157         TRP,
8158         TENDCASE,
8159         TENDBQUOTE,
8160         TNOT,
8161         TCASE,
8162         TDO,
8163         TDONE,
8164         TELIF,
8165         TELSE,
8166         TESAC,
8167         TFI,
8168         TFOR,
8169 #if BASH_FUNCTION
8170         TFUNCTION,
8171 #endif
8172         TIF,
8173         TIN,
8174         TTHEN,
8175         TUNTIL,
8176         TWHILE,
8177         TBEGIN,
8178         TEND
8179 };
8180 typedef smallint token_id_t;
8181
8182 /* Nth bit indicates if token marks the end of a list */
8183 enum {
8184         tokendlist = 0
8185         /*  0 */ | (1u << TEOF)
8186         /*  1 */ | (0u << TNL)
8187         /*  2 */ | (0u << TREDIR)
8188         /*  3 */ | (0u << TWORD)
8189         /*  4 */ | (0u << TSEMI)
8190         /*  5 */ | (0u << TBACKGND)
8191         /*  6 */ | (0u << TAND)
8192         /*  7 */ | (0u << TOR)
8193         /*  8 */ | (0u << TPIPE)
8194         /*  9 */ | (0u << TLP)
8195         /* 10 */ | (1u << TRP)
8196         /* 11 */ | (1u << TENDCASE)
8197         /* 12 */ | (1u << TENDBQUOTE)
8198         /* 13 */ | (0u << TNOT)
8199         /* 14 */ | (0u << TCASE)
8200         /* 15 */ | (1u << TDO)
8201         /* 16 */ | (1u << TDONE)
8202         /* 17 */ | (1u << TELIF)
8203         /* 18 */ | (1u << TELSE)
8204         /* 19 */ | (1u << TESAC)
8205         /* 20 */ | (1u << TFI)
8206         /* 21 */ | (0u << TFOR)
8207 #if BASH_FUNCTION
8208         /* 22 */ | (0u << TFUNCTION)
8209 #endif
8210         /* 23 */ | (0u << TIF)
8211         /* 24 */ | (0u << TIN)
8212         /* 25 */ | (1u << TTHEN)
8213         /* 26 */ | (0u << TUNTIL)
8214         /* 27 */ | (0u << TWHILE)
8215         /* 28 */ | (0u << TBEGIN)
8216         /* 29 */ | (1u << TEND)
8217         , /* thus far 29 bits used */
8218 };
8219
8220 static const char *const tokname_array[] = {
8221         "end of file",
8222         "newline",
8223         "redirection",
8224         "word",
8225         ";",
8226         "&",
8227         "&&",
8228         "||",
8229         "|",
8230         "(",
8231         ")",
8232         ";;",
8233         "`",
8234 #define KWDOFFSET 13
8235         /* the following are keywords */
8236         "!",
8237         "case",
8238         "do",
8239         "done",
8240         "elif",
8241         "else",
8242         "esac",
8243         "fi",
8244         "for",
8245 #if BASH_FUNCTION
8246         "function",
8247 #endif
8248         "if",
8249         "in",
8250         "then",
8251         "until",
8252         "while",
8253         "{",
8254         "}",
8255 };
8256
8257 /* Wrapper around strcmp for qsort/bsearch/... */
8258 static int
8259 pstrcmp(const void *a, const void *b)
8260 {
8261         return strcmp((char*)a, *(char**)b);
8262 }
8263
8264 static const char *const *
8265 findkwd(const char *s)
8266 {
8267         return bsearch(s, tokname_array + KWDOFFSET,
8268                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8269                         sizeof(tokname_array[0]), pstrcmp);
8270 }
8271
8272 /*
8273  * Locate and print what a word is...
8274  */
8275 static int
8276 describe_command(char *command, const char *path, int describe_command_verbose)
8277 {
8278         struct cmdentry entry;
8279 #if ENABLE_ASH_ALIAS
8280         const struct alias *ap;
8281 #endif
8282
8283         path = path ? path : pathval();
8284
8285         if (describe_command_verbose) {
8286                 out1str(command);
8287         }
8288
8289         /* First look at the keywords */
8290         if (findkwd(command)) {
8291                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8292                 goto out;
8293         }
8294
8295 #if ENABLE_ASH_ALIAS
8296         /* Then look at the aliases */
8297         ap = lookupalias(command, 0);
8298         if (ap != NULL) {
8299                 if (!describe_command_verbose) {
8300                         out1str("alias ");
8301                         printalias(ap);
8302                         return 0;
8303                 }
8304                 out1fmt(" is an alias for %s", ap->val);
8305                 goto out;
8306         }
8307 #endif
8308         /* Brute force */
8309         find_command(command, &entry, DO_ABS, path);
8310
8311         switch (entry.cmdtype) {
8312         case CMDNORMAL: {
8313                 int j = entry.u.index;
8314                 char *p;
8315                 if (j < 0) {
8316                         p = command;
8317                 } else {
8318                         do {
8319                                 p = path_advance(&path, command);
8320                                 stunalloc(p);
8321                         } while (--j >= 0);
8322                 }
8323                 if (describe_command_verbose) {
8324                         out1fmt(" is %s", p);
8325                 } else {
8326                         out1str(p);
8327                 }
8328                 break;
8329         }
8330
8331         case CMDFUNCTION:
8332                 if (describe_command_verbose) {
8333                         out1str(" is a shell function");
8334                 } else {
8335                         out1str(command);
8336                 }
8337                 break;
8338
8339         case CMDBUILTIN:
8340                 if (describe_command_verbose) {
8341                         out1fmt(" is a %sshell builtin",
8342                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8343                                         "special " : nullstr
8344                         );
8345                 } else {
8346                         out1str(command);
8347                 }
8348                 break;
8349
8350         default:
8351                 if (describe_command_verbose) {
8352                         out1str(": not found\n");
8353                 }
8354                 return 127;
8355         }
8356  out:
8357         out1str("\n");
8358         return 0;
8359 }
8360
8361 static int FAST_FUNC
8362 typecmd(int argc UNUSED_PARAM, char **argv)
8363 {
8364         int i = 1;
8365         int err = 0;
8366         int verbose = 1;
8367
8368         /* type -p ... ? (we don't bother checking for 'p') */
8369         if (argv[1] && argv[1][0] == '-') {
8370                 i++;
8371                 verbose = 0;
8372         }
8373         while (argv[i]) {
8374                 err |= describe_command(argv[i++], NULL, verbose);
8375         }
8376         return err;
8377 }
8378
8379 #if ENABLE_ASH_CMDCMD
8380 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8381 static char **
8382 parse_command_args(char **argv, const char **path)
8383 {
8384         char *cp, c;
8385
8386         for (;;) {
8387                 cp = *++argv;
8388                 if (!cp)
8389                         return NULL;
8390                 if (*cp++ != '-')
8391                         break;
8392                 c = *cp++;
8393                 if (!c)
8394                         break;
8395                 if (c == '-' && !*cp) {
8396                         if (!*++argv)
8397                                 return NULL;
8398                         break;
8399                 }
8400                 do {
8401                         switch (c) {
8402                         case 'p':
8403                                 *path = bb_default_path;
8404                                 break;
8405                         default:
8406                                 /* run 'typecmd' for other options */
8407                                 return NULL;
8408                         }
8409                         c = *cp++;
8410                 } while (c);
8411         }
8412         return argv;
8413 }
8414
8415 static int FAST_FUNC
8416 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8417 {
8418         char *cmd;
8419         int c;
8420         enum {
8421                 VERIFY_BRIEF = 1,
8422                 VERIFY_VERBOSE = 2,
8423         } verify = 0;
8424         const char *path = NULL;
8425
8426         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8427          * never reaches this function.
8428          */
8429
8430         while ((c = nextopt("pvV")) != '\0')
8431                 if (c == 'V')
8432                         verify |= VERIFY_VERBOSE;
8433                 else if (c == 'v')
8434                         /*verify |= VERIFY_BRIEF*/;
8435 #if DEBUG
8436                 else if (c != 'p')
8437                         abort();
8438 #endif
8439                 else
8440                         path = bb_default_path;
8441
8442         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8443         cmd = *argptr;
8444         if (/*verify && */ cmd)
8445                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8446
8447         return 0;
8448 }
8449 #endif
8450
8451
8452 /*static int funcblocksize;     // size of structures in function */
8453 /*static int funcstringsize;    // size of strings in node */
8454 static void *funcblock;         /* block to allocate function from */
8455 static char *funcstring_end;    /* end of block to allocate strings from */
8456
8457 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8458         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8459         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8460         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8461         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8462         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8463         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8464         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8465         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8466         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8467         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8468         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8469         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8470         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8471         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8472         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8473         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8474         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8475 #if BASH_REDIR_OUTPUT
8476         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8477 #endif
8478         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8479         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8480         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8481         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8482         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8483         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8484         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8485         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8486         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8487 };
8488
8489 static int calcsize(int funcblocksize, union node *n);
8490
8491 static int
8492 sizenodelist(int funcblocksize, struct nodelist *lp)
8493 {
8494         while (lp) {
8495                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8496                 funcblocksize = calcsize(funcblocksize, lp->n);
8497                 lp = lp->next;
8498         }
8499         return funcblocksize;
8500 }
8501
8502 static int
8503 calcsize(int funcblocksize, union node *n)
8504 {
8505         if (n == NULL)
8506                 return funcblocksize;
8507         funcblocksize += nodesize[n->type];
8508         switch (n->type) {
8509         case NCMD:
8510                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8511                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8512                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8513                 break;
8514         case NPIPE:
8515                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8516                 break;
8517         case NREDIR:
8518         case NBACKGND:
8519         case NSUBSHELL:
8520                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8521                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8522                 break;
8523         case NAND:
8524         case NOR:
8525         case NSEMI:
8526         case NWHILE:
8527         case NUNTIL:
8528                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8529                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8530                 break;
8531         case NIF:
8532                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8533                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8534                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8535                 break;
8536         case NFOR:
8537                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8538                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8539                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8540                 break;
8541         case NCASE:
8542                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8543                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8544                 break;
8545         case NCLIST:
8546                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8547                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8548                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8549                 break;
8550         case NDEFUN:
8551         case NARG:
8552                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8553                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8554                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8555                 break;
8556         case NTO:
8557 #if BASH_REDIR_OUTPUT
8558         case NTO2:
8559 #endif
8560         case NCLOBBER:
8561         case NFROM:
8562         case NFROMTO:
8563         case NAPPEND:
8564                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8565                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8566                 break;
8567         case NTOFD:
8568         case NFROMFD:
8569                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8570                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8571         break;
8572         case NHERE:
8573         case NXHERE:
8574                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8575                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8576                 break;
8577         case NNOT:
8578                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8579                 break;
8580         };
8581         return funcblocksize;
8582 }
8583
8584 static char *
8585 nodeckstrdup(char *s)
8586 {
8587         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8588         return strcpy(funcstring_end, s);
8589 }
8590
8591 static union node *copynode(union node *);
8592
8593 static struct nodelist *
8594 copynodelist(struct nodelist *lp)
8595 {
8596         struct nodelist *start;
8597         struct nodelist **lpp;
8598
8599         lpp = &start;
8600         while (lp) {
8601                 *lpp = funcblock;
8602                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8603                 (*lpp)->n = copynode(lp->n);
8604                 lp = lp->next;
8605                 lpp = &(*lpp)->next;
8606         }
8607         *lpp = NULL;
8608         return start;
8609 }
8610
8611 static union node *
8612 copynode(union node *n)
8613 {
8614         union node *new;
8615
8616         if (n == NULL)
8617                 return NULL;
8618         new = funcblock;
8619         funcblock = (char *) funcblock + nodesize[n->type];
8620
8621         switch (n->type) {
8622         case NCMD:
8623                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8624                 new->ncmd.args = copynode(n->ncmd.args);
8625                 new->ncmd.assign = copynode(n->ncmd.assign);
8626                 break;
8627         case NPIPE:
8628                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8629                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8630                 break;
8631         case NREDIR:
8632         case NBACKGND:
8633         case NSUBSHELL:
8634                 new->nredir.redirect = copynode(n->nredir.redirect);
8635                 new->nredir.n = copynode(n->nredir.n);
8636                 break;
8637         case NAND:
8638         case NOR:
8639         case NSEMI:
8640         case NWHILE:
8641         case NUNTIL:
8642                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8643                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8644                 break;
8645         case NIF:
8646                 new->nif.elsepart = copynode(n->nif.elsepart);
8647                 new->nif.ifpart = copynode(n->nif.ifpart);
8648                 new->nif.test = copynode(n->nif.test);
8649                 break;
8650         case NFOR:
8651                 new->nfor.var = nodeckstrdup(n->nfor.var);
8652                 new->nfor.body = copynode(n->nfor.body);
8653                 new->nfor.args = copynode(n->nfor.args);
8654                 break;
8655         case NCASE:
8656                 new->ncase.cases = copynode(n->ncase.cases);
8657                 new->ncase.expr = copynode(n->ncase.expr);
8658                 break;
8659         case NCLIST:
8660                 new->nclist.body = copynode(n->nclist.body);
8661                 new->nclist.pattern = copynode(n->nclist.pattern);
8662                 new->nclist.next = copynode(n->nclist.next);
8663                 break;
8664         case NDEFUN:
8665         case NARG:
8666                 new->narg.backquote = copynodelist(n->narg.backquote);
8667                 new->narg.text = nodeckstrdup(n->narg.text);
8668                 new->narg.next = copynode(n->narg.next);
8669                 break;
8670         case NTO:
8671 #if BASH_REDIR_OUTPUT
8672         case NTO2:
8673 #endif
8674         case NCLOBBER:
8675         case NFROM:
8676         case NFROMTO:
8677         case NAPPEND:
8678                 new->nfile.fname = copynode(n->nfile.fname);
8679                 new->nfile.fd = n->nfile.fd;
8680                 new->nfile.next = copynode(n->nfile.next);
8681                 break;
8682         case NTOFD:
8683         case NFROMFD:
8684                 new->ndup.vname = copynode(n->ndup.vname);
8685                 new->ndup.dupfd = n->ndup.dupfd;
8686                 new->ndup.fd = n->ndup.fd;
8687                 new->ndup.next = copynode(n->ndup.next);
8688                 break;
8689         case NHERE:
8690         case NXHERE:
8691                 new->nhere.doc = copynode(n->nhere.doc);
8692                 new->nhere.fd = n->nhere.fd;
8693                 new->nhere.next = copynode(n->nhere.next);
8694                 break;
8695         case NNOT:
8696                 new->nnot.com = copynode(n->nnot.com);
8697                 break;
8698         };
8699         new->type = n->type;
8700         return new;
8701 }
8702
8703 /*
8704  * Make a copy of a parse tree.
8705  */
8706 static struct funcnode *
8707 copyfunc(union node *n)
8708 {
8709         struct funcnode *f;
8710         size_t blocksize;
8711
8712         /*funcstringsize = 0;*/
8713         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8714         f = ckzalloc(blocksize /* + funcstringsize */);
8715         funcblock = (char *) f + offsetof(struct funcnode, n);
8716         funcstring_end = (char *) f + blocksize;
8717         copynode(n);
8718         /* f->count = 0; - ckzalloc did it */
8719         return f;
8720 }
8721
8722 /*
8723  * Define a shell function.
8724  */
8725 static void
8726 defun(union node *func)
8727 {
8728         struct cmdentry entry;
8729
8730         INT_OFF;
8731         entry.cmdtype = CMDFUNCTION;
8732         entry.u.func = copyfunc(func);
8733         addcmdentry(func->narg.text, &entry);
8734         INT_ON;
8735 }
8736
8737 /* Reasons for skipping commands (see comment on breakcmd routine) */
8738 #define SKIPBREAK      (1 << 0)
8739 #define SKIPCONT       (1 << 1)
8740 #define SKIPFUNC       (1 << 2)
8741 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8742 static int skipcount;           /* number of levels to skip */
8743 static int funcnest;            /* depth of function calls */
8744 static int loopnest;            /* current loop nesting level */
8745
8746 /* Forward decl way out to parsing code - dotrap needs it */
8747 static int evalstring(char *s, int flags);
8748
8749 /* Called to execute a trap.
8750  * Single callsite - at the end of evaltree().
8751  * If we return non-zero, evaltree raises EXEXIT exception.
8752  *
8753  * Perhaps we should avoid entering new trap handlers
8754  * while we are executing a trap handler. [is it a TODO?]
8755  */
8756 static void
8757 dotrap(void)
8758 {
8759         uint8_t *g;
8760         int sig;
8761         uint8_t last_status;
8762
8763         if (!pending_sig)
8764                 return;
8765
8766         last_status = exitstatus;
8767         pending_sig = 0;
8768         barrier();
8769
8770         TRACE(("dotrap entered\n"));
8771         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8772                 char *p;
8773
8774                 if (!*g)
8775                         continue;
8776
8777                 if (evalskip) {
8778                         pending_sig = sig;
8779                         break;
8780                 }
8781
8782                 p = trap[sig];
8783                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8784                  * don't upset it by resetting gotsig[SIGINT-1] */
8785                 if (sig == SIGINT && !p)
8786                         continue;
8787
8788                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8789                 *g = 0;
8790                 if (!p)
8791                         continue;
8792                 evalstring(p, 0);
8793         }
8794         exitstatus = last_status;
8795         TRACE(("dotrap returns\n"));
8796 }
8797
8798 /* forward declarations - evaluation is fairly recursive business... */
8799 static int evalloop(union node *, int);
8800 static int evalfor(union node *, int);
8801 static int evalcase(union node *, int);
8802 static int evalsubshell(union node *, int);
8803 static void expredir(union node *);
8804 static int evalpipe(union node *, int);
8805 static int evalcommand(union node *, int);
8806 static int evalbltin(const struct builtincmd *, int, char **, int);
8807 static void prehash(union node *);
8808
8809 /*
8810  * Evaluate a parse tree.  The value is left in the global variable
8811  * exitstatus.
8812  */
8813 static int
8814 evaltree(union node *n, int flags)
8815 {
8816         int checkexit = 0;
8817         int (*evalfn)(union node *, int);
8818         int status = 0;
8819
8820         if (n == NULL) {
8821                 TRACE(("evaltree(NULL) called\n"));
8822                 goto out;
8823         }
8824         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8825
8826         dotrap();
8827
8828         switch (n->type) {
8829         default:
8830 #if DEBUG
8831                 out1fmt("Node type = %d\n", n->type);
8832                 fflush_all();
8833                 break;
8834 #endif
8835         case NNOT:
8836                 status = !evaltree(n->nnot.com, EV_TESTED);
8837                 goto setstatus;
8838         case NREDIR:
8839                 expredir(n->nredir.redirect);
8840                 pushredir(n->nredir.redirect);
8841                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8842                 if (!status) {
8843                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8844                 }
8845                 if (n->nredir.redirect)
8846                         popredir(/*drop:*/ 0);
8847                 goto setstatus;
8848         case NCMD:
8849                 evalfn = evalcommand;
8850  checkexit:
8851                 if (eflag && !(flags & EV_TESTED))
8852                         checkexit = ~0;
8853                 goto calleval;
8854         case NFOR:
8855                 evalfn = evalfor;
8856                 goto calleval;
8857         case NWHILE:
8858         case NUNTIL:
8859                 evalfn = evalloop;
8860                 goto calleval;
8861         case NSUBSHELL:
8862         case NBACKGND:
8863                 evalfn = evalsubshell;
8864                 goto checkexit;
8865         case NPIPE:
8866                 evalfn = evalpipe;
8867                 goto checkexit;
8868         case NCASE:
8869                 evalfn = evalcase;
8870                 goto calleval;
8871         case NAND:
8872         case NOR:
8873         case NSEMI: {
8874
8875 #if NAND + 1 != NOR
8876 #error NAND + 1 != NOR
8877 #endif
8878 #if NOR + 1 != NSEMI
8879 #error NOR + 1 != NSEMI
8880 #endif
8881                 unsigned is_or = n->type - NAND;
8882                 status = evaltree(
8883                         n->nbinary.ch1,
8884                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8885                 );
8886                 if ((!status) == is_or || evalskip)
8887                         break;
8888                 n = n->nbinary.ch2;
8889  evaln:
8890                 evalfn = evaltree;
8891  calleval:
8892                 status = evalfn(n, flags);
8893                 goto setstatus;
8894         }
8895         case NIF:
8896                 status = evaltree(n->nif.test, EV_TESTED);
8897                 if (evalskip)
8898                         break;
8899                 if (!status) {
8900                         n = n->nif.ifpart;
8901                         goto evaln;
8902                 }
8903                 if (n->nif.elsepart) {
8904                         n = n->nif.elsepart;
8905                         goto evaln;
8906                 }
8907                 status = 0;
8908                 goto setstatus;
8909         case NDEFUN:
8910                 defun(n);
8911                 /* Not necessary. To test it:
8912                  * "false; f() { qwerty; }; echo $?" should print 0.
8913                  */
8914                 /* status = 0; */
8915  setstatus:
8916                 exitstatus = status;
8917                 break;
8918         }
8919  out:
8920         /* Order of checks below is important:
8921          * signal handlers trigger before exit caused by "set -e".
8922          */
8923         dotrap();
8924
8925         if (checkexit & status)
8926                 raise_exception(EXEXIT);
8927         if (flags & EV_EXIT)
8928                 raise_exception(EXEXIT);
8929
8930         TRACE(("leaving evaltree (no interrupts)\n"));
8931         return exitstatus;
8932 }
8933
8934 static int
8935 skiploop(void)
8936 {
8937         int skip = evalskip;
8938
8939         switch (skip) {
8940         case 0:
8941                 break;
8942         case SKIPBREAK:
8943         case SKIPCONT:
8944                 if (--skipcount <= 0) {
8945                         evalskip = 0;
8946                         break;
8947                 }
8948                 skip = SKIPBREAK;
8949                 break;
8950         }
8951         return skip;
8952 }
8953
8954 static int
8955 evalloop(union node *n, int flags)
8956 {
8957         int skip;
8958         int status;
8959
8960         loopnest++;
8961         status = 0;
8962         flags &= EV_TESTED;
8963         do {
8964                 int i;
8965
8966                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8967                 skip = skiploop();
8968                 if (skip == SKIPFUNC)
8969                         status = i;
8970                 if (skip)
8971                         continue;
8972                 if (n->type != NWHILE)
8973                         i = !i;
8974                 if (i != 0)
8975                         break;
8976                 status = evaltree(n->nbinary.ch2, flags);
8977                 skip = skiploop();
8978         } while (!(skip & ~SKIPCONT));
8979         loopnest--;
8980
8981         return status;
8982 }
8983
8984 static int
8985 evalfor(union node *n, int flags)
8986 {
8987         struct arglist arglist;
8988         union node *argp;
8989         struct strlist *sp;
8990         struct stackmark smark;
8991         int status = 0;
8992
8993         setstackmark(&smark);
8994         arglist.list = NULL;
8995         arglist.lastp = &arglist.list;
8996         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8997                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8998         }
8999         *arglist.lastp = NULL;
9000
9001         loopnest++;
9002         flags &= EV_TESTED;
9003         for (sp = arglist.list; sp; sp = sp->next) {
9004                 setvar0(n->nfor.var, sp->text);
9005                 status = evaltree(n->nfor.body, flags);
9006                 if (skiploop() & ~SKIPCONT)
9007                         break;
9008         }
9009         loopnest--;
9010         popstackmark(&smark);
9011
9012         return status;
9013 }
9014
9015 static int
9016 evalcase(union node *n, int flags)
9017 {
9018         union node *cp;
9019         union node *patp;
9020         struct arglist arglist;
9021         struct stackmark smark;
9022         int status = 0;
9023
9024         setstackmark(&smark);
9025         arglist.list = NULL;
9026         arglist.lastp = &arglist.list;
9027         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9028         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9029                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9030                         if (casematch(patp, arglist.list->text)) {
9031                                 /* Ensure body is non-empty as otherwise
9032                                  * EV_EXIT may prevent us from setting the
9033                                  * exit status.
9034                                  */
9035                                 if (evalskip == 0 && cp->nclist.body) {
9036                                         status = evaltree(cp->nclist.body, flags);
9037                                 }
9038                                 goto out;
9039                         }
9040                 }
9041         }
9042  out:
9043         popstackmark(&smark);
9044
9045         return status;
9046 }
9047
9048 /*
9049  * Kick off a subshell to evaluate a tree.
9050  */
9051 static int
9052 evalsubshell(union node *n, int flags)
9053 {
9054         struct job *jp;
9055         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9056         int status;
9057
9058         expredir(n->nredir.redirect);
9059         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9060                 goto nofork;
9061         INT_OFF;
9062         if (backgnd == FORK_FG)
9063                 get_tty_state();
9064         jp = makejob(/*n,*/ 1);
9065         if (forkshell(jp, n, backgnd) == 0) {
9066                 /* child */
9067                 INT_ON;
9068                 flags |= EV_EXIT;
9069                 if (backgnd)
9070                         flags &= ~EV_TESTED;
9071  nofork:
9072                 redirect(n->nredir.redirect, 0);
9073                 evaltreenr(n->nredir.n, flags);
9074                 /* never returns */
9075         }
9076         /* parent */
9077         status = 0;
9078         if (backgnd == FORK_FG)
9079                 status = waitforjob(jp);
9080         INT_ON;
9081         return status;
9082 }
9083
9084 /*
9085  * Compute the names of the files in a redirection list.
9086  */
9087 static void fixredir(union node *, const char *, int);
9088 static void
9089 expredir(union node *n)
9090 {
9091         union node *redir;
9092
9093         for (redir = n; redir; redir = redir->nfile.next) {
9094                 struct arglist fn;
9095
9096                 fn.list = NULL;
9097                 fn.lastp = &fn.list;
9098                 switch (redir->type) {
9099                 case NFROMTO:
9100                 case NFROM:
9101                 case NTO:
9102 #if BASH_REDIR_OUTPUT
9103                 case NTO2:
9104 #endif
9105                 case NCLOBBER:
9106                 case NAPPEND:
9107                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9108                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9109 #if BASH_REDIR_OUTPUT
9110  store_expfname:
9111 #endif
9112 #if 0
9113 // By the design of stack allocator, the loop of this kind:
9114 //      while true; do while true; do break; done </dev/null; done
9115 // will look like a memory leak: ash plans to free expfname's
9116 // of "/dev/null" as soon as it finishes running the loop
9117 // (in this case, never).
9118 // This "fix" is wrong:
9119                         if (redir->nfile.expfname)
9120                                 stunalloc(redir->nfile.expfname);
9121 // It results in corrupted state of stacked allocations.
9122 #endif
9123                         redir->nfile.expfname = fn.list->text;
9124                         break;
9125                 case NFROMFD:
9126                 case NTOFD: /* >& */
9127                         if (redir->ndup.vname) {
9128                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9129                                 if (fn.list == NULL)
9130                                         ash_msg_and_raise_error("redir error");
9131 #if BASH_REDIR_OUTPUT
9132 //FIXME: we used expandarg with different args!
9133                                 if (!isdigit_str9(fn.list->text)) {
9134                                         /* >&file, not >&fd */
9135                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9136                                                 ash_msg_and_raise_error("redir error");
9137                                         redir->type = NTO2;
9138                                         goto store_expfname;
9139                                 }
9140 #endif
9141                                 fixredir(redir, fn.list->text, 1);
9142                         }
9143                         break;
9144                 }
9145         }
9146 }
9147
9148 /*
9149  * Evaluate a pipeline.  All the processes in the pipeline are children
9150  * of the process creating the pipeline.  (This differs from some versions
9151  * of the shell, which make the last process in a pipeline the parent
9152  * of all the rest.)
9153  */
9154 static int
9155 evalpipe(union node *n, int flags)
9156 {
9157         struct job *jp;
9158         struct nodelist *lp;
9159         int pipelen;
9160         int prevfd;
9161         int pip[2];
9162         int status = 0;
9163
9164         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9165         pipelen = 0;
9166         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9167                 pipelen++;
9168         flags |= EV_EXIT;
9169         INT_OFF;
9170         if (n->npipe.pipe_backgnd == 0)
9171                 get_tty_state();
9172         jp = makejob(/*n,*/ pipelen);
9173         prevfd = -1;
9174         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9175                 prehash(lp->n);
9176                 pip[1] = -1;
9177                 if (lp->next) {
9178                         if (pipe(pip) < 0) {
9179                                 close(prevfd);
9180                                 ash_msg_and_raise_error("pipe call failed");
9181                         }
9182                 }
9183                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9184                         /* child */
9185                         INT_ON;
9186                         if (pip[1] >= 0) {
9187                                 close(pip[0]);
9188                         }
9189                         if (prevfd > 0) {
9190                                 dup2(prevfd, 0);
9191                                 close(prevfd);
9192                         }
9193                         if (pip[1] > 1) {
9194                                 dup2(pip[1], 1);
9195                                 close(pip[1]);
9196                         }
9197                         evaltreenr(lp->n, flags);
9198                         /* never returns */
9199                 }
9200                 /* parent */
9201                 if (prevfd >= 0)
9202                         close(prevfd);
9203                 prevfd = pip[0];
9204                 /* Don't want to trigger debugging */
9205                 if (pip[1] != -1)
9206                         close(pip[1]);
9207         }
9208         if (n->npipe.pipe_backgnd == 0) {
9209                 status = waitforjob(jp);
9210                 TRACE(("evalpipe:  job done exit status %d\n", status));
9211         }
9212         INT_ON;
9213
9214         return status;
9215 }
9216
9217 /*
9218  * Controls whether the shell is interactive or not.
9219  */
9220 static void
9221 setinteractive(int on)
9222 {
9223         static smallint is_interactive;
9224
9225         if (++on == is_interactive)
9226                 return;
9227         is_interactive = on;
9228         setsignal(SIGINT);
9229         setsignal(SIGQUIT);
9230         setsignal(SIGTERM);
9231 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9232         if (is_interactive > 1) {
9233                 /* Looks like they want an interactive shell */
9234                 static smallint did_banner;
9235
9236                 if (!did_banner) {
9237                         /* note: ash and hush share this string */
9238                         out1fmt("\n\n%s %s\n"
9239                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9240                                 "\n",
9241                                 bb_banner,
9242                                 "built-in shell (ash)"
9243                         );
9244                         did_banner = 1;
9245                 }
9246         }
9247 #endif
9248 }
9249
9250 static void
9251 optschanged(void)
9252 {
9253 #if DEBUG
9254         opentrace();
9255 #endif
9256         setinteractive(iflag);
9257         setjobctl(mflag);
9258 #if ENABLE_FEATURE_EDITING_VI
9259         if (viflag)
9260                 line_input_state->flags |= VI_MODE;
9261         else
9262                 line_input_state->flags &= ~VI_MODE;
9263 #else
9264         viflag = 0; /* forcibly keep the option off */
9265 #endif
9266 }
9267
9268 struct localvar_list {
9269         struct localvar_list *next;
9270         struct localvar *lv;
9271 };
9272
9273 static struct localvar_list *localvar_stack;
9274
9275 /*
9276  * Called after a function returns.
9277  * Interrupts must be off.
9278  */
9279 static void
9280 poplocalvars(int keep)
9281 {
9282         struct localvar_list *ll;
9283         struct localvar *lvp, *next;
9284         struct var *vp;
9285
9286         INT_OFF;
9287         ll = localvar_stack;
9288         localvar_stack = ll->next;
9289
9290         next = ll->lv;
9291         free(ll);
9292
9293         while ((lvp = next) != NULL) {
9294                 next = lvp->next;
9295                 vp = lvp->vp;
9296                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9297                 if (keep) {
9298                         int bits = VSTRFIXED;
9299
9300                         if (lvp->flags != VUNSET) {
9301                                 if (vp->var_text == lvp->text)
9302                                         bits |= VTEXTFIXED;
9303                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9304                                         free((char*)lvp->text);
9305                         }
9306
9307                         vp->flags &= ~bits;
9308                         vp->flags |= (lvp->flags & bits);
9309
9310                         if ((vp->flags &
9311                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9312                                 unsetvar(vp->var_text);
9313                 } else if (vp == NULL) {        /* $- saved */
9314                         memcpy(optlist, lvp->text, sizeof(optlist));
9315                         free((char*)lvp->text);
9316                         optschanged();
9317                 } else if (lvp->flags == VUNSET) {
9318                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9319                         unsetvar(vp->var_text);
9320                 } else {
9321                         if (vp->var_func)
9322                                 vp->var_func(var_end(lvp->text));
9323                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9324                                 free((char*)vp->var_text);
9325                         vp->flags = lvp->flags;
9326                         vp->var_text = lvp->text;
9327                 }
9328                 free(lvp);
9329         }
9330         INT_ON;
9331 }
9332
9333 /*
9334  * Create a new localvar environment.
9335  */
9336 static struct localvar_list *
9337 pushlocalvars(void)
9338 {
9339         struct localvar_list *ll;
9340
9341         INT_OFF;
9342         ll = ckzalloc(sizeof(*ll));
9343         /*ll->lv = NULL; - zalloc did it */
9344         ll->next = localvar_stack;
9345         localvar_stack = ll;
9346         INT_ON;
9347
9348         return ll->next;
9349 }
9350
9351 static void
9352 unwindlocalvars(struct localvar_list *stop)
9353 {
9354         while (localvar_stack != stop)
9355                 poplocalvars(0);
9356 }
9357
9358 static int
9359 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9360 {
9361         volatile struct shparam saveparam;
9362         struct jmploc *volatile savehandler;
9363         struct jmploc jmploc;
9364         int e;
9365
9366         saveparam = shellparam;
9367         savehandler = exception_handler;
9368         e = setjmp(jmploc.loc);
9369         if (e) {
9370                 goto funcdone;
9371         }
9372         INT_OFF;
9373         exception_handler = &jmploc;
9374         shellparam.malloced = 0;
9375         func->count++;
9376         funcnest++;
9377         INT_ON;
9378         shellparam.nparam = argc - 1;
9379         shellparam.p = argv + 1;
9380 #if ENABLE_ASH_GETOPTS
9381         shellparam.optind = 1;
9382         shellparam.optoff = -1;
9383 #endif
9384         pushlocalvars();
9385         evaltree(func->n.narg.next, flags & EV_TESTED);
9386         poplocalvars(0);
9387  funcdone:
9388         INT_OFF;
9389         funcnest--;
9390         freefunc(func);
9391         freeparam(&shellparam);
9392         shellparam = saveparam;
9393         exception_handler = savehandler;
9394         INT_ON;
9395         evalskip &= ~SKIPFUNC;
9396         return e;
9397 }
9398
9399 /*
9400  * Make a variable a local variable.  When a variable is made local, it's
9401  * value and flags are saved in a localvar structure.  The saved values
9402  * will be restored when the shell function returns.  We handle the name
9403  * "-" as a special case: it makes changes to "set +-options" local
9404  * (options will be restored on return from the function).
9405  */
9406 static void
9407 mklocal(char *name)
9408 {
9409         struct localvar *lvp;
9410         struct var **vpp;
9411         struct var *vp;
9412         char *eq = strchr(name, '=');
9413
9414         INT_OFF;
9415         /* Cater for duplicate "local". Examples:
9416          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9417          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9418          */
9419         lvp = localvar_stack->lv;
9420         while (lvp) {
9421                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9422                         if (eq)
9423                                 setvareq(name, 0);
9424                         /* else:
9425                          * it's a duplicate "local VAR" declaration, do nothing
9426                          */
9427                         goto ret;
9428                 }
9429                 lvp = lvp->next;
9430         }
9431
9432         lvp = ckzalloc(sizeof(*lvp));
9433         if (LONE_DASH(name)) {
9434                 char *p;
9435                 p = ckmalloc(sizeof(optlist));
9436                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9437                 vp = NULL;
9438         } else {
9439                 vpp = hashvar(name);
9440                 vp = *findvar(vpp, name);
9441                 if (vp == NULL) {
9442                         /* variable did not exist yet */
9443                         if (eq)
9444                                 vp = setvareq(name, VSTRFIXED);
9445                         else
9446                                 vp = setvar(name, NULL, VSTRFIXED);
9447                         lvp->flags = VUNSET;
9448                 } else {
9449                         lvp->text = vp->var_text;
9450                         lvp->flags = vp->flags;
9451                         /* make sure neither "struct var" nor string gets freed
9452                          * during (un)setting:
9453                          */
9454                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9455                         if (eq)
9456                                 setvareq(name, 0);
9457                         else
9458                                 /* "local VAR" unsets VAR: */
9459                                 setvar0(name, NULL);
9460                 }
9461         }
9462         lvp->vp = vp;
9463         lvp->next = localvar_stack->lv;
9464         localvar_stack->lv = lvp;
9465  ret:
9466         INT_ON;
9467 }
9468
9469 /*
9470  * The "local" command.
9471  */
9472 static int FAST_FUNC
9473 localcmd(int argc UNUSED_PARAM, char **argv)
9474 {
9475         char *name;
9476
9477         if (!localvar_stack)
9478                 ash_msg_and_raise_error("not in a function");
9479
9480         argv = argptr;
9481         while ((name = *argv++) != NULL) {
9482                 mklocal(name);
9483         }
9484         return 0;
9485 }
9486
9487 static int FAST_FUNC
9488 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9489 {
9490         return 1;
9491 }
9492
9493 static int FAST_FUNC
9494 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9495 {
9496         return 0;
9497 }
9498
9499 static int FAST_FUNC
9500 execcmd(int argc UNUSED_PARAM, char **argv)
9501 {
9502         optionarg = NULL;
9503         while (nextopt("a:") != '\0')
9504                 /* nextopt() sets optionarg to "-a ARGV0" */;
9505
9506         argv = argptr;
9507         if (argv[0]) {
9508                 char *prog;
9509
9510                 iflag = 0;              /* exit on error */
9511                 mflag = 0;
9512                 optschanged();
9513                 /* We should set up signals for "exec CMD"
9514                  * the same way as for "CMD" without "exec".
9515                  * But optschanged->setinteractive->setsignal
9516                  * still thought we are a root shell. Therefore, for example,
9517                  * SIGQUIT is still set to IGN. Fix it:
9518                  */
9519                 shlvl++;
9520                 setsignal(SIGQUIT);
9521                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9522                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9523                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9524
9525                 prog = argv[0];
9526                 if (optionarg)
9527                         argv[0] = optionarg;
9528                 shellexec(prog, argv, pathval(), 0);
9529                 /* NOTREACHED */
9530         }
9531         return 0;
9532 }
9533
9534 /*
9535  * The return command.
9536  */
9537 static int FAST_FUNC
9538 returncmd(int argc UNUSED_PARAM, char **argv)
9539 {
9540         /*
9541          * If called outside a function, do what ksh does;
9542          * skip the rest of the file.
9543          */
9544         evalskip = SKIPFUNC;
9545         return argv[1] ? number(argv[1]) : exitstatus;
9546 }
9547
9548 /* Forward declarations for builtintab[] */
9549 static int breakcmd(int, char **) FAST_FUNC;
9550 static int dotcmd(int, char **) FAST_FUNC;
9551 static int evalcmd(int, char **, int) FAST_FUNC;
9552 static int exitcmd(int, char **) FAST_FUNC;
9553 static int exportcmd(int, char **) FAST_FUNC;
9554 #if ENABLE_ASH_GETOPTS
9555 static int getoptscmd(int, char **) FAST_FUNC;
9556 #endif
9557 #if ENABLE_ASH_HELP
9558 static int helpcmd(int, char **) FAST_FUNC;
9559 #endif
9560 #if MAX_HISTORY
9561 static int historycmd(int, char **) FAST_FUNC;
9562 #endif
9563 #if ENABLE_FEATURE_SH_MATH
9564 static int letcmd(int, char **) FAST_FUNC;
9565 #endif
9566 static int readcmd(int, char **) FAST_FUNC;
9567 static int setcmd(int, char **) FAST_FUNC;
9568 static int shiftcmd(int, char **) FAST_FUNC;
9569 static int timescmd(int, char **) FAST_FUNC;
9570 static int trapcmd(int, char **) FAST_FUNC;
9571 static int umaskcmd(int, char **) FAST_FUNC;
9572 static int unsetcmd(int, char **) FAST_FUNC;
9573 static int ulimitcmd(int, char **) FAST_FUNC;
9574
9575 #define BUILTIN_NOSPEC          "0"
9576 #define BUILTIN_SPECIAL         "1"
9577 #define BUILTIN_REGULAR         "2"
9578 #define BUILTIN_SPEC_REG        "3"
9579 #define BUILTIN_ASSIGN          "4"
9580 #define BUILTIN_SPEC_ASSG       "5"
9581 #define BUILTIN_REG_ASSG        "6"
9582 #define BUILTIN_SPEC_REG_ASSG   "7"
9583
9584 /* Stubs for calling non-FAST_FUNC's */
9585 #if ENABLE_ASH_ECHO
9586 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9587 #endif
9588 #if ENABLE_ASH_PRINTF
9589 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9590 #endif
9591 #if ENABLE_ASH_TEST || BASH_TEST2
9592 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9593 #endif
9594
9595 /* Keep these in proper order since it is searched via bsearch() */
9596 static const struct builtincmd builtintab[] = {
9597         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9598         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9599 #if ENABLE_ASH_TEST
9600         { BUILTIN_REGULAR       "["       , testcmd    },
9601 #endif
9602 #if BASH_TEST2
9603         { BUILTIN_REGULAR       "[["      , testcmd    },
9604 #endif
9605 #if ENABLE_ASH_ALIAS
9606         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9607 #endif
9608 #if JOBS
9609         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9610 #endif
9611         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9612         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9613         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9614 #if ENABLE_ASH_CMDCMD
9615         { BUILTIN_REGULAR       "command" , commandcmd },
9616 #endif
9617         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9618 #if ENABLE_ASH_ECHO
9619         { BUILTIN_REGULAR       "echo"    , echocmd    },
9620 #endif
9621         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9622         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9623         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9624         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9625         { BUILTIN_REGULAR       "false"   , falsecmd   },
9626 #if JOBS
9627         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9628 #endif
9629 #if ENABLE_ASH_GETOPTS
9630         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9631 #endif
9632         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9633 #if ENABLE_ASH_HELP
9634         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9635 #endif
9636 #if MAX_HISTORY
9637         { BUILTIN_NOSPEC        "history" , historycmd },
9638 #endif
9639 #if JOBS
9640         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9641         { BUILTIN_REGULAR       "kill"    , killcmd    },
9642 #endif
9643 #if ENABLE_FEATURE_SH_MATH
9644         { BUILTIN_NOSPEC        "let"     , letcmd     },
9645 #endif
9646         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9647 #if ENABLE_ASH_PRINTF
9648         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9649 #endif
9650         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9651         { BUILTIN_REGULAR       "read"    , readcmd    },
9652         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9653         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9654         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9655         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9656 #if BASH_SOURCE
9657         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9658 #endif
9659 #if ENABLE_ASH_TEST
9660         { BUILTIN_REGULAR       "test"    , testcmd    },
9661 #endif
9662         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9663         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9664         { BUILTIN_REGULAR       "true"    , truecmd    },
9665         { BUILTIN_NOSPEC        "type"    , typecmd    },
9666         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9667         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9668 #if ENABLE_ASH_ALIAS
9669         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9670 #endif
9671         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9672         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9673 };
9674
9675 /* Should match the above table! */
9676 #define COMMANDCMD (builtintab + \
9677         /* . : */       2 + \
9678         /* [ */         1 * ENABLE_ASH_TEST + \
9679         /* [[ */        1 * BASH_TEST2 + \
9680         /* alias */     1 * ENABLE_ASH_ALIAS + \
9681         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9682         /* break cd cddir  */   3)
9683 #define EVALCMD (COMMANDCMD + \
9684         /* command */   1 * ENABLE_ASH_CMDCMD + \
9685         /* continue */  1 + \
9686         /* echo */      1 * ENABLE_ASH_ECHO + \
9687         0)
9688 #define EXECCMD (EVALCMD + \
9689         /* eval */      1)
9690
9691 /*
9692  * Search the table of builtin commands.
9693  */
9694 static int
9695 pstrcmp1(const void *a, const void *b)
9696 {
9697         return strcmp((char*)a, *(char**)b + 1);
9698 }
9699 static struct builtincmd *
9700 find_builtin(const char *name)
9701 {
9702         struct builtincmd *bp;
9703
9704         bp = bsearch(
9705                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9706                 pstrcmp1
9707         );
9708         return bp;
9709 }
9710
9711 /*
9712  * Execute a simple command.
9713  */
9714 static int
9715 isassignment(const char *p)
9716 {
9717         const char *q = endofname(p);
9718         if (p == q)
9719                 return 0;
9720         return *q == '=';
9721 }
9722 static int FAST_FUNC
9723 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9724 {
9725         /* Preserve exitstatus of a previous possible redirection
9726          * as POSIX mandates */
9727         return back_exitstatus;
9728 }
9729 static int
9730 evalcommand(union node *cmd, int flags)
9731 {
9732         static const struct builtincmd null_bltin = {
9733                 "\0\0", bltincmd /* why three NULs? */
9734         };
9735         struct localvar_list *localvar_stop;
9736         struct redirtab *redir_stop;
9737         struct stackmark smark;
9738         union node *argp;
9739         struct arglist arglist;
9740         struct arglist varlist;
9741         char **argv;
9742         int argc;
9743         const struct strlist *sp;
9744         struct cmdentry cmdentry;
9745         struct job *jp;
9746         char *lastarg;
9747         const char *path;
9748         int spclbltin;
9749         int status;
9750         char **nargv;
9751         smallint cmd_is_exec;
9752
9753         /* First expand the arguments. */
9754         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9755         setstackmark(&smark);
9756         localvar_stop = pushlocalvars();
9757         back_exitstatus = 0;
9758
9759         cmdentry.cmdtype = CMDBUILTIN;
9760         cmdentry.u.cmd = &null_bltin;
9761         varlist.lastp = &varlist.list;
9762         *varlist.lastp = NULL;
9763         arglist.lastp = &arglist.list;
9764         *arglist.lastp = NULL;
9765
9766         argc = 0;
9767         if (cmd->ncmd.args) {
9768                 struct builtincmd *bcmd;
9769                 smallint pseudovarflag;
9770
9771                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9772                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9773
9774                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9775                         struct strlist **spp;
9776
9777                         spp = arglist.lastp;
9778                         if (pseudovarflag && isassignment(argp->narg.text))
9779                                 expandarg(argp, &arglist, EXP_VARTILDE);
9780                         else
9781                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9782
9783                         for (sp = *spp; sp; sp = sp->next)
9784                                 argc++;
9785                 }
9786         }
9787
9788         /* Reserve one extra spot at the front for shellexec. */
9789         nargv = stalloc(sizeof(char *) * (argc + 2));
9790         argv = ++nargv;
9791         for (sp = arglist.list; sp; sp = sp->next) {
9792                 TRACE(("evalcommand arg: %s\n", sp->text));
9793                 *nargv++ = sp->text;
9794         }
9795         *nargv = NULL;
9796
9797         lastarg = NULL;
9798         if (iflag && funcnest == 0 && argc > 0)
9799                 lastarg = nargv[-1];
9800
9801         expredir(cmd->ncmd.redirect);
9802         redir_stop = pushredir(cmd->ncmd.redirect);
9803         preverrout_fd = 2;
9804         if (BASH_XTRACEFD && xflag) {
9805                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9806                  * we do not emulate this. We only use its value.
9807                  */
9808                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9809                 if (xtracefd && is_number(xtracefd))
9810                         preverrout_fd = atoi(xtracefd);
9811
9812         }
9813         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9814
9815         path = vpath.var_text;
9816         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9817                 struct strlist **spp;
9818                 char *p;
9819
9820                 spp = varlist.lastp;
9821                 expandarg(argp, &varlist, EXP_VARTILDE);
9822
9823                 mklocal((*spp)->text);
9824
9825                 /*
9826                  * Modify the command lookup path, if a PATH= assignment
9827                  * is present
9828                  */
9829                 p = (*spp)->text;
9830                 if (varcmp(p, path) == 0)
9831                         path = p;
9832         }
9833
9834         /* Print the command if xflag is set. */
9835         if (xflag) {
9836                 const char *pfx = "";
9837
9838                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9839
9840                 sp = varlist.list;
9841                 while (sp) {
9842                         char *varval = sp->text;
9843                         char *eq = strchrnul(varval, '=');
9844                         if (*eq)
9845                                 eq++;
9846                         fdprintf(preverrout_fd, "%s%.*s%s",
9847                                 pfx,
9848                                 (int)(eq - varval), varval,
9849                                 maybe_single_quote(eq)
9850                         );
9851                         sp = sp->next;
9852                         pfx = " ";
9853                 }
9854
9855                 sp = arglist.list;
9856                 while (sp) {
9857                         fdprintf(preverrout_fd, "%s%s",
9858                                 pfx,
9859                                 /* always quote if matches reserved word: */
9860                                 findkwd(sp->text)
9861                                 ? single_quote(sp->text)
9862                                 : maybe_single_quote(sp->text)
9863                         );
9864                         sp = sp->next;
9865                         pfx = " ";
9866                 }
9867                 safe_write(preverrout_fd, "\n", 1);
9868         }
9869
9870         cmd_is_exec = 0;
9871         spclbltin = -1;
9872
9873         /* Now locate the command. */
9874         if (argc) {
9875                 int cmd_flag = DO_ERR;
9876 #if ENABLE_ASH_CMDCMD
9877                 const char *oldpath = path + 5;
9878 #endif
9879                 path += 5;
9880                 for (;;) {
9881                         find_command(argv[0], &cmdentry, cmd_flag, path);
9882                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9883                                 flush_stdout_stderr();
9884                                 status = 127;
9885                                 goto bail;
9886                         }
9887
9888                         /* implement bltin and command here */
9889                         if (cmdentry.cmdtype != CMDBUILTIN)
9890                                 break;
9891                         if (spclbltin < 0)
9892                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9893                         if (cmdentry.u.cmd == EXECCMD)
9894                                 cmd_is_exec = 1;
9895 #if ENABLE_ASH_CMDCMD
9896                         if (cmdentry.u.cmd == COMMANDCMD) {
9897                                 path = oldpath;
9898                                 nargv = parse_command_args(argv, &path);
9899                                 if (!nargv)
9900                                         break;
9901                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9902                                  * nargv => "PROG". path is updated if -p.
9903                                  */
9904                                 argc -= nargv - argv;
9905                                 argv = nargv;
9906                                 cmd_flag |= DO_NOFUNC;
9907                         } else
9908 #endif
9909                                 break;
9910                 }
9911         }
9912
9913         if (status) {
9914  bail:
9915                 exitstatus = status;
9916
9917                 /* We have a redirection error. */
9918                 if (spclbltin > 0)
9919                         raise_exception(EXERROR);
9920
9921                 goto out;
9922         }
9923
9924         /* Execute the command. */
9925         switch (cmdentry.cmdtype) {
9926         default: {
9927
9928 #if ENABLE_FEATURE_SH_NOFORK
9929 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9930  *     around run_nofork_applet() call.
9931  * (2) Should this check also be done in forkshell()?
9932  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9933  */
9934                 /* find_command() encodes applet_no as (-2 - applet_no) */
9935                 int applet_no = (- cmdentry.u.index - 2);
9936                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9937                         listsetvar(varlist.list, VEXPORT|VSTACK);
9938                         /*
9939                          * Run <applet>_main().
9940                          * Signals (^C) can't interrupt here.
9941                          * Otherwise we can mangle stdio or malloc internal state.
9942                          * This makes applets which can run for a long time
9943                          * and/or wait for user input ineligible for NOFORK:
9944                          * for example, "yes" or "rm" (rm -i waits for input).
9945                          */
9946                         INT_OFF;
9947                         status = run_nofork_applet(applet_no, argv);
9948                         /*
9949                          * Try enabling NOFORK for "yes" applet.
9950                          * ^C _will_ stop it (write returns EINTR),
9951                          * but this causes stdout FILE to be stuck
9952                          * and needing clearerr(). What if other applets
9953                          * also can get EINTRs? Do we need to switch
9954                          * our signals to SA_RESTART?
9955                          */
9956                         /*clearerr(stdout);*/
9957                         INT_ON;
9958                         break;
9959                 }
9960 #endif
9961                 /* Can we avoid forking? For example, very last command
9962                  * in a script or a subshell does not need forking,
9963                  * we can just exec it.
9964                  */
9965                 if (!(flags & EV_EXIT) || may_have_traps) {
9966                         /* No, forking off a child is necessary */
9967                         INT_OFF;
9968                         get_tty_state();
9969                         jp = makejob(/*cmd,*/ 1);
9970                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9971                                 /* parent */
9972                                 status = waitforjob(jp);
9973                                 INT_ON;
9974                                 TRACE(("forked child exited with %d\n", status));
9975                                 break;
9976                         }
9977                         /* child */
9978                         FORCE_INT_ON;
9979                         /* fall through to exec'ing external program */
9980                 }
9981                 listsetvar(varlist.list, VEXPORT|VSTACK);
9982                 shellexec(argv[0], argv, path, cmdentry.u.index);
9983                 /* NOTREACHED */
9984         } /* default */
9985         case CMDBUILTIN:
9986                 if (spclbltin > 0 || argc == 0) {
9987                         poplocalvars(1);
9988                         if (cmd_is_exec && argc > 1)
9989                                 listsetvar(varlist.list, VEXPORT);
9990                 }
9991
9992                 /* Tight loop with builtins only:
9993                  * "while kill -0 $child; do true; done"
9994                  * will never exit even if $child died, unless we do this
9995                  * to reap the zombie and make kill detect that it's gone: */
9996                 dowait(DOWAIT_NONBLOCK, NULL);
9997
9998                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9999                         if (exception_type == EXERROR && spclbltin <= 0) {
10000                                 FORCE_INT_ON;
10001                                 goto readstatus;
10002                         }
10003  raise:
10004                         longjmp(exception_handler->loc, 1);
10005                 }
10006                 goto readstatus;
10007
10008         case CMDFUNCTION:
10009                 poplocalvars(1);
10010                 /* See above for the rationale */
10011                 dowait(DOWAIT_NONBLOCK, NULL);
10012                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10013                         goto raise;
10014  readstatus:
10015                 status = exitstatus;
10016                 break;
10017         } /* switch */
10018
10019  out:
10020         if (cmd->ncmd.redirect)
10021                 popredir(/*drop:*/ cmd_is_exec);
10022         unwindredir(redir_stop);
10023         unwindlocalvars(localvar_stop);
10024         if (lastarg) {
10025                 /* dsl: I think this is intended to be used to support
10026                  * '_' in 'vi' command mode during line editing...
10027                  * However I implemented that within libedit itself.
10028                  */
10029                 setvar0("_", lastarg);
10030         }
10031         popstackmark(&smark);
10032
10033         return status;
10034 }
10035
10036 static int
10037 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10038 {
10039         char *volatile savecmdname;
10040         struct jmploc *volatile savehandler;
10041         struct jmploc jmploc;
10042         int status;
10043         int i;
10044
10045         savecmdname = commandname;
10046         savehandler = exception_handler;
10047         i = setjmp(jmploc.loc);
10048         if (i)
10049                 goto cmddone;
10050         exception_handler = &jmploc;
10051         commandname = argv[0];
10052         argptr = argv + 1;
10053         optptr = NULL;                  /* initialize nextopt */
10054         if (cmd == EVALCMD)
10055                 status = evalcmd(argc, argv, flags);
10056         else
10057                 status = (*cmd->builtin)(argc, argv);
10058         flush_stdout_stderr();
10059         status |= ferror(stdout);
10060         exitstatus = status;
10061  cmddone:
10062         clearerr(stdout);
10063         commandname = savecmdname;
10064         exception_handler = savehandler;
10065
10066         return i;
10067 }
10068
10069 static int
10070 goodname(const char *p)
10071 {
10072         return endofname(p)[0] == '\0';
10073 }
10074
10075
10076 /*
10077  * Search for a command.  This is called before we fork so that the
10078  * location of the command will be available in the parent as well as
10079  * the child.  The check for "goodname" is an overly conservative
10080  * check that the name will not be subject to expansion.
10081  */
10082 static void
10083 prehash(union node *n)
10084 {
10085         struct cmdentry entry;
10086
10087         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10088                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10089 }
10090
10091
10092 /* ============ Builtin commands
10093  *
10094  * Builtin commands whose functions are closely tied to evaluation
10095  * are implemented here.
10096  */
10097
10098 /*
10099  * Handle break and continue commands.  Break, continue, and return are
10100  * all handled by setting the evalskip flag.  The evaluation routines
10101  * above all check this flag, and if it is set they start skipping
10102  * commands rather than executing them.  The variable skipcount is
10103  * the number of loops to break/continue, or the number of function
10104  * levels to return.  (The latter is always 1.)  It should probably
10105  * be an error to break out of more loops than exist, but it isn't
10106  * in the standard shell so we don't make it one here.
10107  */
10108 static int FAST_FUNC
10109 breakcmd(int argc UNUSED_PARAM, char **argv)
10110 {
10111         int n = argv[1] ? number(argv[1]) : 1;
10112
10113         if (n <= 0)
10114                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10115         if (n > loopnest)
10116                 n = loopnest;
10117         if (n > 0) {
10118                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10119                 skipcount = n;
10120         }
10121         return 0;
10122 }
10123
10124
10125 /*
10126  * This implements the input routines used by the parser.
10127  */
10128
10129 enum {
10130         INPUT_PUSH_FILE = 1,
10131         INPUT_NOFILE_OK = 2,
10132 };
10133
10134 static smallint checkkwd;
10135 /* values of checkkwd variable */
10136 #define CHKALIAS        0x1
10137 #define CHKKWD          0x2
10138 #define CHKNL           0x4
10139 #define CHKEOFMARK      0x8
10140
10141 /*
10142  * Push a string back onto the input at this current parsefile level.
10143  * We handle aliases this way.
10144  */
10145 #if !ENABLE_ASH_ALIAS
10146 #define pushstring(s, ap) pushstring(s)
10147 #endif
10148 static void
10149 pushstring(char *s, struct alias *ap)
10150 {
10151         struct strpush *sp;
10152         int len;
10153
10154         len = strlen(s);
10155         INT_OFF;
10156         if (g_parsefile->strpush) {
10157                 sp = ckzalloc(sizeof(*sp));
10158                 sp->prev = g_parsefile->strpush;
10159         } else {
10160                 sp = &(g_parsefile->basestrpush);
10161         }
10162         g_parsefile->strpush = sp;
10163         sp->prev_string = g_parsefile->next_to_pgetc;
10164         sp->prev_left_in_line = g_parsefile->left_in_line;
10165         sp->unget = g_parsefile->unget;
10166         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10167 #if ENABLE_ASH_ALIAS
10168         sp->ap = ap;
10169         if (ap) {
10170                 ap->flag |= ALIASINUSE;
10171                 sp->string = s;
10172         }
10173 #endif
10174         g_parsefile->next_to_pgetc = s;
10175         g_parsefile->left_in_line = len;
10176         g_parsefile->unget = 0;
10177         INT_ON;
10178 }
10179
10180 static void
10181 popstring(void)
10182 {
10183         struct strpush *sp = g_parsefile->strpush;
10184
10185         INT_OFF;
10186 #if ENABLE_ASH_ALIAS
10187         if (sp->ap) {
10188                 if (g_parsefile->next_to_pgetc[-1] == ' '
10189                  || g_parsefile->next_to_pgetc[-1] == '\t'
10190                 ) {
10191                         checkkwd |= CHKALIAS;
10192                 }
10193                 if (sp->string != sp->ap->val) {
10194                         free(sp->string);
10195                 }
10196                 sp->ap->flag &= ~ALIASINUSE;
10197                 if (sp->ap->flag & ALIASDEAD) {
10198                         unalias(sp->ap->name);
10199                 }
10200         }
10201 #endif
10202         g_parsefile->next_to_pgetc = sp->prev_string;
10203         g_parsefile->left_in_line = sp->prev_left_in_line;
10204         g_parsefile->unget = sp->unget;
10205         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10206         g_parsefile->strpush = sp->prev;
10207         if (sp != &(g_parsefile->basestrpush))
10208                 free(sp);
10209         INT_ON;
10210 }
10211
10212 static int
10213 preadfd(void)
10214 {
10215         int nr;
10216         char *buf = g_parsefile->buf;
10217
10218         g_parsefile->next_to_pgetc = buf;
10219 #if ENABLE_FEATURE_EDITING
10220  retry:
10221         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10222                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10223         else {
10224 # if ENABLE_ASH_IDLE_TIMEOUT
10225                 int timeout = -1;
10226                 if (iflag) {
10227                         const char *tmout_var = lookupvar("TMOUT");
10228                         if (tmout_var) {
10229                                 timeout = atoi(tmout_var) * 1000;
10230                                 if (timeout <= 0)
10231                                         timeout = -1;
10232                         }
10233                 }
10234                 line_input_state->timeout = timeout;
10235 # endif
10236 # if ENABLE_FEATURE_TAB_COMPLETION
10237                 line_input_state->path_lookup = pathval();
10238 # endif
10239                 reinit_unicode_for_ash();
10240                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10241                 if (nr == 0) {
10242                         /* ^C pressed, "convert" to SIGINT */
10243                         write(STDOUT_FILENO, "^C", 2);
10244                         if (trap[SIGINT]) {
10245                                 buf[0] = '\n';
10246                                 buf[1] = '\0';
10247                                 raise(SIGINT);
10248                                 return 1;
10249                         }
10250                         exitstatus = 128 + SIGINT;
10251                         bb_putchar('\n');
10252                         goto retry;
10253                 }
10254                 if (nr < 0) {
10255                         if (errno == 0) {
10256                                 /* Ctrl+D pressed */
10257                                 nr = 0;
10258                         }
10259 # if ENABLE_ASH_IDLE_TIMEOUT
10260                         else if (errno == EAGAIN && timeout > 0) {
10261                                 puts("\007timed out waiting for input: auto-logout");
10262                                 exitshell();
10263                         }
10264 # endif
10265                 }
10266         }
10267 #else
10268         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10269 #endif
10270
10271 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10272         if (nr < 0) {
10273                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10274                         int flags = fcntl(0, F_GETFL);
10275                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10276                                 flags &= ~O_NONBLOCK;
10277                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10278                                         out2str("sh: turning off NDELAY mode\n");
10279                                         goto retry;
10280                                 }
10281                         }
10282                 }
10283         }
10284 #endif
10285         return nr;
10286 }
10287
10288 /*
10289  * Refill the input buffer and return the next input character:
10290  *
10291  * 1) If a string was pushed back on the input, pop it;
10292  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10293  *    or we are reading from a string so we can't refill the buffer,
10294  *    return EOF.
10295  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10296  * 4) Process input up to the next newline, deleting nul characters.
10297  */
10298 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10299 #define pgetc_debug(...) ((void)0)
10300 static int pgetc(void);
10301 static int
10302 preadbuffer(void)
10303 {
10304         char *q;
10305         int more;
10306
10307         if (g_parsefile->strpush) {
10308 #if ENABLE_ASH_ALIAS
10309                 if (g_parsefile->left_in_line == -1
10310                  && g_parsefile->strpush->ap
10311                  && g_parsefile->next_to_pgetc[-1] != ' '
10312                  && g_parsefile->next_to_pgetc[-1] != '\t'
10313                 ) {
10314                         pgetc_debug("preadbuffer PEOA");
10315                         return PEOA;
10316                 }
10317 #endif
10318                 popstring();
10319                 return pgetc();
10320         }
10321         /* on both branches above g_parsefile->left_in_line < 0.
10322          * "pgetc" needs refilling.
10323          */
10324
10325         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10326          * pungetc() may increment it a few times.
10327          * Assuming it won't increment it to less than -90.
10328          */
10329         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10330                 pgetc_debug("preadbuffer PEOF1");
10331                 /* even in failure keep left_in_line and next_to_pgetc
10332                  * in lock step, for correct multi-layer pungetc.
10333                  * left_in_line was decremented before preadbuffer(),
10334                  * must inc next_to_pgetc: */
10335                 g_parsefile->next_to_pgetc++;
10336                 return PEOF;
10337         }
10338
10339         more = g_parsefile->left_in_buffer;
10340         if (more <= 0) {
10341                 flush_stdout_stderr();
10342  again:
10343                 more = preadfd();
10344                 if (more <= 0) {
10345                         /* don't try reading again */
10346                         g_parsefile->left_in_line = -99;
10347                         pgetc_debug("preadbuffer PEOF2");
10348                         g_parsefile->next_to_pgetc++;
10349                         return PEOF;
10350                 }
10351         }
10352
10353         /* Find out where's the end of line.
10354          * Set g_parsefile->left_in_line
10355          * and g_parsefile->left_in_buffer acordingly.
10356          * NUL chars are deleted.
10357          */
10358         q = g_parsefile->next_to_pgetc;
10359         for (;;) {
10360                 char c;
10361
10362                 more--;
10363
10364                 c = *q;
10365                 if (c == '\0') {
10366                         memmove(q, q + 1, more);
10367                 } else {
10368                         q++;
10369                         if (c == '\n') {
10370                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10371                                 break;
10372                         }
10373                 }
10374
10375                 if (more <= 0) {
10376                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10377                         if (g_parsefile->left_in_line < 0)
10378                                 goto again;
10379                         break;
10380                 }
10381         }
10382         g_parsefile->left_in_buffer = more;
10383
10384         if (vflag) {
10385                 char save = *q;
10386                 *q = '\0';
10387                 out2str(g_parsefile->next_to_pgetc);
10388                 *q = save;
10389         }
10390
10391         pgetc_debug("preadbuffer at %d:%p'%s'",
10392                         g_parsefile->left_in_line,
10393                         g_parsefile->next_to_pgetc,
10394                         g_parsefile->next_to_pgetc);
10395         return (unsigned char)*g_parsefile->next_to_pgetc++;
10396 }
10397
10398 static void
10399 nlprompt(void)
10400 {
10401         g_parsefile->linno++;
10402         setprompt_if(doprompt, 2);
10403 }
10404 static void
10405 nlnoprompt(void)
10406 {
10407         g_parsefile->linno++;
10408         needprompt = doprompt;
10409 }
10410
10411 static int
10412 pgetc(void)
10413 {
10414         int c;
10415
10416         pgetc_debug("pgetc at %d:%p'%s'",
10417                         g_parsefile->left_in_line,
10418                         g_parsefile->next_to_pgetc,
10419                         g_parsefile->next_to_pgetc);
10420         if (g_parsefile->unget)
10421                 return g_parsefile->lastc[--g_parsefile->unget];
10422
10423         if (--g_parsefile->left_in_line >= 0)
10424                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10425         else
10426                 c = preadbuffer();
10427
10428         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10429         g_parsefile->lastc[0] = c;
10430
10431         return c;
10432 }
10433
10434 #if ENABLE_ASH_ALIAS
10435 static int
10436 pgetc_without_PEOA(void)
10437 {
10438         int c;
10439         do {
10440                 pgetc_debug("pgetc at %d:%p'%s'",
10441                                 g_parsefile->left_in_line,
10442                                 g_parsefile->next_to_pgetc,
10443                                 g_parsefile->next_to_pgetc);
10444                 c = pgetc();
10445         } while (c == PEOA);
10446         return c;
10447 }
10448 #else
10449 # define pgetc_without_PEOA() pgetc()
10450 #endif
10451
10452 /*
10453  * Undo a call to pgetc.  Only two characters may be pushed back.
10454  * PEOF may be pushed back.
10455  */
10456 static void
10457 pungetc(void)
10458 {
10459         g_parsefile->unget++;
10460 }
10461
10462 /* This one eats backslash+newline */
10463 static int
10464 pgetc_eatbnl(void)
10465 {
10466         int c;
10467
10468         while ((c = pgetc()) == '\\') {
10469                 if (pgetc() != '\n') {
10470                         pungetc();
10471                         break;
10472                 }
10473
10474                 nlprompt();
10475         }
10476
10477         return c;
10478 }
10479
10480 /*
10481  * To handle the "." command, a stack of input files is used.  Pushfile
10482  * adds a new entry to the stack and popfile restores the previous level.
10483  */
10484 static void
10485 pushfile(void)
10486 {
10487         struct parsefile *pf;
10488
10489         pf = ckzalloc(sizeof(*pf));
10490         pf->prev = g_parsefile;
10491         pf->pf_fd = -1;
10492         /*pf->strpush = NULL; - ckzalloc did it */
10493         /*pf->basestrpush.prev = NULL;*/
10494         /*pf->unget = 0;*/
10495         g_parsefile = pf;
10496 }
10497
10498 static void
10499 popfile(void)
10500 {
10501         struct parsefile *pf = g_parsefile;
10502
10503         if (pf == &basepf)
10504                 return;
10505
10506         INT_OFF;
10507         if (pf->pf_fd >= 0)
10508                 close(pf->pf_fd);
10509         free(pf->buf);
10510         while (pf->strpush)
10511                 popstring();
10512         g_parsefile = pf->prev;
10513         free(pf);
10514         INT_ON;
10515 }
10516
10517 /*
10518  * Return to top level.
10519  */
10520 static void
10521 popallfiles(void)
10522 {
10523         while (g_parsefile != &basepf)
10524                 popfile();
10525 }
10526
10527 /*
10528  * Close the file(s) that the shell is reading commands from.  Called
10529  * after a fork is done.
10530  */
10531 static void
10532 closescript(void)
10533 {
10534         popallfiles();
10535         if (g_parsefile->pf_fd > 0) {
10536                 close(g_parsefile->pf_fd);
10537                 g_parsefile->pf_fd = 0;
10538         }
10539 }
10540
10541 /*
10542  * Like setinputfile, but takes an open file descriptor.  Call this with
10543  * interrupts off.
10544  */
10545 static void
10546 setinputfd(int fd, int push)
10547 {
10548         if (push) {
10549                 pushfile();
10550                 g_parsefile->buf = NULL;
10551         }
10552         g_parsefile->pf_fd = fd;
10553         if (g_parsefile->buf == NULL)
10554                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10555         g_parsefile->left_in_buffer = 0;
10556         g_parsefile->left_in_line = 0;
10557         g_parsefile->linno = 1;
10558 }
10559
10560 /*
10561  * Set the input to take input from a file.  If push is set, push the
10562  * old input onto the stack first.
10563  */
10564 static int
10565 setinputfile(const char *fname, int flags)
10566 {
10567         int fd;
10568
10569         INT_OFF;
10570         fd = open(fname, O_RDONLY);
10571         if (fd < 0) {
10572                 if (flags & INPUT_NOFILE_OK)
10573                         goto out;
10574                 exitstatus = 127;
10575                 ash_msg_and_raise_error("can't open '%s'", fname);
10576         }
10577         if (fd < 10)
10578                 fd = savefd(fd);
10579         else
10580                 close_on_exec_on(fd);
10581         setinputfd(fd, flags & INPUT_PUSH_FILE);
10582  out:
10583         INT_ON;
10584         return fd;
10585 }
10586
10587 /*
10588  * Like setinputfile, but takes input from a string.
10589  */
10590 static void
10591 setinputstring(char *string)
10592 {
10593         INT_OFF;
10594         pushfile();
10595         g_parsefile->next_to_pgetc = string;
10596         g_parsefile->left_in_line = strlen(string);
10597         g_parsefile->buf = NULL;
10598         g_parsefile->linno = 1;
10599         INT_ON;
10600 }
10601
10602
10603 /*
10604  * Routines to check for mail.
10605  */
10606
10607 #if ENABLE_ASH_MAIL
10608
10609 /* Hash of mtimes of mailboxes */
10610 static unsigned mailtime_hash;
10611 /* Set if MAIL or MAILPATH is changed. */
10612 static smallint mail_var_path_changed;
10613
10614 /*
10615  * Print appropriate message(s) if mail has arrived.
10616  * If mail_var_path_changed is set,
10617  * then the value of MAIL has mail_var_path_changed,
10618  * so we just update the values.
10619  */
10620 static void
10621 chkmail(void)
10622 {
10623         const char *mpath;
10624         char *p;
10625         char *q;
10626         unsigned new_hash;
10627         struct stackmark smark;
10628         struct stat statb;
10629
10630         setstackmark(&smark);
10631         mpath = mpathset() ? mpathval() : mailval();
10632         new_hash = 0;
10633         for (;;) {
10634                 p = path_advance(&mpath, nullstr);
10635                 if (p == NULL)
10636                         break;
10637                 if (*p == '\0')
10638                         continue;
10639                 for (q = p; *q; q++)
10640                         continue;
10641 #if DEBUG
10642                 if (q[-1] != '/')
10643                         abort();
10644 #endif
10645                 q[-1] = '\0';                   /* delete trailing '/' */
10646                 if (stat(p, &statb) < 0) {
10647                         continue;
10648                 }
10649                 /* Very simplistic "hash": just a sum of all mtimes */
10650                 new_hash += (unsigned)statb.st_mtime;
10651         }
10652         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10653                 if (mailtime_hash != 0)
10654                         out2str("you have mail\n");
10655                 mailtime_hash = new_hash;
10656         }
10657         mail_var_path_changed = 0;
10658         popstackmark(&smark);
10659 }
10660
10661 static void FAST_FUNC
10662 changemail(const char *val UNUSED_PARAM)
10663 {
10664         mail_var_path_changed = 1;
10665 }
10666
10667 #endif /* ASH_MAIL */
10668
10669
10670 /* ============ ??? */
10671
10672 /*
10673  * Set the shell parameters.
10674  */
10675 static void
10676 setparam(char **argv)
10677 {
10678         char **newparam;
10679         char **ap;
10680         int nparam;
10681
10682         for (nparam = 0; argv[nparam]; nparam++)
10683                 continue;
10684         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10685         while (*argv) {
10686                 *ap++ = ckstrdup(*argv++);
10687         }
10688         *ap = NULL;
10689         freeparam(&shellparam);
10690         shellparam.malloced = 1;
10691         shellparam.nparam = nparam;
10692         shellparam.p = newparam;
10693 #if ENABLE_ASH_GETOPTS
10694         shellparam.optind = 1;
10695         shellparam.optoff = -1;
10696 #endif
10697 }
10698
10699 /*
10700  * Process shell options.  The global variable argptr contains a pointer
10701  * to the argument list; we advance it past the options.
10702  *
10703  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10704  * For a non-interactive shell, an error condition encountered
10705  * by a special built-in ... shall cause the shell to write a diagnostic message
10706  * to standard error and exit as shown in the following table:
10707  * Error                                           Special Built-In
10708  * ...
10709  * Utility syntax error (option or operand error)  Shall exit
10710  * ...
10711  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10712  * we see that bash does not do that (set "finishes" with error code 1 instead,
10713  * and shell continues), and people rely on this behavior!
10714  * Testcase:
10715  * set -o barfoo 2>/dev/null
10716  * echo $?
10717  *
10718  * Oh well. Let's mimic that.
10719  */
10720 static int
10721 plus_minus_o(char *name, int val)
10722 {
10723         int i;
10724
10725         if (name) {
10726                 for (i = 0; i < NOPTS; i++) {
10727                         if (strcmp(name, optnames(i)) == 0) {
10728                                 optlist[i] = val;
10729                                 return 0;
10730                         }
10731                 }
10732                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10733                 return 1;
10734         }
10735         for (i = 0; i < NOPTS; i++) {
10736                 if (val) {
10737                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10738                 } else {
10739                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10740                 }
10741         }
10742         return 0;
10743 }
10744 static void
10745 setoption(int flag, int val)
10746 {
10747         int i;
10748
10749         for (i = 0; i < NOPTS; i++) {
10750                 if (optletters(i) == flag) {
10751                         optlist[i] = val;
10752                         return;
10753                 }
10754         }
10755         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10756         /* NOTREACHED */
10757 }
10758 static int
10759 options(int cmdline, int *login_sh)
10760 {
10761         char *p;
10762         int val;
10763         int c;
10764
10765         if (cmdline)
10766                 minusc = NULL;
10767         while ((p = *argptr) != NULL) {
10768                 c = *p++;
10769                 if (c != '-' && c != '+')
10770                         break;
10771                 argptr++;
10772                 val = 0; /* val = 0 if c == '+' */
10773                 if (c == '-') {
10774                         val = 1;
10775                         if (p[0] == '\0' || LONE_DASH(p)) {
10776                                 if (!cmdline) {
10777                                         /* "-" means turn off -x and -v */
10778                                         if (p[0] == '\0')
10779                                                 xflag = vflag = 0;
10780                                         /* "--" means reset params */
10781                                         else if (*argptr == NULL)
10782                                                 setparam(argptr);
10783                                 }
10784                                 break;    /* "-" or "--" terminates options */
10785                         }
10786                 }
10787                 /* first char was + or - */
10788                 while ((c = *p++) != '\0') {
10789                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10790                         if (c == 'c' && cmdline) {
10791                                 minusc = p;     /* command is after shell args */
10792                         } else if (c == 'o') {
10793                                 if (plus_minus_o(*argptr, val)) {
10794                                         /* it already printed err message */
10795                                         return 1; /* error */
10796                                 }
10797                                 if (*argptr)
10798                                         argptr++;
10799                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10800                                 if (login_sh)
10801                                         *login_sh = 1;
10802                         /* bash does not accept +-login, we also won't */
10803                         } else if (cmdline && val && (c == '-')) { /* long options */
10804                                 if (strcmp(p, "login") == 0) {
10805                                         if (login_sh)
10806                                                 *login_sh = 1;
10807                                 }
10808                                 break;
10809                         } else {
10810                                 setoption(c, val);
10811                         }
10812                 }
10813         }
10814         return 0;
10815 }
10816
10817 /*
10818  * The shift builtin command.
10819  */
10820 static int FAST_FUNC
10821 shiftcmd(int argc UNUSED_PARAM, char **argv)
10822 {
10823         int n;
10824         char **ap1, **ap2;
10825
10826         n = 1;
10827         if (argv[1])
10828                 n = number(argv[1]);
10829         if (n > shellparam.nparam)
10830                 n = 0; /* bash compat, was = shellparam.nparam; */
10831         INT_OFF;
10832         shellparam.nparam -= n;
10833         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10834                 if (shellparam.malloced)
10835                         free(*ap1);
10836         }
10837         ap2 = shellparam.p;
10838         while ((*ap2++ = *ap1++) != NULL)
10839                 continue;
10840 #if ENABLE_ASH_GETOPTS
10841         shellparam.optind = 1;
10842         shellparam.optoff = -1;
10843 #endif
10844         INT_ON;
10845         return 0;
10846 }
10847
10848 /*
10849  * POSIX requires that 'set' (but not export or readonly) output the
10850  * variables in lexicographic order - by the locale's collating order (sigh).
10851  * Maybe we could keep them in an ordered balanced binary tree
10852  * instead of hashed lists.
10853  * For now just roll 'em through qsort for printing...
10854  */
10855 static int
10856 showvars(const char *sep_prefix, int on, int off)
10857 {
10858         const char *sep;
10859         char **ep, **epend;
10860
10861         ep = listvars(on, off, &epend);
10862         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10863
10864         sep = *sep_prefix ? " " : sep_prefix;
10865
10866         for (; ep < epend; ep++) {
10867                 const char *p;
10868                 const char *q;
10869
10870                 p = strchrnul(*ep, '=');
10871                 q = nullstr;
10872                 if (*p)
10873                         q = single_quote(++p);
10874                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10875         }
10876         return 0;
10877 }
10878
10879 /*
10880  * The set command builtin.
10881  */
10882 static int FAST_FUNC
10883 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10884 {
10885         int retval;
10886
10887         if (!argv[1])
10888                 return showvars(nullstr, 0, VUNSET);
10889
10890         INT_OFF;
10891         retval = options(/*cmdline:*/ 0, NULL);
10892         if (retval == 0) { /* if no parse error... */
10893                 optschanged();
10894                 if (*argptr != NULL) {
10895                         setparam(argptr);
10896                 }
10897         }
10898         INT_ON;
10899         return retval;
10900 }
10901
10902 #if ENABLE_ASH_RANDOM_SUPPORT
10903 static void FAST_FUNC
10904 change_random(const char *value)
10905 {
10906         uint32_t t;
10907
10908         if (value == NULL) {
10909                 /* "get", generate */
10910                 t = next_random(&random_gen);
10911                 /* set without recursion */
10912                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10913                 vrandom.flags &= ~VNOFUNC;
10914         } else {
10915                 /* set/reset */
10916                 t = strtoul(value, NULL, 10);
10917                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10918         }
10919 }
10920 #endif
10921
10922 #if ENABLE_ASH_GETOPTS
10923 static int
10924 getopts(char *optstr, char *optvar, char **optfirst)
10925 {
10926         char *p, *q;
10927         char c = '?';
10928         int done = 0;
10929         char sbuf[2];
10930         char **optnext;
10931         int ind = shellparam.optind;
10932         int off = shellparam.optoff;
10933
10934         sbuf[1] = '\0';
10935
10936         shellparam.optind = -1;
10937         optnext = optfirst + ind - 1;
10938
10939         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10940                 p = NULL;
10941         else
10942                 p = optnext[-1] + off;
10943         if (p == NULL || *p == '\0') {
10944                 /* Current word is done, advance */
10945                 p = *optnext;
10946                 if (p == NULL || *p != '-' || *++p == '\0') {
10947  atend:
10948                         p = NULL;
10949                         done = 1;
10950                         goto out;
10951                 }
10952                 optnext++;
10953                 if (LONE_DASH(p))        /* check for "--" */
10954                         goto atend;
10955         }
10956
10957         c = *p++;
10958         for (q = optstr; *q != c;) {
10959                 if (*q == '\0') {
10960                         if (optstr[0] == ':') {
10961                                 sbuf[0] = c;
10962                                 /*sbuf[1] = '\0'; - already is */
10963                                 setvar0("OPTARG", sbuf);
10964                         } else {
10965                                 fprintf(stderr, "Illegal option -%c\n", c);
10966                                 unsetvar("OPTARG");
10967                         }
10968                         c = '?';
10969                         goto out;
10970                 }
10971                 if (*++q == ':')
10972                         q++;
10973         }
10974
10975         if (*++q == ':') {
10976                 if (*p == '\0' && (p = *optnext) == NULL) {
10977                         if (optstr[0] == ':') {
10978                                 sbuf[0] = c;
10979                                 /*sbuf[1] = '\0'; - already is */
10980                                 setvar0("OPTARG", sbuf);
10981                                 c = ':';
10982                         } else {
10983                                 fprintf(stderr, "No arg for -%c option\n", c);
10984                                 unsetvar("OPTARG");
10985                                 c = '?';
10986                         }
10987                         goto out;
10988                 }
10989
10990                 if (p == *optnext)
10991                         optnext++;
10992                 setvar0("OPTARG", p);
10993                 p = NULL;
10994         } else
10995                 setvar0("OPTARG", nullstr);
10996  out:
10997         ind = optnext - optfirst + 1;
10998         setvar("OPTIND", itoa(ind), VNOFUNC);
10999         sbuf[0] = c;
11000         /*sbuf[1] = '\0'; - already is */
11001         setvar0(optvar, sbuf);
11002
11003         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11004         shellparam.optind = ind;
11005
11006         return done;
11007 }
11008
11009 /*
11010  * The getopts builtin.  Shellparam.optnext points to the next argument
11011  * to be processed.  Shellparam.optptr points to the next character to
11012  * be processed in the current argument.  If shellparam.optnext is NULL,
11013  * then it's the first time getopts has been called.
11014  */
11015 static int FAST_FUNC
11016 getoptscmd(int argc, char **argv)
11017 {
11018         char **optbase;
11019
11020         if (argc < 3)
11021                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11022         if (argc == 3) {
11023                 optbase = shellparam.p;
11024                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11025                         shellparam.optind = 1;
11026                         shellparam.optoff = -1;
11027                 }
11028         } else {
11029                 optbase = &argv[3];
11030                 if ((unsigned)shellparam.optind > argc - 2) {
11031                         shellparam.optind = 1;
11032                         shellparam.optoff = -1;
11033                 }
11034         }
11035
11036         return getopts(argv[1], argv[2], optbase);
11037 }
11038 #endif /* ASH_GETOPTS */
11039
11040
11041 /* ============ Shell parser */
11042
11043 struct heredoc {
11044         struct heredoc *next;   /* next here document in list */
11045         union node *here;       /* redirection node */
11046         char *eofmark;          /* string indicating end of input */
11047         smallint striptabs;     /* if set, strip leading tabs */
11048 };
11049
11050 static smallint tokpushback;           /* last token pushed back */
11051 static smallint quoteflag;             /* set if (part of) last token was quoted */
11052 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11053 static struct heredoc *heredoclist;    /* list of here documents to read */
11054 static char *wordtext;                 /* text of last word returned by readtoken */
11055 static struct nodelist *backquotelist;
11056 static union node *redirnode;
11057 static struct heredoc *heredoc;
11058
11059 static const char *
11060 tokname(char *buf, int tok)
11061 {
11062         if (tok < TSEMI)
11063                 return tokname_array[tok];
11064         sprintf(buf, "\"%s\"", tokname_array[tok]);
11065         return buf;
11066 }
11067
11068 /* raise_error_unexpected_syntax:
11069  * Called when an unexpected token is read during the parse.  The argument
11070  * is the token that is expected, or -1 if more than one type of token can
11071  * occur at this point.
11072  */
11073 static void raise_error_unexpected_syntax(int) NORETURN;
11074 static void
11075 raise_error_unexpected_syntax(int token)
11076 {
11077         char msg[64];
11078         char buf[16];
11079         int l;
11080
11081         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11082         if (token >= 0)
11083                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11084         raise_error_syntax(msg);
11085         /* NOTREACHED */
11086 }
11087
11088 /* parsing is heavily cross-recursive, need these forward decls */
11089 static union node *andor(void);
11090 static union node *pipeline(void);
11091 static union node *parse_command(void);
11092 static void parseheredoc(void);
11093 static int peektoken(void);
11094 static int readtoken(void);
11095
11096 static union node *
11097 list(int nlflag)
11098 {
11099         union node *n1, *n2, *n3;
11100         int tok;
11101
11102         n1 = NULL;
11103         for (;;) {
11104                 switch (peektoken()) {
11105                 case TNL:
11106                         if (!(nlflag & 1))
11107                                 break;
11108                         parseheredoc();
11109                         return n1;
11110
11111                 case TEOF:
11112                         if (!n1 && (nlflag & 1))
11113                                 n1 = NODE_EOF;
11114                         parseheredoc();
11115                         return n1;
11116                 }
11117
11118                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11119                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11120                         return n1;
11121                 nlflag |= 2;
11122
11123                 n2 = andor();
11124                 tok = readtoken();
11125                 if (tok == TBACKGND) {
11126                         if (n2->type == NPIPE) {
11127                                 n2->npipe.pipe_backgnd = 1;
11128                         } else {
11129                                 if (n2->type != NREDIR) {
11130                                         n3 = stzalloc(sizeof(struct nredir));
11131                                         n3->nredir.n = n2;
11132                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11133                                         n2 = n3;
11134                                 }
11135                                 n2->type = NBACKGND;
11136                         }
11137                 }
11138                 if (n1 == NULL) {
11139                         n1 = n2;
11140                 } else {
11141                         n3 = stzalloc(sizeof(struct nbinary));
11142                         n3->type = NSEMI;
11143                         n3->nbinary.ch1 = n1;
11144                         n3->nbinary.ch2 = n2;
11145                         n1 = n3;
11146                 }
11147                 switch (tok) {
11148                 case TNL:
11149                 case TEOF:
11150                         tokpushback = 1;
11151                         /* fall through */
11152                 case TBACKGND:
11153                 case TSEMI:
11154                         break;
11155                 default:
11156                         if ((nlflag & 1))
11157                                 raise_error_unexpected_syntax(-1);
11158                         tokpushback = 1;
11159                         return n1;
11160                 }
11161         }
11162 }
11163
11164 static union node *
11165 andor(void)
11166 {
11167         union node *n1, *n2, *n3;
11168         int t;
11169
11170         n1 = pipeline();
11171         for (;;) {
11172                 t = readtoken();
11173                 if (t == TAND) {
11174                         t = NAND;
11175                 } else if (t == TOR) {
11176                         t = NOR;
11177                 } else {
11178                         tokpushback = 1;
11179                         return n1;
11180                 }
11181                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11182                 n2 = pipeline();
11183                 n3 = stzalloc(sizeof(struct nbinary));
11184                 n3->type = t;
11185                 n3->nbinary.ch1 = n1;
11186                 n3->nbinary.ch2 = n2;
11187                 n1 = n3;
11188         }
11189 }
11190
11191 static union node *
11192 pipeline(void)
11193 {
11194         union node *n1, *n2, *pipenode;
11195         struct nodelist *lp, *prev;
11196         int negate;
11197
11198         negate = 0;
11199         TRACE(("pipeline: entered\n"));
11200         if (readtoken() == TNOT) {
11201                 negate = !negate;
11202                 checkkwd = CHKKWD | CHKALIAS;
11203         } else
11204                 tokpushback = 1;
11205         n1 = parse_command();
11206         if (readtoken() == TPIPE) {
11207                 pipenode = stzalloc(sizeof(struct npipe));
11208                 pipenode->type = NPIPE;
11209                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11210                 lp = stzalloc(sizeof(struct nodelist));
11211                 pipenode->npipe.cmdlist = lp;
11212                 lp->n = n1;
11213                 do {
11214                         prev = lp;
11215                         lp = stzalloc(sizeof(struct nodelist));
11216                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11217                         lp->n = parse_command();
11218                         prev->next = lp;
11219                 } while (readtoken() == TPIPE);
11220                 lp->next = NULL;
11221                 n1 = pipenode;
11222         }
11223         tokpushback = 1;
11224         if (negate) {
11225                 n2 = stzalloc(sizeof(struct nnot));
11226                 n2->type = NNOT;
11227                 n2->nnot.com = n1;
11228                 return n2;
11229         }
11230         return n1;
11231 }
11232
11233 static union node *
11234 makename(void)
11235 {
11236         union node *n;
11237
11238         n = stzalloc(sizeof(struct narg));
11239         n->type = NARG;
11240         /*n->narg.next = NULL; - stzalloc did it */
11241         n->narg.text = wordtext;
11242         n->narg.backquote = backquotelist;
11243         return n;
11244 }
11245
11246 static void
11247 fixredir(union node *n, const char *text, int err)
11248 {
11249         int fd;
11250
11251         TRACE(("Fix redir %s %d\n", text, err));
11252         if (!err)
11253                 n->ndup.vname = NULL;
11254
11255         fd = bb_strtou(text, NULL, 10);
11256         if (!errno && fd >= 0)
11257                 n->ndup.dupfd = fd;
11258         else if (LONE_DASH(text))
11259                 n->ndup.dupfd = -1;
11260         else {
11261                 if (err)
11262                         raise_error_syntax("bad fd number");
11263                 n->ndup.vname = makename();
11264         }
11265 }
11266
11267 static void
11268 parsefname(void)
11269 {
11270         union node *n = redirnode;
11271
11272         if (n->type == NHERE)
11273                 checkkwd = CHKEOFMARK;
11274         if (readtoken() != TWORD)
11275                 raise_error_unexpected_syntax(-1);
11276         if (n->type == NHERE) {
11277                 struct heredoc *here = heredoc;
11278                 struct heredoc *p;
11279
11280                 if (quoteflag == 0)
11281                         n->type = NXHERE;
11282                 TRACE(("Here document %d\n", n->type));
11283                 rmescapes(wordtext, 0);
11284                 here->eofmark = wordtext;
11285                 here->next = NULL;
11286                 if (heredoclist == NULL)
11287                         heredoclist = here;
11288                 else {
11289                         for (p = heredoclist; p->next; p = p->next)
11290                                 continue;
11291                         p->next = here;
11292                 }
11293         } else if (n->type == NTOFD || n->type == NFROMFD) {
11294                 fixredir(n, wordtext, 0);
11295         } else {
11296                 n->nfile.fname = makename();
11297         }
11298 }
11299
11300 static union node *
11301 simplecmd(void)
11302 {
11303         union node *args, **app;
11304         union node *n = NULL;
11305         union node *vars, **vpp;
11306         union node **rpp, *redir;
11307         int savecheckkwd;
11308 #if BASH_TEST2
11309         smallint double_brackets_flag = 0;
11310 #endif
11311         IF_BASH_FUNCTION(smallint function_flag = 0;)
11312
11313         args = NULL;
11314         app = &args;
11315         vars = NULL;
11316         vpp = &vars;
11317         redir = NULL;
11318         rpp = &redir;
11319
11320         savecheckkwd = CHKALIAS;
11321         for (;;) {
11322                 int t;
11323                 checkkwd = savecheckkwd;
11324                 t = readtoken();
11325                 switch (t) {
11326 #if BASH_FUNCTION
11327                 case TFUNCTION:
11328                         if (peektoken() != TWORD)
11329                                 raise_error_unexpected_syntax(TWORD);
11330                         function_flag = 1;
11331                         break;
11332 #endif
11333 #if BASH_TEST2
11334                 case TAND: /* "&&" */
11335                 case TOR: /* "||" */
11336                         if (!double_brackets_flag) {
11337                                 tokpushback = 1;
11338                                 goto out;
11339                         }
11340                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11341 #endif
11342                 case TWORD:
11343                         n = stzalloc(sizeof(struct narg));
11344                         n->type = NARG;
11345                         /*n->narg.next = NULL; - stzalloc did it */
11346                         n->narg.text = wordtext;
11347 #if BASH_TEST2
11348                         if (strcmp("[[", wordtext) == 0)
11349                                 double_brackets_flag = 1;
11350                         else if (strcmp("]]", wordtext) == 0)
11351                                 double_brackets_flag = 0;
11352 #endif
11353                         n->narg.backquote = backquotelist;
11354                         if (savecheckkwd && isassignment(wordtext)) {
11355                                 *vpp = n;
11356                                 vpp = &n->narg.next;
11357                         } else {
11358                                 *app = n;
11359                                 app = &n->narg.next;
11360                                 savecheckkwd = 0;
11361                         }
11362 #if BASH_FUNCTION
11363                         if (function_flag) {
11364                                 checkkwd = CHKNL | CHKKWD;
11365                                 switch (peektoken()) {
11366                                 case TBEGIN:
11367                                 case TIF:
11368                                 case TCASE:
11369                                 case TUNTIL:
11370                                 case TWHILE:
11371                                 case TFOR:
11372                                         goto do_func;
11373                                 case TLP:
11374                                         function_flag = 0;
11375                                         break;
11376                                 case TWORD:
11377                                         if (strcmp("[[", wordtext) == 0)
11378                                                 goto do_func;
11379                                         /* fall through */
11380                                 default:
11381                                         raise_error_unexpected_syntax(-1);
11382                                 }
11383                         }
11384 #endif
11385                         break;
11386                 case TREDIR:
11387                         *rpp = n = redirnode;
11388                         rpp = &n->nfile.next;
11389                         parsefname();   /* read name of redirection file */
11390                         break;
11391                 case TLP:
11392  IF_BASH_FUNCTION(do_func:)
11393                         if (args && app == &args->narg.next
11394                          && !vars && !redir
11395                         ) {
11396                                 struct builtincmd *bcmd;
11397                                 const char *name;
11398
11399                                 /* We have a function */
11400                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11401                                         raise_error_unexpected_syntax(TRP);
11402                                 name = n->narg.text;
11403                                 if (!goodname(name)
11404                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11405                                 ) {
11406                                         raise_error_syntax("bad function name");
11407                                 }
11408                                 n->type = NDEFUN;
11409                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11410                                 n->narg.next = parse_command();
11411                                 return n;
11412                         }
11413                         IF_BASH_FUNCTION(function_flag = 0;)
11414                         /* fall through */
11415                 default:
11416                         tokpushback = 1;
11417                         goto out;
11418                 }
11419         }
11420  out:
11421         *app = NULL;
11422         *vpp = NULL;
11423         *rpp = NULL;
11424         n = stzalloc(sizeof(struct ncmd));
11425         n->type = NCMD;
11426         n->ncmd.args = args;
11427         n->ncmd.assign = vars;
11428         n->ncmd.redirect = redir;
11429         return n;
11430 }
11431
11432 static union node *
11433 parse_command(void)
11434 {
11435         union node *n1, *n2;
11436         union node *ap, **app;
11437         union node *cp, **cpp;
11438         union node *redir, **rpp;
11439         union node **rpp2;
11440         int t;
11441
11442         redir = NULL;
11443         rpp2 = &redir;
11444
11445         switch (readtoken()) {
11446         default:
11447                 raise_error_unexpected_syntax(-1);
11448                 /* NOTREACHED */
11449         case TIF:
11450                 n1 = stzalloc(sizeof(struct nif));
11451                 n1->type = NIF;
11452                 n1->nif.test = list(0);
11453                 if (readtoken() != TTHEN)
11454                         raise_error_unexpected_syntax(TTHEN);
11455                 n1->nif.ifpart = list(0);
11456                 n2 = n1;
11457                 while (readtoken() == TELIF) {
11458                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11459                         n2 = n2->nif.elsepart;
11460                         n2->type = NIF;
11461                         n2->nif.test = list(0);
11462                         if (readtoken() != TTHEN)
11463                                 raise_error_unexpected_syntax(TTHEN);
11464                         n2->nif.ifpart = list(0);
11465                 }
11466                 if (lasttoken == TELSE)
11467                         n2->nif.elsepart = list(0);
11468                 else {
11469                         n2->nif.elsepart = NULL;
11470                         tokpushback = 1;
11471                 }
11472                 t = TFI;
11473                 break;
11474         case TWHILE:
11475         case TUNTIL: {
11476                 int got;
11477                 n1 = stzalloc(sizeof(struct nbinary));
11478                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11479                 n1->nbinary.ch1 = list(0);
11480                 got = readtoken();
11481                 if (got != TDO) {
11482                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11483                                         got == TWORD ? wordtext : ""));
11484                         raise_error_unexpected_syntax(TDO);
11485                 }
11486                 n1->nbinary.ch2 = list(0);
11487                 t = TDONE;
11488                 break;
11489         }
11490         case TFOR:
11491                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11492                         raise_error_syntax("bad for loop variable");
11493                 n1 = stzalloc(sizeof(struct nfor));
11494                 n1->type = NFOR;
11495                 n1->nfor.var = wordtext;
11496                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11497                 if (readtoken() == TIN) {
11498                         app = &ap;
11499                         while (readtoken() == TWORD) {
11500                                 n2 = stzalloc(sizeof(struct narg));
11501                                 n2->type = NARG;
11502                                 /*n2->narg.next = NULL; - stzalloc did it */
11503                                 n2->narg.text = wordtext;
11504                                 n2->narg.backquote = backquotelist;
11505                                 *app = n2;
11506                                 app = &n2->narg.next;
11507                         }
11508                         *app = NULL;
11509                         n1->nfor.args = ap;
11510                         if (lasttoken != TNL && lasttoken != TSEMI)
11511                                 raise_error_unexpected_syntax(-1);
11512                 } else {
11513                         n2 = stzalloc(sizeof(struct narg));
11514                         n2->type = NARG;
11515                         /*n2->narg.next = NULL; - stzalloc did it */
11516                         n2->narg.text = (char *)dolatstr;
11517                         /*n2->narg.backquote = NULL;*/
11518                         n1->nfor.args = n2;
11519                         /*
11520                          * Newline or semicolon here is optional (but note
11521                          * that the original Bourne shell only allowed NL).
11522                          */
11523                         if (lasttoken != TSEMI)
11524                                 tokpushback = 1;
11525                 }
11526                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11527                 if (readtoken() != TDO)
11528                         raise_error_unexpected_syntax(TDO);
11529                 n1->nfor.body = list(0);
11530                 t = TDONE;
11531                 break;
11532         case TCASE:
11533                 n1 = stzalloc(sizeof(struct ncase));
11534                 n1->type = NCASE;
11535                 if (readtoken() != TWORD)
11536                         raise_error_unexpected_syntax(TWORD);
11537                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11538                 n2->type = NARG;
11539                 /*n2->narg.next = NULL; - stzalloc did it */
11540                 n2->narg.text = wordtext;
11541                 n2->narg.backquote = backquotelist;
11542                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11543                 if (readtoken() != TIN)
11544                         raise_error_unexpected_syntax(TIN);
11545                 cpp = &n1->ncase.cases;
11546  next_case:
11547                 checkkwd = CHKNL | CHKKWD;
11548                 t = readtoken();
11549                 while (t != TESAC) {
11550                         if (lasttoken == TLP)
11551                                 readtoken();
11552                         *cpp = cp = stzalloc(sizeof(struct nclist));
11553                         cp->type = NCLIST;
11554                         app = &cp->nclist.pattern;
11555                         for (;;) {
11556                                 *app = ap = stzalloc(sizeof(struct narg));
11557                                 ap->type = NARG;
11558                                 /*ap->narg.next = NULL; - stzalloc did it */
11559                                 ap->narg.text = wordtext;
11560                                 ap->narg.backquote = backquotelist;
11561                                 if (readtoken() != TPIPE)
11562                                         break;
11563                                 app = &ap->narg.next;
11564                                 readtoken();
11565                         }
11566                         //ap->narg.next = NULL;
11567                         if (lasttoken != TRP)
11568                                 raise_error_unexpected_syntax(TRP);
11569                         cp->nclist.body = list(2);
11570
11571                         cpp = &cp->nclist.next;
11572
11573                         checkkwd = CHKNL | CHKKWD;
11574                         t = readtoken();
11575                         if (t != TESAC) {
11576                                 if (t != TENDCASE)
11577                                         raise_error_unexpected_syntax(TENDCASE);
11578                                 goto next_case;
11579                         }
11580                 }
11581                 *cpp = NULL;
11582                 goto redir;
11583         case TLP:
11584                 n1 = stzalloc(sizeof(struct nredir));
11585                 n1->type = NSUBSHELL;
11586                 n1->nredir.n = list(0);
11587                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11588                 t = TRP;
11589                 break;
11590         case TBEGIN:
11591                 n1 = list(0);
11592                 t = TEND;
11593                 break;
11594         IF_BASH_FUNCTION(case TFUNCTION:)
11595         case TWORD:
11596         case TREDIR:
11597                 tokpushback = 1;
11598                 return simplecmd();
11599         }
11600
11601         if (readtoken() != t)
11602                 raise_error_unexpected_syntax(t);
11603
11604  redir:
11605         /* Now check for redirection which may follow command */
11606         checkkwd = CHKKWD | CHKALIAS;
11607         rpp = rpp2;
11608         while (readtoken() == TREDIR) {
11609                 *rpp = n2 = redirnode;
11610                 rpp = &n2->nfile.next;
11611                 parsefname();
11612         }
11613         tokpushback = 1;
11614         *rpp = NULL;
11615         if (redir) {
11616                 if (n1->type != NSUBSHELL) {
11617                         n2 = stzalloc(sizeof(struct nredir));
11618                         n2->type = NREDIR;
11619                         n2->nredir.n = n1;
11620                         n1 = n2;
11621                 }
11622                 n1->nredir.redirect = redir;
11623         }
11624         return n1;
11625 }
11626
11627 #if BASH_DOLLAR_SQUOTE
11628 static int
11629 decode_dollar_squote(void)
11630 {
11631         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11632         int c, cnt;
11633         char *p;
11634         char buf[4];
11635
11636         c = pgetc();
11637         p = strchr(C_escapes, c);
11638         if (p) {
11639                 buf[0] = c;
11640                 p = buf;
11641                 cnt = 3;
11642                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11643                         do {
11644                                 c = pgetc();
11645                                 *++p = c;
11646                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11647                         pungetc();
11648                 } else if (c == 'x') { /* \xHH */
11649                         do {
11650                                 c = pgetc();
11651                                 *++p = c;
11652                         } while (isxdigit(c) && --cnt);
11653                         pungetc();
11654                         if (cnt == 3) { /* \x but next char is "bad" */
11655                                 c = 'x';
11656                                 goto unrecognized;
11657                         }
11658                 } else { /* simple seq like \\ or \t */
11659                         p++;
11660                 }
11661                 *p = '\0';
11662                 p = buf;
11663                 c = bb_process_escape_sequence((void*)&p);
11664         } else { /* unrecognized "\z": print both chars unless ' or " */
11665                 if (c != '\'' && c != '"') {
11666  unrecognized:
11667                         c |= 0x100; /* "please encode \, then me" */
11668                 }
11669         }
11670         return c;
11671 }
11672 #endif
11673
11674 /* Used by expandstr to get here-doc like behaviour. */
11675 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11676
11677 static ALWAYS_INLINE int
11678 realeofmark(const char *eofmark)
11679 {
11680         return eofmark && eofmark != FAKEEOFMARK;
11681 }
11682
11683 /*
11684  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11685  * is not NULL, read a here document.  In the latter case, eofmark is the
11686  * word which marks the end of the document and striptabs is true if
11687  * leading tabs should be stripped from the document.  The argument c
11688  * is the first character of the input token or document.
11689  *
11690  * Because C does not have internal subroutines, I have simulated them
11691  * using goto's to implement the subroutine linkage.  The following macros
11692  * will run code that appears at the end of readtoken1.
11693  */
11694 #define CHECKEND()      {goto checkend; checkend_return:;}
11695 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11696 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11697 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11698 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11699 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11700 static int
11701 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11702 {
11703         /* NB: syntax parameter fits into smallint */
11704         /* c parameter is an unsigned char or PEOF or PEOA */
11705         char *out;
11706         size_t len;
11707         struct nodelist *bqlist;
11708         smallint quotef;
11709         smallint dblquote;
11710         smallint oldstyle;
11711         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11712         smallint pssyntax;   /* we are expanding a prompt string */
11713         int varnest;         /* levels of variables expansion */
11714         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11715         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11716         int dqvarnest;       /* levels of variables expansion within double quotes */
11717
11718         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11719
11720         startlinno = g_parsefile->linno;
11721         bqlist = NULL;
11722         quotef = 0;
11723         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11724 #if ENABLE_ASH_EXPAND_PRMT
11725         pssyntax = (syntax == PSSYNTAX);
11726         if (pssyntax)
11727                 syntax = DQSYNTAX;
11728 #else
11729         pssyntax = 0; /* constant */
11730 #endif
11731         dblquote = (syntax == DQSYNTAX);
11732         varnest = 0;
11733         IF_FEATURE_SH_MATH(arinest = 0;)
11734         IF_FEATURE_SH_MATH(parenlevel = 0;)
11735         dqvarnest = 0;
11736
11737         STARTSTACKSTR(out);
11738  loop:
11739         /* For each line, until end of word */
11740         CHECKEND();     /* set c to PEOF if at end of here document */
11741         for (;;) {      /* until end of line or end of word */
11742                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11743                 switch (SIT(c, syntax)) {
11744                 case CNL:       /* '\n' */
11745                         if (syntax == BASESYNTAX)
11746                                 goto endword;   /* exit outer loop */
11747                         USTPUTC(c, out);
11748                         nlprompt();
11749                         c = pgetc();
11750                         goto loop;              /* continue outer loop */
11751                 case CWORD:
11752                         USTPUTC(c, out);
11753                         break;
11754                 case CCTL:
11755 #if BASH_DOLLAR_SQUOTE
11756                         if (c == '\\' && bash_dollar_squote) {
11757                                 c = decode_dollar_squote();
11758                                 if (c == '\0') {
11759                                         /* skip $'\000', $'\x00' (like bash) */
11760                                         break;
11761                                 }
11762                                 if (c & 0x100) {
11763                                         /* Unknown escape. Encode as '\z' */
11764                                         c = (unsigned char)c;
11765                                         if (eofmark == NULL || dblquote)
11766                                                 USTPUTC(CTLESC, out);
11767                                         USTPUTC('\\', out);
11768                                 }
11769                         }
11770 #endif
11771                         if (eofmark == NULL || dblquote)
11772                                 USTPUTC(CTLESC, out);
11773                         USTPUTC(c, out);
11774                         break;
11775                 case CBACK:     /* backslash */
11776                         c = pgetc_without_PEOA();
11777                         if (c == PEOF) {
11778                                 USTPUTC(CTLESC, out);
11779                                 USTPUTC('\\', out);
11780                                 pungetc();
11781                         } else if (c == '\n') {
11782                                 nlprompt();
11783                         } else {
11784                                 if (pssyntax && c == '$') {
11785                                         USTPUTC(CTLESC, out);
11786                                         USTPUTC('\\', out);
11787                                 }
11788                                 /* Backslash is retained if we are in "str" and next char isn't special */
11789                                 if (dblquote
11790                                  && c != '\\'
11791                                  && c != '`'
11792                                  && c != '$'
11793                                  && (c != '"' || eofmark != NULL)
11794                                 ) {
11795                                         USTPUTC('\\', out);
11796                                 }
11797                                 USTPUTC(CTLESC, out);
11798                                 USTPUTC(c, out);
11799                                 quotef = 1;
11800                         }
11801                         break;
11802                 case CSQUOTE:
11803                         syntax = SQSYNTAX;
11804  quotemark:
11805                         if (eofmark == NULL) {
11806                                 USTPUTC(CTLQUOTEMARK, out);
11807                         }
11808                         break;
11809                 case CDQUOTE:
11810                         syntax = DQSYNTAX;
11811                         dblquote = 1;
11812                         goto quotemark;
11813                 case CENDQUOTE:
11814                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11815                         if (eofmark != NULL && varnest == 0) {
11816                                 USTPUTC(c, out);
11817                         } else {
11818                                 if (dqvarnest == 0) {
11819                                         syntax = BASESYNTAX;
11820                                         dblquote = 0;
11821                                 }
11822                                 quotef = 1;
11823                                 goto quotemark;
11824                         }
11825                         break;
11826                 case CVAR:      /* '$' */
11827                         PARSESUB();             /* parse substitution */
11828                         break;
11829                 case CENDVAR:   /* '}' */
11830                         if (varnest > 0) {
11831                                 varnest--;
11832                                 if (dqvarnest > 0) {
11833                                         dqvarnest--;
11834                                 }
11835                                 c = CTLENDVAR;
11836                         }
11837                         USTPUTC(c, out);
11838                         break;
11839 #if ENABLE_FEATURE_SH_MATH
11840                 case CLP:       /* '(' in arithmetic */
11841                         parenlevel++;
11842                         USTPUTC(c, out);
11843                         break;
11844                 case CRP:       /* ')' in arithmetic */
11845                         if (parenlevel > 0) {
11846                                 parenlevel--;
11847                         } else {
11848                                 if (pgetc_eatbnl() == ')') {
11849                                         c = CTLENDARI;
11850                                         if (--arinest == 0) {
11851                                                 syntax = prevsyntax;
11852                                         }
11853                                 } else {
11854                                         /*
11855                                          * unbalanced parens
11856                                          * (don't 2nd guess - no error)
11857                                          */
11858                                         pungetc();
11859                                 }
11860                         }
11861                         USTPUTC(c, out);
11862                         break;
11863 #endif
11864                 case CBQUOTE:   /* '`' */
11865                         PARSEBACKQOLD();
11866                         break;
11867                 case CENDFILE:
11868                         goto endword;           /* exit outer loop */
11869                 case CIGN:
11870                         break;
11871                 default:
11872                         if (varnest == 0) {
11873 #if BASH_REDIR_OUTPUT
11874                                 if (c == '&') {
11875 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11876                                         if (pgetc() == '>')
11877                                                 c = 0x100 + '>'; /* flag &> */
11878                                         pungetc();
11879                                 }
11880 #endif
11881                                 goto endword;   /* exit outer loop */
11882                         }
11883                         IF_ASH_ALIAS(if (c != PEOA))
11884                                 USTPUTC(c, out);
11885                 }
11886                 c = pgetc();
11887         } /* for (;;) */
11888  endword:
11889
11890 #if ENABLE_FEATURE_SH_MATH
11891         if (syntax == ARISYNTAX)
11892                 raise_error_syntax("missing '))'");
11893 #endif
11894         if (syntax != BASESYNTAX && eofmark == NULL)
11895                 raise_error_syntax("unterminated quoted string");
11896         if (varnest != 0) {
11897                 startlinno = g_parsefile->linno;
11898                 /* { */
11899                 raise_error_syntax("missing '}'");
11900         }
11901         USTPUTC('\0', out);
11902         len = out - (char *)stackblock();
11903         out = stackblock();
11904         if (eofmark == NULL) {
11905                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11906                  && quotef == 0
11907                 ) {
11908                         if (isdigit_str9(out)) {
11909                                 PARSEREDIR(); /* passed as params: out, c */
11910                                 lasttoken = TREDIR;
11911                                 return lasttoken;
11912                         }
11913                         /* else: non-number X seen, interpret it
11914                          * as "NNNX>file" = "NNNX >file" */
11915                 }
11916                 pungetc();
11917         }
11918         quoteflag = quotef;
11919         backquotelist = bqlist;
11920         grabstackblock(len);
11921         wordtext = out;
11922         lasttoken = TWORD;
11923         return lasttoken;
11924 /* end of readtoken routine */
11925
11926 /*
11927  * Check to see whether we are at the end of the here document.  When this
11928  * is called, c is set to the first character of the next input line.  If
11929  * we are at the end of the here document, this routine sets the c to PEOF.
11930  */
11931 checkend: {
11932         if (realeofmark(eofmark)) {
11933                 int markloc;
11934                 char *p;
11935
11936 #if ENABLE_ASH_ALIAS
11937                 if (c == PEOA)
11938                         c = pgetc_without_PEOA();
11939 #endif
11940                 if (striptabs) {
11941                         while (c == '\t') {
11942                                 c = pgetc_without_PEOA();
11943                         }
11944                 }
11945
11946                 markloc = out - (char *)stackblock();
11947                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11948                         if (c != *p)
11949                                 goto more_heredoc;
11950
11951                         c = pgetc_without_PEOA();
11952                 }
11953
11954                 if (c == '\n' || c == PEOF) {
11955                         c = PEOF;
11956                         g_parsefile->linno++;
11957                         needprompt = doprompt;
11958                 } else {
11959                         int len_here;
11960
11961  more_heredoc:
11962                         p = (char *)stackblock() + markloc + 1;
11963                         len_here = out - p;
11964
11965                         if (len_here) {
11966                                 len_here -= (c >= PEOF);
11967                                 c = p[-1];
11968
11969                                 if (len_here) {
11970                                         char *str;
11971
11972                                         str = alloca(len_here + 1);
11973                                         *(char *)mempcpy(str, p, len_here) = '\0';
11974
11975                                         pushstring(str, NULL);
11976                                 }
11977                         }
11978                 }
11979
11980                 STADJUST((char *)stackblock() + markloc - out, out);
11981         }
11982         goto checkend_return;
11983 }
11984
11985 /*
11986  * Parse a redirection operator.  The variable "out" points to a string
11987  * specifying the fd to be redirected.  The variable "c" contains the
11988  * first character of the redirection operator.
11989  */
11990 parseredir: {
11991         /* out is already checked to be a valid number or "" */
11992         int fd = (*out == '\0' ? -1 : atoi(out));
11993         union node *np;
11994
11995         np = stzalloc(sizeof(struct nfile));
11996         if (c == '>') {
11997                 np->nfile.fd = 1;
11998                 c = pgetc();
11999                 if (c == '>')
12000                         np->type = NAPPEND;
12001                 else if (c == '|')
12002                         np->type = NCLOBBER;
12003                 else if (c == '&')
12004                         np->type = NTOFD;
12005                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12006                 else {
12007                         np->type = NTO;
12008                         pungetc();
12009                 }
12010         }
12011 #if BASH_REDIR_OUTPUT
12012         else if (c == 0x100 + '>') { /* this flags &> redirection */
12013                 np->nfile.fd = 1;
12014                 pgetc(); /* this is '>', no need to check */
12015                 np->type = NTO2;
12016         }
12017 #endif
12018         else { /* c == '<' */
12019                 /*np->nfile.fd = 0; - stzalloc did it */
12020                 c = pgetc();
12021                 switch (c) {
12022                 case '<':
12023                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12024                                 np = stzalloc(sizeof(struct nhere));
12025                                 /*np->nfile.fd = 0; - stzalloc did it */
12026                         }
12027                         np->type = NHERE;
12028                         heredoc = stzalloc(sizeof(struct heredoc));
12029                         heredoc->here = np;
12030                         c = pgetc();
12031                         if (c == '-') {
12032                                 heredoc->striptabs = 1;
12033                         } else {
12034                                 /*heredoc->striptabs = 0; - stzalloc did it */
12035                                 pungetc();
12036                         }
12037                         break;
12038
12039                 case '&':
12040                         np->type = NFROMFD;
12041                         break;
12042
12043                 case '>':
12044                         np->type = NFROMTO;
12045                         break;
12046
12047                 default:
12048                         np->type = NFROM;
12049                         pungetc();
12050                         break;
12051                 }
12052         }
12053         if (fd >= 0)
12054                 np->nfile.fd = fd;
12055         redirnode = np;
12056         goto parseredir_return;
12057 }
12058
12059 /*
12060  * Parse a substitution.  At this point, we have read the dollar sign
12061  * and nothing else.
12062  */
12063
12064 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12065  * (assuming ascii char codes, as the original implementation did) */
12066 #define is_special(c) \
12067         (((unsigned)(c) - 33 < 32) \
12068                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12069 parsesub: {
12070         unsigned char subtype;
12071         int typeloc;
12072
12073         c = pgetc_eatbnl();
12074         if ((checkkwd & CHKEOFMARK)
12075          || c > 255 /* PEOA or PEOF */
12076          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12077         ) {
12078 #if BASH_DOLLAR_SQUOTE
12079                 if (syntax != DQSYNTAX && c == '\'')
12080                         bash_dollar_squote = 1;
12081                 else
12082 #endif
12083                         USTPUTC('$', out);
12084                 pungetc();
12085         } else if (c == '(') {
12086                 /* $(command) or $((arith)) */
12087                 if (pgetc_eatbnl() == '(') {
12088 #if ENABLE_FEATURE_SH_MATH
12089                         PARSEARITH();
12090 #else
12091                         raise_error_syntax("support for $((arith)) is disabled");
12092 #endif
12093                 } else {
12094                         pungetc();
12095                         PARSEBACKQNEW();
12096                 }
12097         } else {
12098                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12099                 USTPUTC(CTLVAR, out);
12100                 typeloc = out - (char *)stackblock();
12101                 STADJUST(1, out);
12102                 subtype = VSNORMAL;
12103                 if (c == '{') {
12104                         c = pgetc_eatbnl();
12105                         subtype = 0;
12106                 }
12107  varname:
12108                 if (is_name(c)) {
12109                         /* $[{[#]]NAME[}] */
12110                         do {
12111                                 STPUTC(c, out);
12112                                 c = pgetc_eatbnl();
12113                         } while (is_in_name(c));
12114                 } else if (isdigit(c)) {
12115                         /* $[{[#]]NUM[}] */
12116                         do {
12117                                 STPUTC(c, out);
12118                                 c = pgetc_eatbnl();
12119                         } while (isdigit(c));
12120                 } else if (is_special(c)) {
12121                         /* $[{[#]]<specialchar>[}] */
12122                         int cc = c;
12123
12124                         c = pgetc_eatbnl();
12125                         if (!subtype && cc == '#') {
12126                                 subtype = VSLENGTH;
12127                                 if (c == '_' || isalnum(c))
12128                                         goto varname;
12129                                 cc = c;
12130                                 c = pgetc_eatbnl();
12131                                 if (cc == '}' || c != '}') {
12132                                         pungetc();
12133                                         subtype = 0;
12134                                         c = cc;
12135                                         cc = '#';
12136                                 }
12137                         }
12138                         USTPUTC(cc, out);
12139                 } else {
12140                         goto badsub;
12141                 }
12142                 if (c != '}' && subtype == VSLENGTH) {
12143                         /* ${#VAR didn't end with } */
12144                         goto badsub;
12145                 }
12146
12147                 if (subtype == 0) {
12148                         static const char types[] ALIGN1 = "}-+?=";
12149                         /* ${VAR...} but not $VAR or ${#VAR} */
12150                         /* c == first char after VAR */
12151                         switch (c) {
12152                         case ':':
12153                                 c = pgetc_eatbnl();
12154 #if BASH_SUBSTR
12155                                 /* This check is only needed to not misinterpret
12156                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12157                                  * constructs.
12158                                  */
12159                                 if (!strchr(types, c)) {
12160                                         subtype = VSSUBSTR;
12161                                         pungetc();
12162                                         break; /* "goto badsub" is bigger (!) */
12163                                 }
12164 #endif
12165                                 subtype = VSNUL;
12166                                 /*FALLTHROUGH*/
12167                         default: {
12168                                 const char *p = strchr(types, c);
12169                                 if (p == NULL)
12170                                         break;
12171                                 subtype |= p - types + VSNORMAL;
12172                                 break;
12173                         }
12174                         case '%':
12175                         case '#': {
12176                                 int cc = c;
12177                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12178                                 c = pgetc_eatbnl();
12179                                 if (c != cc)
12180                                         goto badsub;
12181                                 subtype++;
12182                                 break;
12183                         }
12184 #if BASH_PATTERN_SUBST
12185                         case '/':
12186                                 /* ${v/[/]pattern/repl} */
12187 //TODO: encode pattern and repl separately.
12188 // Currently ${v/$var_with_slash/repl} is horribly broken
12189                                 subtype = VSREPLACE;
12190                                 c = pgetc_eatbnl();
12191                                 if (c != '/')
12192                                         goto badsub;
12193                                 subtype++; /* VSREPLACEALL */
12194                                 break;
12195 #endif
12196                         }
12197                 } else {
12198  badsub:
12199                         pungetc();
12200                 }
12201                 ((unsigned char *)stackblock())[typeloc] = subtype;
12202                 if (subtype != VSNORMAL) {
12203                         varnest++;
12204                         if (dblquote)
12205                                 dqvarnest++;
12206                 }
12207                 STPUTC('=', out);
12208         }
12209         goto parsesub_return;
12210 }
12211
12212 /*
12213  * Called to parse command substitutions.  Newstyle is set if the command
12214  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12215  * list of commands (passed by reference), and savelen is the number of
12216  * characters on the top of the stack which must be preserved.
12217  */
12218 parsebackq: {
12219         struct nodelist **nlpp;
12220         union node *n;
12221         char *str;
12222         size_t savelen;
12223         smallint saveprompt = 0;
12224
12225         str = NULL;
12226         savelen = out - (char *)stackblock();
12227         if (savelen > 0) {
12228                 /*
12229                  * FIXME: this can allocate very large block on stack and SEGV.
12230                  * Example:
12231                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12232                  * allocates 100kb for every command subst. With about
12233                  * a hundred command substitutions stack overflows.
12234                  * With larger prepended string, SEGV happens sooner.
12235                  */
12236                 str = alloca(savelen);
12237                 memcpy(str, stackblock(), savelen);
12238         }
12239
12240         if (oldstyle) {
12241                 /* We must read until the closing backquote, giving special
12242                  * treatment to some slashes, and then push the string and
12243                  * reread it as input, interpreting it normally.
12244                  */
12245                 char *pout;
12246                 size_t psavelen;
12247                 char *pstr;
12248
12249                 STARTSTACKSTR(pout);
12250                 for (;;) {
12251                         int pc;
12252
12253                         setprompt_if(needprompt, 2);
12254                         pc = pgetc();
12255                         switch (pc) {
12256                         case '`':
12257                                 goto done;
12258
12259                         case '\\':
12260                                 pc = pgetc();
12261                                 if (pc == '\n') {
12262                                         nlprompt();
12263                                         /*
12264                                          * If eating a newline, avoid putting
12265                                          * the newline into the new character
12266                                          * stream (via the STPUTC after the
12267                                          * switch).
12268                                          */
12269                                         continue;
12270                                 }
12271                                 if (pc != '\\' && pc != '`' && pc != '$'
12272                                  && (!dblquote || pc != '"')
12273                                 ) {
12274                                         STPUTC('\\', pout);
12275                                 }
12276                                 if (pc <= 255 /* not PEOA or PEOF */) {
12277                                         break;
12278                                 }
12279                                 /* fall through */
12280
12281                         case PEOF:
12282                         IF_ASH_ALIAS(case PEOA:)
12283                                 startlinno = g_parsefile->linno;
12284                                 raise_error_syntax("EOF in backquote substitution");
12285
12286                         case '\n':
12287                                 nlnoprompt();
12288                                 break;
12289
12290                         default:
12291                                 break;
12292                         }
12293                         STPUTC(pc, pout);
12294                 }
12295  done:
12296                 STPUTC('\0', pout);
12297                 psavelen = pout - (char *)stackblock();
12298                 if (psavelen > 0) {
12299                         pstr = grabstackstr(pout);
12300                         setinputstring(pstr);
12301                 }
12302         }
12303         nlpp = &bqlist;
12304         while (*nlpp)
12305                 nlpp = &(*nlpp)->next;
12306         *nlpp = stzalloc(sizeof(**nlpp));
12307         /* (*nlpp)->next = NULL; - stzalloc did it */
12308
12309         if (oldstyle) {
12310                 saveprompt = doprompt;
12311                 doprompt = 0;
12312         }
12313
12314         n = list(2);
12315
12316         if (oldstyle)
12317                 doprompt = saveprompt;
12318         else if (readtoken() != TRP)
12319                 raise_error_unexpected_syntax(TRP);
12320
12321         (*nlpp)->n = n;
12322         if (oldstyle) {
12323                 /*
12324                  * Start reading from old file again, ignoring any pushed back
12325                  * tokens left from the backquote parsing
12326                  */
12327                 popfile();
12328                 tokpushback = 0;
12329         }
12330         while (stackblocksize() <= savelen)
12331                 growstackblock();
12332         STARTSTACKSTR(out);
12333         if (str) {
12334                 memcpy(out, str, savelen);
12335                 STADJUST(savelen, out);
12336         }
12337         USTPUTC(CTLBACKQ, out);
12338         if (oldstyle)
12339                 goto parsebackq_oldreturn;
12340         goto parsebackq_newreturn;
12341 }
12342
12343 #if ENABLE_FEATURE_SH_MATH
12344 /*
12345  * Parse an arithmetic expansion (indicate start of one and set state)
12346  */
12347 parsearith: {
12348         if (++arinest == 1) {
12349                 prevsyntax = syntax;
12350                 syntax = ARISYNTAX;
12351         }
12352         USTPUTC(CTLARI, out);
12353         goto parsearith_return;
12354 }
12355 #endif
12356 } /* end of readtoken */
12357
12358 /*
12359  * Read the next input token.
12360  * If the token is a word, we set backquotelist to the list of cmds in
12361  *      backquotes.  We set quoteflag to true if any part of the word was
12362  *      quoted.
12363  * If the token is TREDIR, then we set redirnode to a structure containing
12364  *      the redirection.
12365  * In all cases, the variable startlinno is set to the number of the line
12366  *      on which the token starts.
12367  *
12368  * [Change comment:  here documents and internal procedures]
12369  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12370  *  word parsing code into a separate routine.  In this case, readtoken
12371  *  doesn't need to have any internal procedures, but parseword does.
12372  *  We could also make parseoperator in essence the main routine, and
12373  *  have parseword (readtoken1?) handle both words and redirection.]
12374  */
12375 #define NEW_xxreadtoken
12376 #ifdef NEW_xxreadtoken
12377 /* singles must be first! */
12378 static const char xxreadtoken_chars[7] ALIGN1 = {
12379         '\n', '(', ')', /* singles */
12380         '&', '|', ';',  /* doubles */
12381         0
12382 };
12383
12384 #define xxreadtoken_singles 3
12385 #define xxreadtoken_doubles 3
12386
12387 static const char xxreadtoken_tokens[] ALIGN1 = {
12388         TNL, TLP, TRP,          /* only single occurrence allowed */
12389         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12390         TEOF,                   /* corresponds to trailing nul */
12391         TAND, TOR, TENDCASE     /* if double occurrence */
12392 };
12393
12394 static int
12395 xxreadtoken(void)
12396 {
12397         int c;
12398
12399         if (tokpushback) {
12400                 tokpushback = 0;
12401                 return lasttoken;
12402         }
12403         setprompt_if(needprompt, 2);
12404         startlinno = g_parsefile->linno;
12405         for (;;) {                      /* until token or start of word found */
12406                 c = pgetc();
12407                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12408                         continue;
12409
12410                 if (c == '#') {
12411                         while ((c = pgetc()) != '\n' && c != PEOF)
12412                                 continue;
12413                         pungetc();
12414                 } else if (c == '\\') {
12415                         if (pgetc() != '\n') {
12416                                 pungetc();
12417                                 break; /* return readtoken1(...) */
12418                         }
12419                         nlprompt();
12420                 } else {
12421                         const char *p;
12422
12423                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12424                         if (c != PEOF) {
12425                                 if (c == '\n') {
12426                                         nlnoprompt();
12427                                 }
12428
12429                                 p = strchr(xxreadtoken_chars, c);
12430                                 if (p == NULL)
12431                                         break; /* return readtoken1(...) */
12432
12433                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12434                                         int cc = pgetc();
12435                                         if (cc == c) {    /* double occurrence? */
12436                                                 p += xxreadtoken_doubles + 1;
12437                                         } else {
12438                                                 pungetc();
12439 #if BASH_REDIR_OUTPUT
12440                                                 if (c == '&' && cc == '>') /* &> */
12441                                                         break; /* return readtoken1(...) */
12442 #endif
12443                                         }
12444                                 }
12445                         }
12446                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12447                         return lasttoken;
12448                 }
12449         } /* for (;;) */
12450
12451         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12452 }
12453 #else /* old xxreadtoken */
12454 #define RETURN(token)   return lasttoken = token
12455 static int
12456 xxreadtoken(void)
12457 {
12458         int c;
12459
12460         if (tokpushback) {
12461                 tokpushback = 0;
12462                 return lasttoken;
12463         }
12464         setprompt_if(needprompt, 2);
12465         startlinno = g_parsefile->linno;
12466         for (;;) {      /* until token or start of word found */
12467                 c = pgetc();
12468                 switch (c) {
12469                 case ' ': case '\t':
12470                 IF_ASH_ALIAS(case PEOA:)
12471                         continue;
12472                 case '#':
12473                         while ((c = pgetc()) != '\n' && c != PEOF)
12474                                 continue;
12475                         pungetc();
12476                         continue;
12477                 case '\\':
12478                         if (pgetc() == '\n') {
12479                                 nlprompt();
12480                                 continue;
12481                         }
12482                         pungetc();
12483                         goto breakloop;
12484                 case '\n':
12485                         nlnoprompt();
12486                         RETURN(TNL);
12487                 case PEOF:
12488                         RETURN(TEOF);
12489                 case '&':
12490                         if (pgetc() == '&')
12491                                 RETURN(TAND);
12492                         pungetc();
12493                         RETURN(TBACKGND);
12494                 case '|':
12495                         if (pgetc() == '|')
12496                                 RETURN(TOR);
12497                         pungetc();
12498                         RETURN(TPIPE);
12499                 case ';':
12500                         if (pgetc() == ';')
12501                                 RETURN(TENDCASE);
12502                         pungetc();
12503                         RETURN(TSEMI);
12504                 case '(':
12505                         RETURN(TLP);
12506                 case ')':
12507                         RETURN(TRP);
12508                 default:
12509                         goto breakloop;
12510                 }
12511         }
12512  breakloop:
12513         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12514 #undef RETURN
12515 }
12516 #endif /* old xxreadtoken */
12517
12518 static int
12519 readtoken(void)
12520 {
12521         int t;
12522         int kwd = checkkwd;
12523 #if DEBUG
12524         smallint alreadyseen = tokpushback;
12525 #endif
12526
12527 #if ENABLE_ASH_ALIAS
12528  top:
12529 #endif
12530
12531         t = xxreadtoken();
12532
12533         /*
12534          * eat newlines
12535          */
12536         if (kwd & CHKNL) {
12537                 while (t == TNL) {
12538                         parseheredoc();
12539                         t = xxreadtoken();
12540                 }
12541         }
12542
12543         if (t != TWORD || quoteflag) {
12544                 goto out;
12545         }
12546
12547         /*
12548          * check for keywords
12549          */
12550         if (kwd & CHKKWD) {
12551                 const char *const *pp;
12552
12553                 pp = findkwd(wordtext);
12554                 if (pp) {
12555                         lasttoken = t = pp - tokname_array;
12556                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12557                         goto out;
12558                 }
12559         }
12560
12561         if (checkkwd & CHKALIAS) {
12562 #if ENABLE_ASH_ALIAS
12563                 struct alias *ap;
12564                 ap = lookupalias(wordtext, 1);
12565                 if (ap != NULL) {
12566                         if (*ap->val) {
12567                                 pushstring(ap->val, ap);
12568                         }
12569                         goto top;
12570                 }
12571 #endif
12572         }
12573  out:
12574         checkkwd = 0;
12575 #if DEBUG
12576         if (!alreadyseen)
12577                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12578         else
12579                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12580 #endif
12581         return t;
12582 }
12583
12584 static int
12585 peektoken(void)
12586 {
12587         int t;
12588
12589         t = readtoken();
12590         tokpushback = 1;
12591         return t;
12592 }
12593
12594 /*
12595  * Read and parse a command.  Returns NODE_EOF on end of file.
12596  * (NULL is a valid parse tree indicating a blank line.)
12597  */
12598 static union node *
12599 parsecmd(int interact)
12600 {
12601         tokpushback = 0;
12602         checkkwd = 0;
12603         heredoclist = 0;
12604         doprompt = interact;
12605         setprompt_if(doprompt, doprompt);
12606         needprompt = 0;
12607         return list(1);
12608 }
12609
12610 /*
12611  * Input any here documents.
12612  */
12613 static void
12614 parseheredoc(void)
12615 {
12616         struct heredoc *here;
12617         union node *n;
12618
12619         here = heredoclist;
12620         heredoclist = NULL;
12621
12622         while (here) {
12623                 setprompt_if(needprompt, 2);
12624                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12625                                 here->eofmark, here->striptabs);
12626                 n = stzalloc(sizeof(struct narg));
12627                 n->narg.type = NARG;
12628                 /*n->narg.next = NULL; - stzalloc did it */
12629                 n->narg.text = wordtext;
12630                 n->narg.backquote = backquotelist;
12631                 here->here->nhere.doc = n;
12632                 here = here->next;
12633         }
12634 }
12635
12636
12637 static const char *
12638 expandstr(const char *ps, int syntax_type)
12639 {
12640         union node n;
12641         int saveprompt;
12642
12643         /* XXX Fix (char *) cast. */
12644         setinputstring((char *)ps);
12645
12646         saveprompt = doprompt;
12647         doprompt = 0;
12648         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12649         doprompt = saveprompt;
12650
12651         popfile();
12652
12653         n.narg.type = NARG;
12654         n.narg.next = NULL;
12655         n.narg.text = wordtext;
12656         n.narg.backquote = backquotelist;
12657
12658         expandarg(&n, NULL, EXP_QUOTED);
12659         return stackblock();
12660 }
12661
12662 static inline int
12663 parser_eof(void)
12664 {
12665         return tokpushback && lasttoken == TEOF;
12666 }
12667
12668 /*
12669  * Execute a command or commands contained in a string.
12670  */
12671 static int
12672 evalstring(char *s, int flags)
12673 {
12674         struct jmploc *volatile savehandler;
12675         struct jmploc jmploc;
12676         int ex;
12677
12678         union node *n;
12679         struct stackmark smark;
12680         int status;
12681
12682         s = sstrdup(s);
12683         setinputstring(s);
12684         setstackmark(&smark);
12685
12686         status = 0;
12687         /* On exception inside execution loop, we must popfile().
12688          * Try interactively:
12689          *      readonly a=a
12690          *      command eval "a=b"  # throws "is read only" error
12691          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12692          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12693          */
12694         savehandler = exception_handler;
12695         ex = setjmp(jmploc.loc);
12696         if (ex)
12697                 goto out;
12698         exception_handler = &jmploc;
12699
12700         while ((n = parsecmd(0)) != NODE_EOF) {
12701                 int i;
12702
12703                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12704                 if (n)
12705                         status = i;
12706                 popstackmark(&smark);
12707                 if (evalskip)
12708                         break;
12709         }
12710  out:
12711         popstackmark(&smark);
12712         popfile();
12713         stunalloc(s);
12714
12715         exception_handler = savehandler;
12716         if (ex)
12717                 longjmp(exception_handler->loc, ex);
12718
12719         return status;
12720 }
12721
12722 /*
12723  * The eval command.
12724  */
12725 static int FAST_FUNC
12726 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12727 {
12728         char *p;
12729         char *concat;
12730
12731         if (argv[1]) {
12732                 p = argv[1];
12733                 argv += 2;
12734                 if (argv[0]) {
12735                         STARTSTACKSTR(concat);
12736                         for (;;) {
12737                                 concat = stack_putstr(p, concat);
12738                                 p = *argv++;
12739                                 if (p == NULL)
12740                                         break;
12741                                 STPUTC(' ', concat);
12742                         }
12743                         STPUTC('\0', concat);
12744                         p = grabstackstr(concat);
12745                 }
12746                 return evalstring(p, flags & EV_TESTED);
12747         }
12748         return 0;
12749 }
12750
12751 /*
12752  * Read and execute commands.
12753  * "Top" is nonzero for the top level command loop;
12754  * it turns on prompting if the shell is interactive.
12755  */
12756 static int
12757 cmdloop(int top)
12758 {
12759         union node *n;
12760         struct stackmark smark;
12761         int inter;
12762         int status = 0;
12763         int numeof = 0;
12764
12765         TRACE(("cmdloop(%d) called\n", top));
12766         for (;;) {
12767                 int skip;
12768
12769                 setstackmark(&smark);
12770 #if JOBS
12771                 if (doing_jobctl)
12772                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12773 #endif
12774                 inter = 0;
12775                 if (iflag && top) {
12776                         inter++;
12777                         chkmail();
12778                 }
12779                 n = parsecmd(inter);
12780 #if DEBUG
12781                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12782                         showtree(n);
12783 #endif
12784                 if (n == NODE_EOF) {
12785                         if (!top || numeof >= 50)
12786                                 break;
12787                         if (!stoppedjobs()) {
12788                                 if (!Iflag)
12789                                         break;
12790                                 out2str("\nUse \"exit\" to leave shell.\n");
12791                         }
12792                         numeof++;
12793                 } else if (nflag == 0) {
12794                         int i;
12795
12796                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12797                         job_warning >>= 1;
12798                         numeof = 0;
12799                         i = evaltree(n, 0);
12800                         if (n)
12801                                 status = i;
12802                 }
12803                 popstackmark(&smark);
12804                 skip = evalskip;
12805
12806                 if (skip) {
12807                         evalskip &= ~SKIPFUNC;
12808                         break;
12809                 }
12810         }
12811         return status;
12812 }
12813
12814 /*
12815  * Take commands from a file.  To be compatible we should do a path
12816  * search for the file, which is necessary to find sub-commands.
12817  */
12818 static char *
12819 find_dot_file(char *name)
12820 {
12821         char *fullname;
12822         const char *path = pathval();
12823         struct stat statb;
12824
12825         /* don't try this for absolute or relative paths */
12826         if (strchr(name, '/'))
12827                 return name;
12828
12829         while ((fullname = path_advance(&path, name)) != NULL) {
12830                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12831                         /*
12832                          * Don't bother freeing here, since it will
12833                          * be freed by the caller.
12834                          */
12835                         return fullname;
12836                 }
12837                 if (fullname != name)
12838                         stunalloc(fullname);
12839         }
12840
12841         /* not found in the PATH */
12842         ash_msg_and_raise_error("%s: not found", name);
12843         /* NOTREACHED */
12844 }
12845
12846 static int FAST_FUNC
12847 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12848 {
12849         /* "false; . empty_file; echo $?" should print 0, not 1: */
12850         int status = 0;
12851         char *fullname;
12852         char **argv;
12853         char *args_need_save;
12854         volatile struct shparam saveparam;
12855
12856 //???
12857 //      struct strlist *sp;
12858 //      for (sp = cmdenviron; sp; sp = sp->next)
12859 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12860
12861         nextopt(nullstr); /* handle possible "--" */
12862         argv = argptr;
12863
12864         if (!argv[0]) {
12865                 /* bash says: "bash: .: filename argument required" */
12866                 return 2; /* bash compat */
12867         }
12868
12869         /* This aborts if file isn't found, which is POSIXly correct.
12870          * bash returns exitcode 1 instead.
12871          */
12872         fullname = find_dot_file(argv[0]);
12873         argv++;
12874         args_need_save = argv[0];
12875         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12876                 int argc;
12877                 saveparam = shellparam;
12878                 shellparam.malloced = 0;
12879                 argc = 1;
12880                 while (argv[argc])
12881                         argc++;
12882                 shellparam.nparam = argc;
12883                 shellparam.p = argv;
12884         };
12885
12886         /* This aborts if file can't be opened, which is POSIXly correct.
12887          * bash returns exitcode 1 instead.
12888          */
12889         setinputfile(fullname, INPUT_PUSH_FILE);
12890         commandname = fullname;
12891         status = cmdloop(0);
12892         popfile();
12893
12894         if (args_need_save) {
12895                 freeparam(&shellparam);
12896                 shellparam = saveparam;
12897         };
12898
12899         return status;
12900 }
12901
12902 static int FAST_FUNC
12903 exitcmd(int argc UNUSED_PARAM, char **argv)
12904 {
12905         if (stoppedjobs())
12906                 return 0;
12907         if (argv[1])
12908                 exitstatus = number(argv[1]);
12909         raise_exception(EXEXIT);
12910         /* NOTREACHED */
12911 }
12912
12913 /*
12914  * Read a file containing shell functions.
12915  */
12916 static void
12917 readcmdfile(char *name)
12918 {
12919         setinputfile(name, INPUT_PUSH_FILE);
12920         cmdloop(0);
12921         popfile();
12922 }
12923
12924
12925 /* ============ find_command inplementation */
12926
12927 /*
12928  * Resolve a command name.  If you change this routine, you may have to
12929  * change the shellexec routine as well.
12930  */
12931 static void
12932 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12933 {
12934         struct tblentry *cmdp;
12935         int idx;
12936         int prev;
12937         char *fullname;
12938         struct stat statb;
12939         int e;
12940         int updatetbl;
12941         struct builtincmd *bcmd;
12942
12943         /* If name contains a slash, don't use PATH or hash table */
12944         if (strchr(name, '/') != NULL) {
12945                 entry->u.index = -1;
12946                 if (act & DO_ABS) {
12947                         while (stat(name, &statb) < 0) {
12948 #ifdef SYSV
12949                                 if (errno == EINTR)
12950                                         continue;
12951 #endif
12952                                 entry->cmdtype = CMDUNKNOWN;
12953                                 return;
12954                         }
12955                 }
12956                 entry->cmdtype = CMDNORMAL;
12957                 return;
12958         }
12959
12960 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12961
12962         updatetbl = (path == pathval());
12963         if (!updatetbl) {
12964                 act |= DO_ALTPATH;
12965                 if (strstr(path, "%builtin") != NULL)
12966                         act |= DO_ALTBLTIN;
12967         }
12968
12969         /* If name is in the table, check answer will be ok */
12970         cmdp = cmdlookup(name, 0);
12971         if (cmdp != NULL) {
12972                 int bit;
12973
12974                 switch (cmdp->cmdtype) {
12975                 default:
12976 #if DEBUG
12977                         abort();
12978 #endif
12979                 case CMDNORMAL:
12980                         bit = DO_ALTPATH;
12981                         break;
12982                 case CMDFUNCTION:
12983                         bit = DO_NOFUNC;
12984                         break;
12985                 case CMDBUILTIN:
12986                         bit = DO_ALTBLTIN;
12987                         break;
12988                 }
12989                 if (act & bit) {
12990                         updatetbl = 0;
12991                         cmdp = NULL;
12992                 } else if (cmdp->rehash == 0)
12993                         /* if not invalidated by cd, we're done */
12994                         goto success;
12995         }
12996
12997         /* If %builtin not in path, check for builtin next */
12998         bcmd = find_builtin(name);
12999         if (bcmd) {
13000                 if (IS_BUILTIN_REGULAR(bcmd))
13001                         goto builtin_success;
13002                 if (act & DO_ALTPATH) {
13003                         if (!(act & DO_ALTBLTIN))
13004                                 goto builtin_success;
13005                 } else if (builtinloc <= 0) {
13006                         goto builtin_success;
13007                 }
13008         }
13009
13010 #if ENABLE_FEATURE_SH_STANDALONE
13011         {
13012                 int applet_no = find_applet_by_name(name);
13013                 if (applet_no >= 0) {
13014                         entry->cmdtype = CMDNORMAL;
13015                         entry->u.index = -2 - applet_no;
13016                         return;
13017                 }
13018         }
13019 #endif
13020
13021         /* We have to search path. */
13022         prev = -1;              /* where to start */
13023         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13024                 if (cmdp->cmdtype == CMDBUILTIN)
13025                         prev = builtinloc;
13026                 else
13027                         prev = cmdp->param.index;
13028         }
13029
13030         e = ENOENT;
13031         idx = -1;
13032  loop:
13033         while ((fullname = path_advance(&path, name)) != NULL) {
13034                 stunalloc(fullname);
13035                 /* NB: code below will still use fullname
13036                  * despite it being "unallocated" */
13037                 idx++;
13038                 if (pathopt) {
13039                         if (prefix(pathopt, "builtin")) {
13040                                 if (bcmd)
13041                                         goto builtin_success;
13042                                 continue;
13043                         }
13044                         if ((act & DO_NOFUNC)
13045                          || !prefix(pathopt, "func")
13046                         ) {     /* ignore unimplemented options */
13047                                 continue;
13048                         }
13049                 }
13050                 /* if rehash, don't redo absolute path names */
13051                 if (fullname[0] == '/' && idx <= prev) {
13052                         if (idx < prev)
13053                                 continue;
13054                         TRACE(("searchexec \"%s\": no change\n", name));
13055                         goto success;
13056                 }
13057                 while (stat(fullname, &statb) < 0) {
13058 #ifdef SYSV
13059                         if (errno == EINTR)
13060                                 continue;
13061 #endif
13062                         if (errno != ENOENT && errno != ENOTDIR)
13063                                 e = errno;
13064                         goto loop;
13065                 }
13066                 e = EACCES;     /* if we fail, this will be the error */
13067                 if (!S_ISREG(statb.st_mode))
13068                         continue;
13069                 if (pathopt) {          /* this is a %func directory */
13070                         stalloc(strlen(fullname) + 1);
13071                         /* NB: stalloc will return space pointed by fullname
13072                          * (because we don't have any intervening allocations
13073                          * between stunalloc above and this stalloc) */
13074                         readcmdfile(fullname);
13075                         cmdp = cmdlookup(name, 0);
13076                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13077                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13078                         stunalloc(fullname);
13079                         goto success;
13080                 }
13081                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13082                 if (!updatetbl) {
13083                         entry->cmdtype = CMDNORMAL;
13084                         entry->u.index = idx;
13085                         return;
13086                 }
13087                 INT_OFF;
13088                 cmdp = cmdlookup(name, 1);
13089                 cmdp->cmdtype = CMDNORMAL;
13090                 cmdp->param.index = idx;
13091                 INT_ON;
13092                 goto success;
13093         }
13094
13095         /* We failed.  If there was an entry for this command, delete it */
13096         if (cmdp && updatetbl)
13097                 delete_cmd_entry();
13098         if (act & DO_ERR)
13099                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13100         entry->cmdtype = CMDUNKNOWN;
13101         return;
13102
13103  builtin_success:
13104         if (!updatetbl) {
13105                 entry->cmdtype = CMDBUILTIN;
13106                 entry->u.cmd = bcmd;
13107                 return;
13108         }
13109         INT_OFF;
13110         cmdp = cmdlookup(name, 1);
13111         cmdp->cmdtype = CMDBUILTIN;
13112         cmdp->param.cmd = bcmd;
13113         INT_ON;
13114  success:
13115         cmdp->rehash = 0;
13116         entry->cmdtype = cmdp->cmdtype;
13117         entry->u = cmdp->param;
13118 }
13119
13120
13121 /*
13122  * The trap builtin.
13123  */
13124 static int FAST_FUNC
13125 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13126 {
13127         char *action;
13128         char **ap;
13129         int signo, exitcode;
13130
13131         nextopt(nullstr);
13132         ap = argptr;
13133         if (!*ap) {
13134                 for (signo = 0; signo < NSIG; signo++) {
13135                         char *tr = trap_ptr[signo];
13136                         if (tr) {
13137                                 /* note: bash adds "SIG", but only if invoked
13138                                  * as "bash". If called as "sh", or if set -o posix,
13139                                  * then it prints short signal names.
13140                                  * We are printing short names: */
13141                                 out1fmt("trap -- %s %s\n",
13142                                                 single_quote(tr),
13143                                                 get_signame(signo));
13144                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13145                  * In this case, we will exit very soon, no need to free(). */
13146                                 /* if (trap_ptr != trap && tp[0]) */
13147                                 /*      free(tr); */
13148                         }
13149                 }
13150                 /*
13151                 if (trap_ptr != trap) {
13152                         free(trap_ptr);
13153                         trap_ptr = trap;
13154                 }
13155                 */
13156                 return 0;
13157         }
13158
13159         /* Why the second check?
13160          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13161          * In this case, NUM is signal no, not an action.
13162          */
13163         action = NULL;
13164         if (ap[1] && !is_number(ap[0]))
13165                 action = *ap++;
13166
13167         exitcode = 0;
13168         while (*ap) {
13169                 signo = get_signum(*ap);
13170                 if (signo < 0) {
13171                         /* Mimic bash message exactly */
13172                         ash_msg("%s: invalid signal specification", *ap);
13173                         exitcode = 1;
13174                         goto next;
13175                 }
13176                 INT_OFF;
13177                 if (action) {
13178                         if (LONE_DASH(action))
13179                                 action = NULL;
13180                         else {
13181                                 if (action[0]) /* not NULL and not "" and not "-" */
13182                                         may_have_traps = 1;
13183                                 action = ckstrdup(action);
13184                         }
13185                 }
13186                 free(trap[signo]);
13187                 trap[signo] = action;
13188                 if (signo != 0)
13189                         setsignal(signo);
13190                 INT_ON;
13191  next:
13192                 ap++;
13193         }
13194         return exitcode;
13195 }
13196
13197
13198 /* ============ Builtins */
13199
13200 #if ENABLE_ASH_HELP
13201 static int FAST_FUNC
13202 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13203 {
13204         unsigned col;
13205         unsigned i;
13206
13207         out1fmt(
13208                 "Built-in commands:\n"
13209                 "------------------\n");
13210         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13211                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13212                                         builtintab[i].name + 1);
13213                 if (col > 60) {
13214                         out1fmt("\n");
13215                         col = 0;
13216                 }
13217         }
13218 # if ENABLE_FEATURE_SH_STANDALONE
13219         {
13220                 const char *a = applet_names;
13221                 while (*a) {
13222                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13223                         if (col > 60) {
13224                                 out1fmt("\n");
13225                                 col = 0;
13226                         }
13227                         while (*a++ != '\0')
13228                                 continue;
13229                 }
13230         }
13231 # endif
13232         newline_and_flush(stdout);
13233         return EXIT_SUCCESS;
13234 }
13235 #endif
13236
13237 #if MAX_HISTORY
13238 static int FAST_FUNC
13239 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13240 {
13241         show_history(line_input_state);
13242         return EXIT_SUCCESS;
13243 }
13244 #endif
13245
13246 /*
13247  * The export and readonly commands.
13248  */
13249 static int FAST_FUNC
13250 exportcmd(int argc UNUSED_PARAM, char **argv)
13251 {
13252         struct var *vp;
13253         char *name;
13254         const char *p;
13255         char **aptr;
13256         char opt;
13257         int flag;
13258         int flag_off;
13259
13260         /* "readonly" in bash accepts, but ignores -n.
13261          * We do the same: it saves a conditional in nextopt's param.
13262          */
13263         flag_off = 0;
13264         while ((opt = nextopt("np")) != '\0') {
13265                 if (opt == 'n')
13266                         flag_off = VEXPORT;
13267         }
13268         flag = VEXPORT;
13269         if (argv[0][0] == 'r') {
13270                 flag = VREADONLY;
13271                 flag_off = 0; /* readonly ignores -n */
13272         }
13273         flag_off = ~flag_off;
13274
13275         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13276         {
13277                 aptr = argptr;
13278                 name = *aptr;
13279                 if (name) {
13280                         do {
13281                                 p = strchr(name, '=');
13282                                 if (p != NULL) {
13283                                         p++;
13284                                 } else {
13285                                         vp = *findvar(hashvar(name), name);
13286                                         if (vp) {
13287                                                 vp->flags = ((vp->flags | flag) & flag_off);
13288                                                 continue;
13289                                         }
13290                                 }
13291                                 setvar(name, p, (flag & flag_off));
13292                         } while ((name = *++aptr) != NULL);
13293                         return 0;
13294                 }
13295         }
13296
13297         /* No arguments. Show the list of exported or readonly vars.
13298          * -n is ignored.
13299          */
13300         showvars(argv[0], flag, 0);
13301         return 0;
13302 }
13303
13304 /*
13305  * Delete a function if it exists.
13306  */
13307 static void
13308 unsetfunc(const char *name)
13309 {
13310         struct tblentry *cmdp;
13311
13312         cmdp = cmdlookup(name, 0);
13313         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13314                 delete_cmd_entry();
13315 }
13316
13317 /*
13318  * The unset builtin command.  We unset the function before we unset the
13319  * variable to allow a function to be unset when there is a readonly variable
13320  * with the same name.
13321  */
13322 static int FAST_FUNC
13323 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13324 {
13325         char **ap;
13326         int i;
13327         int flag = 0;
13328
13329         while ((i = nextopt("vf")) != 0) {
13330                 flag = i;
13331         }
13332
13333         for (ap = argptr; *ap; ap++) {
13334                 if (flag != 'f') {
13335                         unsetvar(*ap);
13336                         continue;
13337                 }
13338                 if (flag != 'v')
13339                         unsetfunc(*ap);
13340         }
13341         return 0;
13342 }
13343
13344 static const unsigned char timescmd_str[] ALIGN1 = {
13345         ' ',  offsetof(struct tms, tms_utime),
13346         '\n', offsetof(struct tms, tms_stime),
13347         ' ',  offsetof(struct tms, tms_cutime),
13348         '\n', offsetof(struct tms, tms_cstime),
13349         0
13350 };
13351 static int FAST_FUNC
13352 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13353 {
13354         unsigned long clk_tck, s, t;
13355         const unsigned char *p;
13356         struct tms buf;
13357
13358         clk_tck = bb_clk_tck();
13359         times(&buf);
13360
13361         p = timescmd_str;
13362         do {
13363                 t = *(clock_t *)(((char *) &buf) + p[1]);
13364                 s = t / clk_tck;
13365                 t = t % clk_tck;
13366                 out1fmt("%lum%lu.%03lus%c",
13367                         s / 60, s % 60,
13368                         (t * 1000) / clk_tck,
13369                         p[0]);
13370                 p += 2;
13371         } while (*p);
13372
13373         return 0;
13374 }
13375
13376 #if ENABLE_FEATURE_SH_MATH
13377 /*
13378  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13379  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13380  *
13381  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13382  */
13383 static int FAST_FUNC
13384 letcmd(int argc UNUSED_PARAM, char **argv)
13385 {
13386         arith_t i;
13387
13388         argv++;
13389         if (!*argv)
13390                 ash_msg_and_raise_error("expression expected");
13391         do {
13392                 i = ash_arith(*argv);
13393         } while (*++argv);
13394
13395         return !i;
13396 }
13397 #endif
13398
13399 /*
13400  * The read builtin. Options:
13401  *      -r              Do not interpret '\' specially
13402  *      -s              Turn off echo (tty only)
13403  *      -n NCHARS       Read NCHARS max
13404  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13405  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13406  *      -u FD           Read from given FD instead of fd 0
13407  * This uses unbuffered input, which may be avoidable in some cases.
13408  * TODO: bash also has:
13409  *      -a ARRAY        Read into array[0],[1],etc
13410  *      -d DELIM        End on DELIM char, not newline
13411  *      -e              Use line editing (tty only)
13412  */
13413 static int FAST_FUNC
13414 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13415 {
13416         char *opt_n = NULL;
13417         char *opt_p = NULL;
13418         char *opt_t = NULL;
13419         char *opt_u = NULL;
13420         int read_flags = 0;
13421         const char *r;
13422         int i;
13423
13424         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13425                 switch (i) {
13426                 case 'p':
13427                         opt_p = optionarg;
13428                         break;
13429                 case 'n':
13430                         opt_n = optionarg;
13431                         break;
13432                 case 's':
13433                         read_flags |= BUILTIN_READ_SILENT;
13434                         break;
13435                 case 't':
13436                         opt_t = optionarg;
13437                         break;
13438                 case 'r':
13439                         read_flags |= BUILTIN_READ_RAW;
13440                         break;
13441                 case 'u':
13442                         opt_u = optionarg;
13443                         break;
13444                 default:
13445                         break;
13446                 }
13447         }
13448
13449         /* "read -s" needs to save/restore termios, can't allow ^C
13450          * to jump out of it.
13451          */
13452  again:
13453         INT_OFF;
13454         r = shell_builtin_read(setvar0,
13455                 argptr,
13456                 bltinlookup("IFS"), /* can be NULL */
13457                 read_flags,
13458                 opt_n,
13459                 opt_p,
13460                 opt_t,
13461                 opt_u
13462         );
13463         INT_ON;
13464
13465         if ((uintptr_t)r == 1 && errno == EINTR) {
13466                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13467                  * Correct behavior is to not exit "read"
13468                  */
13469                 if (pending_sig == 0)
13470                         goto again;
13471         }
13472
13473         if ((uintptr_t)r > 1)
13474                 ash_msg_and_raise_error(r);
13475
13476         return (uintptr_t)r;
13477 }
13478
13479 static int FAST_FUNC
13480 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13481 {
13482         static const char permuser[3] ALIGN1 = "ogu";
13483
13484         mode_t mask;
13485         int symbolic_mode = 0;
13486
13487         while (nextopt("S") != '\0') {
13488                 symbolic_mode = 1;
13489         }
13490
13491         INT_OFF;
13492         mask = umask(0);
13493         umask(mask);
13494         INT_ON;
13495
13496         if (*argptr == NULL) {
13497                 if (symbolic_mode) {
13498                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13499                         char *p = buf;
13500                         int i;
13501
13502                         i = 2;
13503                         for (;;) {
13504                                 *p++ = ',';
13505                                 *p++ = permuser[i];
13506                                 *p++ = '=';
13507                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13508                                 if (!(mask & 0400)) *p++ = 'r';
13509                                 if (!(mask & 0200)) *p++ = 'w';
13510                                 if (!(mask & 0100)) *p++ = 'x';
13511                                 mask <<= 3;
13512                                 if (--i < 0)
13513                                         break;
13514                         }
13515                         *p = '\0';
13516                         puts(buf + 1);
13517                 } else {
13518                         out1fmt("%04o\n", mask);
13519                 }
13520         } else {
13521                 char *modestr = *argptr;
13522                 /* numeric umasks are taken as-is */
13523                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13524                 if (!isdigit(modestr[0]))
13525                         mask ^= 0777;
13526                 mask = bb_parse_mode(modestr, mask);
13527                 if ((unsigned)mask > 0777) {
13528                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13529                 }
13530                 if (!isdigit(modestr[0]))
13531                         mask ^= 0777;
13532                 umask(mask);
13533         }
13534         return 0;
13535 }
13536
13537 static int FAST_FUNC
13538 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13539 {
13540         return shell_builtin_ulimit(argv);
13541 }
13542
13543 /* ============ main() and helpers */
13544
13545 /*
13546  * Called to exit the shell.
13547  */
13548 static void
13549 exitshell(void)
13550 {
13551         struct jmploc loc;
13552         char *p;
13553         int status;
13554
13555 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13556         save_history(line_input_state);
13557 #endif
13558         status = exitstatus;
13559         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13560         if (setjmp(loc.loc)) {
13561                 if (exception_type == EXEXIT)
13562                         status = exitstatus;
13563                 goto out;
13564         }
13565         exception_handler = &loc;
13566         p = trap[0];
13567         if (p) {
13568                 trap[0] = NULL;
13569                 evalskip = 0;
13570                 evalstring(p, 0);
13571                 /*free(p); - we'll exit soon */
13572         }
13573  out:
13574         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13575          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13576          */
13577         setjobctl(0);
13578         flush_stdout_stderr();
13579         _exit(status);
13580         /* NOTREACHED */
13581 }
13582
13583 /* Don't inline: conserve stack of caller from having our locals too */
13584 static NOINLINE void
13585 init(void)
13586 {
13587         /* we will never free this */
13588         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13589
13590         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13591         setsignal(SIGCHLD);
13592
13593         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13594          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13595          */
13596         signal(SIGHUP, SIG_DFL);
13597
13598         {
13599                 char **envp;
13600                 const char *p;
13601
13602                 initvar();
13603                 for (envp = environ; envp && *envp; envp++) {
13604                         p = endofname(*envp);
13605                         if (p != *envp && *p == '=') {
13606                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13607                         }
13608                 }
13609
13610                 setvareq((char*)defoptindvar, VTEXTFIXED);
13611
13612                 setvar0("PPID", utoa(getppid()));
13613 #if BASH_SHLVL_VAR
13614                 p = lookupvar("SHLVL");
13615                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13616 #endif
13617 #if BASH_HOSTNAME_VAR
13618                 if (!lookupvar("HOSTNAME")) {
13619                         struct utsname uts;
13620                         uname(&uts);
13621                         setvar0("HOSTNAME", uts.nodename);
13622                 }
13623 #endif
13624                 p = lookupvar("PWD");
13625                 if (p) {
13626                         struct stat st1, st2;
13627                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13628                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13629                         ) {
13630                                 p = NULL;
13631                         }
13632                 }
13633                 setpwd(p, 0);
13634         }
13635 }
13636
13637
13638 //usage:#define ash_trivial_usage
13639 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13640 //usage:#define ash_full_usage "\n\n"
13641 //usage:        "Unix shell interpreter"
13642
13643 /*
13644  * Process the shell command line arguments.
13645  */
13646 static int
13647 procargs(char **argv)
13648 {
13649         int i;
13650         const char *xminusc;
13651         char **xargv;
13652         int login_sh;
13653
13654         xargv = argv;
13655         login_sh = xargv[0] && xargv[0][0] == '-';
13656         arg0 = xargv[0];
13657         /* if (xargv[0]) - mmm, this is always true! */
13658                 xargv++;
13659         for (i = 0; i < NOPTS; i++)
13660                 optlist[i] = 2;
13661         argptr = xargv;
13662         if (options(/*cmdline:*/ 1, &login_sh)) {
13663                 /* it already printed err message */
13664                 raise_exception(EXERROR);
13665         }
13666         xargv = argptr;
13667         xminusc = minusc;
13668         if (*xargv == NULL) {
13669                 if (xminusc)
13670                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13671                 sflag = 1;
13672         }
13673         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13674                 iflag = 1;
13675         if (mflag == 2)
13676                 mflag = iflag;
13677         for (i = 0; i < NOPTS; i++)
13678                 if (optlist[i] == 2)
13679                         optlist[i] = 0;
13680 #if DEBUG == 2
13681         debug = 1;
13682 #endif
13683         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13684         if (xminusc) {
13685                 minusc = *xargv++;
13686                 if (*xargv)
13687                         goto setarg0;
13688         } else if (!sflag) {
13689                 setinputfile(*xargv, 0);
13690  setarg0:
13691                 arg0 = *xargv++;
13692                 commandname = arg0;
13693         }
13694
13695         shellparam.p = xargv;
13696 #if ENABLE_ASH_GETOPTS
13697         shellparam.optind = 1;
13698         shellparam.optoff = -1;
13699 #endif
13700         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13701         while (*xargv) {
13702                 shellparam.nparam++;
13703                 xargv++;
13704         }
13705         optschanged();
13706
13707         return login_sh;
13708 }
13709
13710 /*
13711  * Read /etc/profile, ~/.profile, $ENV.
13712  */
13713 static void
13714 read_profile(const char *name)
13715 {
13716         name = expandstr(name, DQSYNTAX);
13717         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13718                 return;
13719         cmdloop(0);
13720         popfile();
13721 }
13722
13723 /*
13724  * This routine is called when an error or an interrupt occurs in an
13725  * interactive shell and control is returned to the main command loop.
13726  * (In dash, this function is auto-generated by build machinery).
13727  */
13728 static void
13729 reset(void)
13730 {
13731         /* from eval.c: */
13732         evalskip = 0;
13733         loopnest = 0;
13734
13735         /* from expand.c: */
13736         ifsfree();
13737
13738         /* from input.c: */
13739         g_parsefile->left_in_buffer = 0;
13740         g_parsefile->left_in_line = 0;      /* clear input buffer */
13741         popallfiles();
13742
13743         /* from redir.c: */
13744         unwindredir(NULL);
13745
13746         /* from var.c: */
13747         unwindlocalvars(NULL);
13748 }
13749
13750 #if PROFILE
13751 static short profile_buf[16384];
13752 extern int etext();
13753 #endif
13754
13755 /*
13756  * Main routine.  We initialize things, parse the arguments, execute
13757  * profiles if we're a login shell, and then call cmdloop to execute
13758  * commands.  The setjmp call sets up the location to jump to when an
13759  * exception occurs.  When an exception occurs the variable "state"
13760  * is used to figure out how far we had gotten.
13761  */
13762 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13763 int ash_main(int argc UNUSED_PARAM, char **argv)
13764 {
13765         volatile smallint state;
13766         struct jmploc jmploc;
13767         struct stackmark smark;
13768         int login_sh;
13769
13770         /* Initialize global data */
13771         INIT_G_misc();
13772         INIT_G_memstack();
13773         INIT_G_var();
13774 #if ENABLE_ASH_ALIAS
13775         INIT_G_alias();
13776 #endif
13777         INIT_G_cmdtable();
13778
13779 #if PROFILE
13780         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13781 #endif
13782
13783 #if ENABLE_FEATURE_EDITING
13784         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13785 #endif
13786         state = 0;
13787         if (setjmp(jmploc.loc)) {
13788                 smallint e;
13789                 smallint s;
13790
13791                 reset();
13792
13793                 e = exception_type;
13794                 s = state;
13795                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13796                         exitshell();
13797                 }
13798                 if (e == EXINT) {
13799                         newline_and_flush(stderr);
13800                 }
13801
13802                 popstackmark(&smark);
13803                 FORCE_INT_ON; /* enable interrupts */
13804                 if (s == 1)
13805                         goto state1;
13806                 if (s == 2)
13807                         goto state2;
13808                 if (s == 3)
13809                         goto state3;
13810                 goto state4;
13811         }
13812         exception_handler = &jmploc;
13813         rootpid = getpid();
13814
13815         init();
13816         setstackmark(&smark);
13817         login_sh = procargs(argv);
13818 #if DEBUG
13819         TRACE(("Shell args: "));
13820         trace_puts_args(argv);
13821 #endif
13822
13823         if (login_sh) {
13824                 const char *hp;
13825
13826                 state = 1;
13827                 read_profile("/etc/profile");
13828  state1:
13829                 state = 2;
13830                 hp = lookupvar("HOME");
13831                 if (hp)
13832                         read_profile("$HOME/.profile");
13833         }
13834  state2:
13835         state = 3;
13836         if (
13837 #ifndef linux
13838          getuid() == geteuid() && getgid() == getegid() &&
13839 #endif
13840          iflag
13841         ) {
13842                 const char *shinit = lookupvar("ENV");
13843                 if (shinit != NULL && *shinit != '\0')
13844                         read_profile(shinit);
13845         }
13846         popstackmark(&smark);
13847  state3:
13848         state = 4;
13849         if (minusc) {
13850                 /* evalstring pushes parsefile stack.
13851                  * Ensure we don't falsely claim that 0 (stdin)
13852                  * is one of stacked source fds.
13853                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13854                 // if (!sflag) g_parsefile->pf_fd = -1;
13855                 // ^^ not necessary since now we special-case fd 0
13856                 // in save_fd_on_redirect()
13857                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13858         }
13859
13860         if (sflag || minusc == NULL) {
13861 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13862                 if (iflag) {
13863                         const char *hp = lookupvar("HISTFILE");
13864                         if (!hp) {
13865                                 hp = lookupvar("HOME");
13866                                 if (hp) {
13867                                         INT_OFF;
13868                                         hp = concat_path_file(hp, ".ash_history");
13869                                         setvar0("HISTFILE", hp);
13870                                         free((char*)hp);
13871                                         INT_ON;
13872                                         hp = lookupvar("HISTFILE");
13873                                 }
13874                         }
13875                         if (hp)
13876                                 line_input_state->hist_file = hp;
13877 # if ENABLE_FEATURE_SH_HISTFILESIZE
13878                         hp = lookupvar("HISTFILESIZE");
13879                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13880 # endif
13881                 }
13882 #endif
13883  state4: /* XXX ??? - why isn't this before the "if" statement */
13884                 cmdloop(1);
13885         }
13886 #if PROFILE
13887         monitor(0);
13888 #endif
13889 #ifdef GPROF
13890         {
13891                 extern void _mcleanup(void);
13892                 _mcleanup();
13893         }
13894 #endif
13895         TRACE(("End of main reached\n"));
13896         exitshell();
13897         /* NOTREACHED */
13898 }
13899
13900
13901 /*-
13902  * Copyright (c) 1989, 1991, 1993, 1994
13903  *      The Regents of the University of California.  All rights reserved.
13904  *
13905  * This code is derived from software contributed to Berkeley by
13906  * Kenneth Almquist.
13907  *
13908  * Redistribution and use in source and binary forms, with or without
13909  * modification, are permitted provided that the following conditions
13910  * are met:
13911  * 1. Redistributions of source code must retain the above copyright
13912  *    notice, this list of conditions and the following disclaimer.
13913  * 2. Redistributions in binary form must reproduce the above copyright
13914  *    notice, this list of conditions and the following disclaimer in the
13915  *    documentation and/or other materials provided with the distribution.
13916  * 3. Neither the name of the University nor the names of its contributors
13917  *    may be used to endorse or promote products derived from this software
13918  *    without specific prior written permission.
13919  *
13920  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
13921  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13922  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13923  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13924  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13925  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13926  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13927  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13928  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13929  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13930  * SUCH DAMAGE.
13931  */