noexec: consolidate code
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
192
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                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7807                 }
7808                 /* re-exec ourselves with the new arguments */
7809                 execve(bb_busybox_exec_path, argv, envp);
7810                 /* If they called chroot or otherwise made the binary no longer
7811                  * executable, fall through */
7812         }
7813 #endif
7814
7815  repeat:
7816 #ifdef SYSV
7817         do {
7818                 execve(cmd, argv, envp);
7819         } while (errno == EINTR);
7820 #else
7821         execve(cmd, argv, envp);
7822 #endif
7823         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7824                 /* Run "cmd" as a shell script:
7825                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7826                  * "If the execve() function fails with ENOEXEC, the shell
7827                  * shall execute a command equivalent to having a shell invoked
7828                  * with the command name as its first operand,
7829                  * with any remaining arguments passed to the new shell"
7830                  *
7831                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7832                  * just call ourselves.
7833                  *
7834                  * Note that bash reads ~80 chars of the file, and if it sees
7835                  * a zero byte before it sees newline, it doesn't try to
7836                  * interpret it, but fails with "cannot execute binary file"
7837                  * message and exit code 126. For one, this prevents attempts
7838                  * to interpret foreign ELF binaries as shell scripts.
7839                  */
7840                 argv[0] = (char*) cmd;
7841                 cmd = bb_busybox_exec_path;
7842                 /* NB: this is only possible because all callers of shellexec()
7843                  * ensure that the argv[-1] slot exists!
7844                  */
7845                 argv--;
7846                 argv[0] = (char*) "ash";
7847                 goto repeat;
7848         }
7849 }
7850
7851 /*
7852  * Exec a program.  Never returns.  If you change this routine, you may
7853  * have to change the find_command routine as well.
7854  * argv[-1] must exist and be writable! See tryexec() for why.
7855  */
7856 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7857 static void shellexec(char *prog, char **argv, const char *path, int idx)
7858 {
7859         char *cmdname;
7860         int e;
7861         char **envp;
7862         int exerrno;
7863         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7864
7865         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7866         if (strchr(prog, '/') != NULL
7867 #if ENABLE_FEATURE_SH_STANDALONE
7868          || (applet_no = find_applet_by_name(prog)) >= 0
7869 #endif
7870         ) {
7871                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7872                 if (applet_no >= 0) {
7873                         /* We tried execing ourself, but it didn't work.
7874                          * Maybe /proc/self/exe doesn't exist?
7875                          * Try $PATH search.
7876                          */
7877                         goto try_PATH;
7878                 }
7879                 e = errno;
7880         } else {
7881  try_PATH:
7882                 e = ENOENT;
7883                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7884                         if (--idx < 0 && pathopt == NULL) {
7885                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7886                                 if (errno != ENOENT && errno != ENOTDIR)
7887                                         e = errno;
7888                         }
7889                         stunalloc(cmdname);
7890                 }
7891         }
7892
7893         /* Map to POSIX errors */
7894         switch (e) {
7895         case EACCES:
7896                 exerrno = 126;
7897                 break;
7898         case ENOENT:
7899                 exerrno = 127;
7900                 break;
7901         default:
7902                 exerrno = 2;
7903                 break;
7904         }
7905         exitstatus = exerrno;
7906         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7907                 prog, e, suppress_int));
7908         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7909         /* NOTREACHED */
7910 }
7911
7912 static void
7913 printentry(struct tblentry *cmdp)
7914 {
7915         int idx;
7916         const char *path;
7917         char *name;
7918
7919         idx = cmdp->param.index;
7920         path = pathval();
7921         do {
7922                 name = path_advance(&path, cmdp->cmdname);
7923                 stunalloc(name);
7924         } while (--idx >= 0);
7925         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7926 }
7927
7928 /*
7929  * Clear out command entries.  The argument specifies the first entry in
7930  * PATH which has changed.
7931  */
7932 static void
7933 clearcmdentry(int firstchange)
7934 {
7935         struct tblentry **tblp;
7936         struct tblentry **pp;
7937         struct tblentry *cmdp;
7938
7939         INT_OFF;
7940         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7941                 pp = tblp;
7942                 while ((cmdp = *pp) != NULL) {
7943                         if ((cmdp->cmdtype == CMDNORMAL &&
7944                              cmdp->param.index >= firstchange)
7945                          || (cmdp->cmdtype == CMDBUILTIN &&
7946                              builtinloc >= firstchange)
7947                         ) {
7948                                 *pp = cmdp->next;
7949                                 free(cmdp);
7950                         } else {
7951                                 pp = &cmdp->next;
7952                         }
7953                 }
7954         }
7955         INT_ON;
7956 }
7957
7958 /*
7959  * Locate a command in the command hash table.  If "add" is nonzero,
7960  * add the command to the table if it is not already present.  The
7961  * variable "lastcmdentry" is set to point to the address of the link
7962  * pointing to the entry, so that delete_cmd_entry can delete the
7963  * entry.
7964  *
7965  * Interrupts must be off if called with add != 0.
7966  */
7967 static struct tblentry **lastcmdentry;
7968
7969 static struct tblentry *
7970 cmdlookup(const char *name, int add)
7971 {
7972         unsigned int hashval;
7973         const char *p;
7974         struct tblentry *cmdp;
7975         struct tblentry **pp;
7976
7977         p = name;
7978         hashval = (unsigned char)*p << 4;
7979         while (*p)
7980                 hashval += (unsigned char)*p++;
7981         hashval &= 0x7FFF;
7982         pp = &cmdtable[hashval % CMDTABLESIZE];
7983         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7984                 if (strcmp(cmdp->cmdname, name) == 0)
7985                         break;
7986                 pp = &cmdp->next;
7987         }
7988         if (add && cmdp == NULL) {
7989                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7990                                 + strlen(name)
7991                                 /* + 1 - already done because
7992                                  * tblentry::cmdname is char[1] */);
7993                 /*cmdp->next = NULL; - ckzalloc did it */
7994                 cmdp->cmdtype = CMDUNKNOWN;
7995                 strcpy(cmdp->cmdname, name);
7996         }
7997         lastcmdentry = pp;
7998         return cmdp;
7999 }
8000
8001 /*
8002  * Delete the command entry returned on the last lookup.
8003  */
8004 static void
8005 delete_cmd_entry(void)
8006 {
8007         struct tblentry *cmdp;
8008
8009         INT_OFF;
8010         cmdp = *lastcmdentry;
8011         *lastcmdentry = cmdp->next;
8012         if (cmdp->cmdtype == CMDFUNCTION)
8013                 freefunc(cmdp->param.func);
8014         free(cmdp);
8015         INT_ON;
8016 }
8017
8018 /*
8019  * Add a new command entry, replacing any existing command entry for
8020  * the same name - except special builtins.
8021  */
8022 static void
8023 addcmdentry(char *name, struct cmdentry *entry)
8024 {
8025         struct tblentry *cmdp;
8026
8027         cmdp = cmdlookup(name, 1);
8028         if (cmdp->cmdtype == CMDFUNCTION) {
8029                 freefunc(cmdp->param.func);
8030         }
8031         cmdp->cmdtype = entry->cmdtype;
8032         cmdp->param = entry->u;
8033         cmdp->rehash = 0;
8034 }
8035
8036 static int FAST_FUNC
8037 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8038 {
8039         struct tblentry **pp;
8040         struct tblentry *cmdp;
8041         int c;
8042         struct cmdentry entry;
8043         char *name;
8044
8045         if (nextopt("r") != '\0') {
8046                 clearcmdentry(0);
8047                 return 0;
8048         }
8049
8050         if (*argptr == NULL) {
8051                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8052                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8053                                 if (cmdp->cmdtype == CMDNORMAL)
8054                                         printentry(cmdp);
8055                         }
8056                 }
8057                 return 0;
8058         }
8059
8060         c = 0;
8061         while ((name = *argptr) != NULL) {
8062                 cmdp = cmdlookup(name, 0);
8063                 if (cmdp != NULL
8064                  && (cmdp->cmdtype == CMDNORMAL
8065                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8066                 ) {
8067                         delete_cmd_entry();
8068                 }
8069                 find_command(name, &entry, DO_ERR, pathval());
8070                 if (entry.cmdtype == CMDUNKNOWN)
8071                         c = 1;
8072                 argptr++;
8073         }
8074         return c;
8075 }
8076
8077 /*
8078  * Called when a cd is done.  Marks all commands so the next time they
8079  * are executed they will be rehashed.
8080  */
8081 static void
8082 hashcd(void)
8083 {
8084         struct tblentry **pp;
8085         struct tblentry *cmdp;
8086
8087         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8088                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8089                         if (cmdp->cmdtype == CMDNORMAL
8090                          || (cmdp->cmdtype == CMDBUILTIN
8091                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8092                              && builtinloc > 0)
8093                         ) {
8094                                 cmdp->rehash = 1;
8095                         }
8096                 }
8097         }
8098 }
8099
8100 /*
8101  * Fix command hash table when PATH changed.
8102  * Called before PATH is changed.  The argument is the new value of PATH;
8103  * pathval() still returns the old value at this point.
8104  * Called with interrupts off.
8105  */
8106 static void FAST_FUNC
8107 changepath(const char *new)
8108 {
8109         const char *old;
8110         int firstchange;
8111         int idx;
8112         int idx_bltin;
8113
8114         old = pathval();
8115         firstchange = 9999;     /* assume no change */
8116         idx = 0;
8117         idx_bltin = -1;
8118         for (;;) {
8119                 if (*old != *new) {
8120                         firstchange = idx;
8121                         if ((*old == '\0' && *new == ':')
8122                          || (*old == ':' && *new == '\0')
8123                         ) {
8124                                 firstchange++;
8125                         }
8126                         old = new;      /* ignore subsequent differences */
8127                 }
8128                 if (*new == '\0')
8129                         break;
8130                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8131                         idx_bltin = idx;
8132                 if (*new == ':')
8133                         idx++;
8134                 new++;
8135                 old++;
8136         }
8137         if (builtinloc < 0 && idx_bltin >= 0)
8138                 builtinloc = idx_bltin;             /* zap builtins */
8139         if (builtinloc >= 0 && idx_bltin < 0)
8140                 firstchange = 0;
8141         clearcmdentry(firstchange);
8142         builtinloc = idx_bltin;
8143 }
8144 enum {
8145         TEOF,
8146         TNL,
8147         TREDIR,
8148         TWORD,
8149         TSEMI,
8150         TBACKGND,
8151         TAND,
8152         TOR,
8153         TPIPE,
8154         TLP,
8155         TRP,
8156         TENDCASE,
8157         TENDBQUOTE,
8158         TNOT,
8159         TCASE,
8160         TDO,
8161         TDONE,
8162         TELIF,
8163         TELSE,
8164         TESAC,
8165         TFI,
8166         TFOR,
8167 #if BASH_FUNCTION
8168         TFUNCTION,
8169 #endif
8170         TIF,
8171         TIN,
8172         TTHEN,
8173         TUNTIL,
8174         TWHILE,
8175         TBEGIN,
8176         TEND
8177 };
8178 typedef smallint token_id_t;
8179
8180 /* Nth bit indicates if token marks the end of a list */
8181 enum {
8182         tokendlist = 0
8183         /*  0 */ | (1u << TEOF)
8184         /*  1 */ | (0u << TNL)
8185         /*  2 */ | (0u << TREDIR)
8186         /*  3 */ | (0u << TWORD)
8187         /*  4 */ | (0u << TSEMI)
8188         /*  5 */ | (0u << TBACKGND)
8189         /*  6 */ | (0u << TAND)
8190         /*  7 */ | (0u << TOR)
8191         /*  8 */ | (0u << TPIPE)
8192         /*  9 */ | (0u << TLP)
8193         /* 10 */ | (1u << TRP)
8194         /* 11 */ | (1u << TENDCASE)
8195         /* 12 */ | (1u << TENDBQUOTE)
8196         /* 13 */ | (0u << TNOT)
8197         /* 14 */ | (0u << TCASE)
8198         /* 15 */ | (1u << TDO)
8199         /* 16 */ | (1u << TDONE)
8200         /* 17 */ | (1u << TELIF)
8201         /* 18 */ | (1u << TELSE)
8202         /* 19 */ | (1u << TESAC)
8203         /* 20 */ | (1u << TFI)
8204         /* 21 */ | (0u << TFOR)
8205 #if BASH_FUNCTION
8206         /* 22 */ | (0u << TFUNCTION)
8207 #endif
8208         /* 23 */ | (0u << TIF)
8209         /* 24 */ | (0u << TIN)
8210         /* 25 */ | (1u << TTHEN)
8211         /* 26 */ | (0u << TUNTIL)
8212         /* 27 */ | (0u << TWHILE)
8213         /* 28 */ | (0u << TBEGIN)
8214         /* 29 */ | (1u << TEND)
8215         , /* thus far 29 bits used */
8216 };
8217
8218 static const char *const tokname_array[] = {
8219         "end of file",
8220         "newline",
8221         "redirection",
8222         "word",
8223         ";",
8224         "&",
8225         "&&",
8226         "||",
8227         "|",
8228         "(",
8229         ")",
8230         ";;",
8231         "`",
8232 #define KWDOFFSET 13
8233         /* the following are keywords */
8234         "!",
8235         "case",
8236         "do",
8237         "done",
8238         "elif",
8239         "else",
8240         "esac",
8241         "fi",
8242         "for",
8243 #if BASH_FUNCTION
8244         "function",
8245 #endif
8246         "if",
8247         "in",
8248         "then",
8249         "until",
8250         "while",
8251         "{",
8252         "}",
8253 };
8254
8255 /* Wrapper around strcmp for qsort/bsearch/... */
8256 static int
8257 pstrcmp(const void *a, const void *b)
8258 {
8259         return strcmp((char*)a, *(char**)b);
8260 }
8261
8262 static const char *const *
8263 findkwd(const char *s)
8264 {
8265         return bsearch(s, tokname_array + KWDOFFSET,
8266                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8267                         sizeof(tokname_array[0]), pstrcmp);
8268 }
8269
8270 /*
8271  * Locate and print what a word is...
8272  */
8273 static int
8274 describe_command(char *command, const char *path, int describe_command_verbose)
8275 {
8276         struct cmdentry entry;
8277 #if ENABLE_ASH_ALIAS
8278         const struct alias *ap;
8279 #endif
8280
8281         path = path ? path : pathval();
8282
8283         if (describe_command_verbose) {
8284                 out1str(command);
8285         }
8286
8287         /* First look at the keywords */
8288         if (findkwd(command)) {
8289                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8290                 goto out;
8291         }
8292
8293 #if ENABLE_ASH_ALIAS
8294         /* Then look at the aliases */
8295         ap = lookupalias(command, 0);
8296         if (ap != NULL) {
8297                 if (!describe_command_verbose) {
8298                         out1str("alias ");
8299                         printalias(ap);
8300                         return 0;
8301                 }
8302                 out1fmt(" is an alias for %s", ap->val);
8303                 goto out;
8304         }
8305 #endif
8306         /* Brute force */
8307         find_command(command, &entry, DO_ABS, path);
8308
8309         switch (entry.cmdtype) {
8310         case CMDNORMAL: {
8311                 int j = entry.u.index;
8312                 char *p;
8313                 if (j < 0) {
8314                         p = command;
8315                 } else {
8316                         do {
8317                                 p = path_advance(&path, command);
8318                                 stunalloc(p);
8319                         } while (--j >= 0);
8320                 }
8321                 if (describe_command_verbose) {
8322                         out1fmt(" is %s", p);
8323                 } else {
8324                         out1str(p);
8325                 }
8326                 break;
8327         }
8328
8329         case CMDFUNCTION:
8330                 if (describe_command_verbose) {
8331                         out1str(" is a shell function");
8332                 } else {
8333                         out1str(command);
8334                 }
8335                 break;
8336
8337         case CMDBUILTIN:
8338                 if (describe_command_verbose) {
8339                         out1fmt(" is a %sshell builtin",
8340                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8341                                         "special " : nullstr
8342                         );
8343                 } else {
8344                         out1str(command);
8345                 }
8346                 break;
8347
8348         default:
8349                 if (describe_command_verbose) {
8350                         out1str(": not found\n");
8351                 }
8352                 return 127;
8353         }
8354  out:
8355         out1str("\n");
8356         return 0;
8357 }
8358
8359 static int FAST_FUNC
8360 typecmd(int argc UNUSED_PARAM, char **argv)
8361 {
8362         int i = 1;
8363         int err = 0;
8364         int verbose = 1;
8365
8366         /* type -p ... ? (we don't bother checking for 'p') */
8367         if (argv[1] && argv[1][0] == '-') {
8368                 i++;
8369                 verbose = 0;
8370         }
8371         while (argv[i]) {
8372                 err |= describe_command(argv[i++], NULL, verbose);
8373         }
8374         return err;
8375 }
8376
8377 #if ENABLE_ASH_CMDCMD
8378 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8379 static char **
8380 parse_command_args(char **argv, const char **path)
8381 {
8382         char *cp, c;
8383
8384         for (;;) {
8385                 cp = *++argv;
8386                 if (!cp)
8387                         return NULL;
8388                 if (*cp++ != '-')
8389                         break;
8390                 c = *cp++;
8391                 if (!c)
8392                         break;
8393                 if (c == '-' && !*cp) {
8394                         if (!*++argv)
8395                                 return NULL;
8396                         break;
8397                 }
8398                 do {
8399                         switch (c) {
8400                         case 'p':
8401                                 *path = bb_default_path;
8402                                 break;
8403                         default:
8404                                 /* run 'typecmd' for other options */
8405                                 return NULL;
8406                         }
8407                         c = *cp++;
8408                 } while (c);
8409         }
8410         return argv;
8411 }
8412
8413 static int FAST_FUNC
8414 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8415 {
8416         char *cmd;
8417         int c;
8418         enum {
8419                 VERIFY_BRIEF = 1,
8420                 VERIFY_VERBOSE = 2,
8421         } verify = 0;
8422         const char *path = NULL;
8423
8424         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8425          * never reaches this function.
8426          */
8427
8428         while ((c = nextopt("pvV")) != '\0')
8429                 if (c == 'V')
8430                         verify |= VERIFY_VERBOSE;
8431                 else if (c == 'v')
8432                         /*verify |= VERIFY_BRIEF*/;
8433 #if DEBUG
8434                 else if (c != 'p')
8435                         abort();
8436 #endif
8437                 else
8438                         path = bb_default_path;
8439
8440         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8441         cmd = *argptr;
8442         if (/*verify && */ cmd)
8443                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8444
8445         return 0;
8446 }
8447 #endif
8448
8449
8450 /*static int funcblocksize;     // size of structures in function */
8451 /*static int funcstringsize;    // size of strings in node */
8452 static void *funcblock;         /* block to allocate function from */
8453 static char *funcstring_end;    /* end of block to allocate strings from */
8454
8455 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8456         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8457         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8458         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8459         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8460         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8461         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8462         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8463         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8464         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8465         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8466         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8467         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8468         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8469         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8470         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8471         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8472         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8473 #if BASH_REDIR_OUTPUT
8474         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8475 #endif
8476         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8477         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8478         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8479         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8480         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8481         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8482         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8483         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8484         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8485 };
8486
8487 static int calcsize(int funcblocksize, union node *n);
8488
8489 static int
8490 sizenodelist(int funcblocksize, struct nodelist *lp)
8491 {
8492         while (lp) {
8493                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8494                 funcblocksize = calcsize(funcblocksize, lp->n);
8495                 lp = lp->next;
8496         }
8497         return funcblocksize;
8498 }
8499
8500 static int
8501 calcsize(int funcblocksize, union node *n)
8502 {
8503         if (n == NULL)
8504                 return funcblocksize;
8505         funcblocksize += nodesize[n->type];
8506         switch (n->type) {
8507         case NCMD:
8508                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8509                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8510                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8511                 break;
8512         case NPIPE:
8513                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8514                 break;
8515         case NREDIR:
8516         case NBACKGND:
8517         case NSUBSHELL:
8518                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8519                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8520                 break;
8521         case NAND:
8522         case NOR:
8523         case NSEMI:
8524         case NWHILE:
8525         case NUNTIL:
8526                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8527                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8528                 break;
8529         case NIF:
8530                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8531                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8532                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8533                 break;
8534         case NFOR:
8535                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8536                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8537                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8538                 break;
8539         case NCASE:
8540                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8541                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8542                 break;
8543         case NCLIST:
8544                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8545                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8546                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8547                 break;
8548         case NDEFUN:
8549         case NARG:
8550                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8551                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8552                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8553                 break;
8554         case NTO:
8555 #if BASH_REDIR_OUTPUT
8556         case NTO2:
8557 #endif
8558         case NCLOBBER:
8559         case NFROM:
8560         case NFROMTO:
8561         case NAPPEND:
8562                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8563                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8564                 break;
8565         case NTOFD:
8566         case NFROMFD:
8567                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8568                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8569         break;
8570         case NHERE:
8571         case NXHERE:
8572                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8573                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8574                 break;
8575         case NNOT:
8576                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8577                 break;
8578         };
8579         return funcblocksize;
8580 }
8581
8582 static char *
8583 nodeckstrdup(char *s)
8584 {
8585         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8586         return strcpy(funcstring_end, s);
8587 }
8588
8589 static union node *copynode(union node *);
8590
8591 static struct nodelist *
8592 copynodelist(struct nodelist *lp)
8593 {
8594         struct nodelist *start;
8595         struct nodelist **lpp;
8596
8597         lpp = &start;
8598         while (lp) {
8599                 *lpp = funcblock;
8600                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8601                 (*lpp)->n = copynode(lp->n);
8602                 lp = lp->next;
8603                 lpp = &(*lpp)->next;
8604         }
8605         *lpp = NULL;
8606         return start;
8607 }
8608
8609 static union node *
8610 copynode(union node *n)
8611 {
8612         union node *new;
8613
8614         if (n == NULL)
8615                 return NULL;
8616         new = funcblock;
8617         funcblock = (char *) funcblock + nodesize[n->type];
8618
8619         switch (n->type) {
8620         case NCMD:
8621                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8622                 new->ncmd.args = copynode(n->ncmd.args);
8623                 new->ncmd.assign = copynode(n->ncmd.assign);
8624                 break;
8625         case NPIPE:
8626                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8627                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8628                 break;
8629         case NREDIR:
8630         case NBACKGND:
8631         case NSUBSHELL:
8632                 new->nredir.redirect = copynode(n->nredir.redirect);
8633                 new->nredir.n = copynode(n->nredir.n);
8634                 break;
8635         case NAND:
8636         case NOR:
8637         case NSEMI:
8638         case NWHILE:
8639         case NUNTIL:
8640                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8641                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8642                 break;
8643         case NIF:
8644                 new->nif.elsepart = copynode(n->nif.elsepart);
8645                 new->nif.ifpart = copynode(n->nif.ifpart);
8646                 new->nif.test = copynode(n->nif.test);
8647                 break;
8648         case NFOR:
8649                 new->nfor.var = nodeckstrdup(n->nfor.var);
8650                 new->nfor.body = copynode(n->nfor.body);
8651                 new->nfor.args = copynode(n->nfor.args);
8652                 break;
8653         case NCASE:
8654                 new->ncase.cases = copynode(n->ncase.cases);
8655                 new->ncase.expr = copynode(n->ncase.expr);
8656                 break;
8657         case NCLIST:
8658                 new->nclist.body = copynode(n->nclist.body);
8659                 new->nclist.pattern = copynode(n->nclist.pattern);
8660                 new->nclist.next = copynode(n->nclist.next);
8661                 break;
8662         case NDEFUN:
8663         case NARG:
8664                 new->narg.backquote = copynodelist(n->narg.backquote);
8665                 new->narg.text = nodeckstrdup(n->narg.text);
8666                 new->narg.next = copynode(n->narg.next);
8667                 break;
8668         case NTO:
8669 #if BASH_REDIR_OUTPUT
8670         case NTO2:
8671 #endif
8672         case NCLOBBER:
8673         case NFROM:
8674         case NFROMTO:
8675         case NAPPEND:
8676                 new->nfile.fname = copynode(n->nfile.fname);
8677                 new->nfile.fd = n->nfile.fd;
8678                 new->nfile.next = copynode(n->nfile.next);
8679                 break;
8680         case NTOFD:
8681         case NFROMFD:
8682                 new->ndup.vname = copynode(n->ndup.vname);
8683                 new->ndup.dupfd = n->ndup.dupfd;
8684                 new->ndup.fd = n->ndup.fd;
8685                 new->ndup.next = copynode(n->ndup.next);
8686                 break;
8687         case NHERE:
8688         case NXHERE:
8689                 new->nhere.doc = copynode(n->nhere.doc);
8690                 new->nhere.fd = n->nhere.fd;
8691                 new->nhere.next = copynode(n->nhere.next);
8692                 break;
8693         case NNOT:
8694                 new->nnot.com = copynode(n->nnot.com);
8695                 break;
8696         };
8697         new->type = n->type;
8698         return new;
8699 }
8700
8701 /*
8702  * Make a copy of a parse tree.
8703  */
8704 static struct funcnode *
8705 copyfunc(union node *n)
8706 {
8707         struct funcnode *f;
8708         size_t blocksize;
8709
8710         /*funcstringsize = 0;*/
8711         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8712         f = ckzalloc(blocksize /* + funcstringsize */);
8713         funcblock = (char *) f + offsetof(struct funcnode, n);
8714         funcstring_end = (char *) f + blocksize;
8715         copynode(n);
8716         /* f->count = 0; - ckzalloc did it */
8717         return f;
8718 }
8719
8720 /*
8721  * Define a shell function.
8722  */
8723 static void
8724 defun(union node *func)
8725 {
8726         struct cmdentry entry;
8727
8728         INT_OFF;
8729         entry.cmdtype = CMDFUNCTION;
8730         entry.u.func = copyfunc(func);
8731         addcmdentry(func->narg.text, &entry);
8732         INT_ON;
8733 }
8734
8735 /* Reasons for skipping commands (see comment on breakcmd routine) */
8736 #define SKIPBREAK      (1 << 0)
8737 #define SKIPCONT       (1 << 1)
8738 #define SKIPFUNC       (1 << 2)
8739 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8740 static int skipcount;           /* number of levels to skip */
8741 static int funcnest;            /* depth of function calls */
8742 static int loopnest;            /* current loop nesting level */
8743
8744 /* Forward decl way out to parsing code - dotrap needs it */
8745 static int evalstring(char *s, int flags);
8746
8747 /* Called to execute a trap.
8748  * Single callsite - at the end of evaltree().
8749  * If we return non-zero, evaltree raises EXEXIT exception.
8750  *
8751  * Perhaps we should avoid entering new trap handlers
8752  * while we are executing a trap handler. [is it a TODO?]
8753  */
8754 static void
8755 dotrap(void)
8756 {
8757         uint8_t *g;
8758         int sig;
8759         uint8_t last_status;
8760
8761         if (!pending_sig)
8762                 return;
8763
8764         last_status = exitstatus;
8765         pending_sig = 0;
8766         barrier();
8767
8768         TRACE(("dotrap entered\n"));
8769         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8770                 char *p;
8771
8772                 if (!*g)
8773                         continue;
8774
8775                 if (evalskip) {
8776                         pending_sig = sig;
8777                         break;
8778                 }
8779
8780                 p = trap[sig];
8781                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8782                  * don't upset it by resetting gotsig[SIGINT-1] */
8783                 if (sig == SIGINT && !p)
8784                         continue;
8785
8786                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8787                 *g = 0;
8788                 if (!p)
8789                         continue;
8790                 evalstring(p, 0);
8791         }
8792         exitstatus = last_status;
8793         TRACE(("dotrap returns\n"));
8794 }
8795
8796 /* forward declarations - evaluation is fairly recursive business... */
8797 static int evalloop(union node *, int);
8798 static int evalfor(union node *, int);
8799 static int evalcase(union node *, int);
8800 static int evalsubshell(union node *, int);
8801 static void expredir(union node *);
8802 static int evalpipe(union node *, int);
8803 static int evalcommand(union node *, int);
8804 static int evalbltin(const struct builtincmd *, int, char **, int);
8805 static void prehash(union node *);
8806
8807 /*
8808  * Evaluate a parse tree.  The value is left in the global variable
8809  * exitstatus.
8810  */
8811 static int
8812 evaltree(union node *n, int flags)
8813 {
8814         int checkexit = 0;
8815         int (*evalfn)(union node *, int);
8816         int status = 0;
8817
8818         if (n == NULL) {
8819                 TRACE(("evaltree(NULL) called\n"));
8820                 goto out;
8821         }
8822         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8823
8824         dotrap();
8825
8826         switch (n->type) {
8827         default:
8828 #if DEBUG
8829                 out1fmt("Node type = %d\n", n->type);
8830                 fflush_all();
8831                 break;
8832 #endif
8833         case NNOT:
8834                 status = !evaltree(n->nnot.com, EV_TESTED);
8835                 goto setstatus;
8836         case NREDIR:
8837                 expredir(n->nredir.redirect);
8838                 pushredir(n->nredir.redirect);
8839                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8840                 if (!status) {
8841                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8842                 }
8843                 if (n->nredir.redirect)
8844                         popredir(/*drop:*/ 0);
8845                 goto setstatus;
8846         case NCMD:
8847                 evalfn = evalcommand;
8848  checkexit:
8849                 if (eflag && !(flags & EV_TESTED))
8850                         checkexit = ~0;
8851                 goto calleval;
8852         case NFOR:
8853                 evalfn = evalfor;
8854                 goto calleval;
8855         case NWHILE:
8856         case NUNTIL:
8857                 evalfn = evalloop;
8858                 goto calleval;
8859         case NSUBSHELL:
8860         case NBACKGND:
8861                 evalfn = evalsubshell;
8862                 goto checkexit;
8863         case NPIPE:
8864                 evalfn = evalpipe;
8865                 goto checkexit;
8866         case NCASE:
8867                 evalfn = evalcase;
8868                 goto calleval;
8869         case NAND:
8870         case NOR:
8871         case NSEMI: {
8872
8873 #if NAND + 1 != NOR
8874 #error NAND + 1 != NOR
8875 #endif
8876 #if NOR + 1 != NSEMI
8877 #error NOR + 1 != NSEMI
8878 #endif
8879                 unsigned is_or = n->type - NAND;
8880                 status = evaltree(
8881                         n->nbinary.ch1,
8882                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8883                 );
8884                 if ((!status) == is_or || evalskip)
8885                         break;
8886                 n = n->nbinary.ch2;
8887  evaln:
8888                 evalfn = evaltree;
8889  calleval:
8890                 status = evalfn(n, flags);
8891                 goto setstatus;
8892         }
8893         case NIF:
8894                 status = evaltree(n->nif.test, EV_TESTED);
8895                 if (evalskip)
8896                         break;
8897                 if (!status) {
8898                         n = n->nif.ifpart;
8899                         goto evaln;
8900                 }
8901                 if (n->nif.elsepart) {
8902                         n = n->nif.elsepart;
8903                         goto evaln;
8904                 }
8905                 status = 0;
8906                 goto setstatus;
8907         case NDEFUN:
8908                 defun(n);
8909                 /* Not necessary. To test it:
8910                  * "false; f() { qwerty; }; echo $?" should print 0.
8911                  */
8912                 /* status = 0; */
8913  setstatus:
8914                 exitstatus = status;
8915                 break;
8916         }
8917  out:
8918         /* Order of checks below is important:
8919          * signal handlers trigger before exit caused by "set -e".
8920          */
8921         dotrap();
8922
8923         if (checkexit & status)
8924                 raise_exception(EXEXIT);
8925         if (flags & EV_EXIT)
8926                 raise_exception(EXEXIT);
8927
8928         TRACE(("leaving evaltree (no interrupts)\n"));
8929         return exitstatus;
8930 }
8931
8932 static int
8933 skiploop(void)
8934 {
8935         int skip = evalskip;
8936
8937         switch (skip) {
8938         case 0:
8939                 break;
8940         case SKIPBREAK:
8941         case SKIPCONT:
8942                 if (--skipcount <= 0) {
8943                         evalskip = 0;
8944                         break;
8945                 }
8946                 skip = SKIPBREAK;
8947                 break;
8948         }
8949         return skip;
8950 }
8951
8952 static int
8953 evalloop(union node *n, int flags)
8954 {
8955         int skip;
8956         int status;
8957
8958         loopnest++;
8959         status = 0;
8960         flags &= EV_TESTED;
8961         do {
8962                 int i;
8963
8964                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8965                 skip = skiploop();
8966                 if (skip == SKIPFUNC)
8967                         status = i;
8968                 if (skip)
8969                         continue;
8970                 if (n->type != NWHILE)
8971                         i = !i;
8972                 if (i != 0)
8973                         break;
8974                 status = evaltree(n->nbinary.ch2, flags);
8975                 skip = skiploop();
8976         } while (!(skip & ~SKIPCONT));
8977         loopnest--;
8978
8979         return status;
8980 }
8981
8982 static int
8983 evalfor(union node *n, int flags)
8984 {
8985         struct arglist arglist;
8986         union node *argp;
8987         struct strlist *sp;
8988         struct stackmark smark;
8989         int status = 0;
8990
8991         setstackmark(&smark);
8992         arglist.list = NULL;
8993         arglist.lastp = &arglist.list;
8994         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8995                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8996         }
8997         *arglist.lastp = NULL;
8998
8999         loopnest++;
9000         flags &= EV_TESTED;
9001         for (sp = arglist.list; sp; sp = sp->next) {
9002                 setvar0(n->nfor.var, sp->text);
9003                 status = evaltree(n->nfor.body, flags);
9004                 if (skiploop() & ~SKIPCONT)
9005                         break;
9006         }
9007         loopnest--;
9008         popstackmark(&smark);
9009
9010         return status;
9011 }
9012
9013 static int
9014 evalcase(union node *n, int flags)
9015 {
9016         union node *cp;
9017         union node *patp;
9018         struct arglist arglist;
9019         struct stackmark smark;
9020         int status = 0;
9021
9022         setstackmark(&smark);
9023         arglist.list = NULL;
9024         arglist.lastp = &arglist.list;
9025         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9026         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9027                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9028                         if (casematch(patp, arglist.list->text)) {
9029                                 /* Ensure body is non-empty as otherwise
9030                                  * EV_EXIT may prevent us from setting the
9031                                  * exit status.
9032                                  */
9033                                 if (evalskip == 0 && cp->nclist.body) {
9034                                         status = evaltree(cp->nclist.body, flags);
9035                                 }
9036                                 goto out;
9037                         }
9038                 }
9039         }
9040  out:
9041         popstackmark(&smark);
9042
9043         return status;
9044 }
9045
9046 /*
9047  * Kick off a subshell to evaluate a tree.
9048  */
9049 static int
9050 evalsubshell(union node *n, int flags)
9051 {
9052         struct job *jp;
9053         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9054         int status;
9055
9056         expredir(n->nredir.redirect);
9057         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9058                 goto nofork;
9059         INT_OFF;
9060         if (backgnd == FORK_FG)
9061                 get_tty_state();
9062         jp = makejob(/*n,*/ 1);
9063         if (forkshell(jp, n, backgnd) == 0) {
9064                 /* child */
9065                 INT_ON;
9066                 flags |= EV_EXIT;
9067                 if (backgnd)
9068                         flags &= ~EV_TESTED;
9069  nofork:
9070                 redirect(n->nredir.redirect, 0);
9071                 evaltreenr(n->nredir.n, flags);
9072                 /* never returns */
9073         }
9074         /* parent */
9075         status = 0;
9076         if (backgnd == FORK_FG)
9077                 status = waitforjob(jp);
9078         INT_ON;
9079         return status;
9080 }
9081
9082 /*
9083  * Compute the names of the files in a redirection list.
9084  */
9085 static void fixredir(union node *, const char *, int);
9086 static void
9087 expredir(union node *n)
9088 {
9089         union node *redir;
9090
9091         for (redir = n; redir; redir = redir->nfile.next) {
9092                 struct arglist fn;
9093
9094                 fn.list = NULL;
9095                 fn.lastp = &fn.list;
9096                 switch (redir->type) {
9097                 case NFROMTO:
9098                 case NFROM:
9099                 case NTO:
9100 #if BASH_REDIR_OUTPUT
9101                 case NTO2:
9102 #endif
9103                 case NCLOBBER:
9104                 case NAPPEND:
9105                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9106                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9107 #if BASH_REDIR_OUTPUT
9108  store_expfname:
9109 #endif
9110 #if 0
9111 // By the design of stack allocator, the loop of this kind:
9112 //      while true; do while true; do break; done </dev/null; done
9113 // will look like a memory leak: ash plans to free expfname's
9114 // of "/dev/null" as soon as it finishes running the loop
9115 // (in this case, never).
9116 // This "fix" is wrong:
9117                         if (redir->nfile.expfname)
9118                                 stunalloc(redir->nfile.expfname);
9119 // It results in corrupted state of stacked allocations.
9120 #endif
9121                         redir->nfile.expfname = fn.list->text;
9122                         break;
9123                 case NFROMFD:
9124                 case NTOFD: /* >& */
9125                         if (redir->ndup.vname) {
9126                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9127                                 if (fn.list == NULL)
9128                                         ash_msg_and_raise_error("redir error");
9129 #if BASH_REDIR_OUTPUT
9130 //FIXME: we used expandarg with different args!
9131                                 if (!isdigit_str9(fn.list->text)) {
9132                                         /* >&file, not >&fd */
9133                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9134                                                 ash_msg_and_raise_error("redir error");
9135                                         redir->type = NTO2;
9136                                         goto store_expfname;
9137                                 }
9138 #endif
9139                                 fixredir(redir, fn.list->text, 1);
9140                         }
9141                         break;
9142                 }
9143         }
9144 }
9145
9146 /*
9147  * Evaluate a pipeline.  All the processes in the pipeline are children
9148  * of the process creating the pipeline.  (This differs from some versions
9149  * of the shell, which make the last process in a pipeline the parent
9150  * of all the rest.)
9151  */
9152 static int
9153 evalpipe(union node *n, int flags)
9154 {
9155         struct job *jp;
9156         struct nodelist *lp;
9157         int pipelen;
9158         int prevfd;
9159         int pip[2];
9160         int status = 0;
9161
9162         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9163         pipelen = 0;
9164         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9165                 pipelen++;
9166         flags |= EV_EXIT;
9167         INT_OFF;
9168         if (n->npipe.pipe_backgnd == 0)
9169                 get_tty_state();
9170         jp = makejob(/*n,*/ pipelen);
9171         prevfd = -1;
9172         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9173                 prehash(lp->n);
9174                 pip[1] = -1;
9175                 if (lp->next) {
9176                         if (pipe(pip) < 0) {
9177                                 close(prevfd);
9178                                 ash_msg_and_raise_error("pipe call failed");
9179                         }
9180                 }
9181                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9182                         /* child */
9183                         INT_ON;
9184                         if (pip[1] >= 0) {
9185                                 close(pip[0]);
9186                         }
9187                         if (prevfd > 0) {
9188                                 dup2(prevfd, 0);
9189                                 close(prevfd);
9190                         }
9191                         if (pip[1] > 1) {
9192                                 dup2(pip[1], 1);
9193                                 close(pip[1]);
9194                         }
9195                         evaltreenr(lp->n, flags);
9196                         /* never returns */
9197                 }
9198                 /* parent */
9199                 if (prevfd >= 0)
9200                         close(prevfd);
9201                 prevfd = pip[0];
9202                 /* Don't want to trigger debugging */
9203                 if (pip[1] != -1)
9204                         close(pip[1]);
9205         }
9206         if (n->npipe.pipe_backgnd == 0) {
9207                 status = waitforjob(jp);
9208                 TRACE(("evalpipe:  job done exit status %d\n", status));
9209         }
9210         INT_ON;
9211
9212         return status;
9213 }
9214
9215 /*
9216  * Controls whether the shell is interactive or not.
9217  */
9218 static void
9219 setinteractive(int on)
9220 {
9221         static smallint is_interactive;
9222
9223         if (++on == is_interactive)
9224                 return;
9225         is_interactive = on;
9226         setsignal(SIGINT);
9227         setsignal(SIGQUIT);
9228         setsignal(SIGTERM);
9229 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9230         if (is_interactive > 1) {
9231                 /* Looks like they want an interactive shell */
9232                 static smallint did_banner;
9233
9234                 if (!did_banner) {
9235                         /* note: ash and hush share this string */
9236                         out1fmt("\n\n%s %s\n"
9237                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9238                                 "\n",
9239                                 bb_banner,
9240                                 "built-in shell (ash)"
9241                         );
9242                         did_banner = 1;
9243                 }
9244         }
9245 #endif
9246 }
9247
9248 static void
9249 optschanged(void)
9250 {
9251 #if DEBUG
9252         opentrace();
9253 #endif
9254         setinteractive(iflag);
9255         setjobctl(mflag);
9256 #if ENABLE_FEATURE_EDITING_VI
9257         if (viflag)
9258                 line_input_state->flags |= VI_MODE;
9259         else
9260                 line_input_state->flags &= ~VI_MODE;
9261 #else
9262         viflag = 0; /* forcibly keep the option off */
9263 #endif
9264 }
9265
9266 struct localvar_list {
9267         struct localvar_list *next;
9268         struct localvar *lv;
9269 };
9270
9271 static struct localvar_list *localvar_stack;
9272
9273 /*
9274  * Called after a function returns.
9275  * Interrupts must be off.
9276  */
9277 static void
9278 poplocalvars(int keep)
9279 {
9280         struct localvar_list *ll;
9281         struct localvar *lvp, *next;
9282         struct var *vp;
9283
9284         INT_OFF;
9285         ll = localvar_stack;
9286         localvar_stack = ll->next;
9287
9288         next = ll->lv;
9289         free(ll);
9290
9291         while ((lvp = next) != NULL) {
9292                 next = lvp->next;
9293                 vp = lvp->vp;
9294                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9295                 if (keep) {
9296                         int bits = VSTRFIXED;
9297
9298                         if (lvp->flags != VUNSET) {
9299                                 if (vp->var_text == lvp->text)
9300                                         bits |= VTEXTFIXED;
9301                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9302                                         free((char*)lvp->text);
9303                         }
9304
9305                         vp->flags &= ~bits;
9306                         vp->flags |= (lvp->flags & bits);
9307
9308                         if ((vp->flags &
9309                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9310                                 unsetvar(vp->var_text);
9311                 } else if (vp == NULL) {        /* $- saved */
9312                         memcpy(optlist, lvp->text, sizeof(optlist));
9313                         free((char*)lvp->text);
9314                         optschanged();
9315                 } else if (lvp->flags == VUNSET) {
9316                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9317                         unsetvar(vp->var_text);
9318                 } else {
9319                         if (vp->var_func)
9320                                 vp->var_func(var_end(lvp->text));
9321                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9322                                 free((char*)vp->var_text);
9323                         vp->flags = lvp->flags;
9324                         vp->var_text = lvp->text;
9325                 }
9326                 free(lvp);
9327         }
9328         INT_ON;
9329 }
9330
9331 /*
9332  * Create a new localvar environment.
9333  */
9334 static struct localvar_list *
9335 pushlocalvars(void)
9336 {
9337         struct localvar_list *ll;
9338
9339         INT_OFF;
9340         ll = ckzalloc(sizeof(*ll));
9341         /*ll->lv = NULL; - zalloc did it */
9342         ll->next = localvar_stack;
9343         localvar_stack = ll;
9344         INT_ON;
9345
9346         return ll->next;
9347 }
9348
9349 static void
9350 unwindlocalvars(struct localvar_list *stop)
9351 {
9352         while (localvar_stack != stop)
9353                 poplocalvars(0);
9354 }
9355
9356 static int
9357 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9358 {
9359         volatile struct shparam saveparam;
9360         struct jmploc *volatile savehandler;
9361         struct jmploc jmploc;
9362         int e;
9363
9364         saveparam = shellparam;
9365         savehandler = exception_handler;
9366         e = setjmp(jmploc.loc);
9367         if (e) {
9368                 goto funcdone;
9369         }
9370         INT_OFF;
9371         exception_handler = &jmploc;
9372         shellparam.malloced = 0;
9373         func->count++;
9374         funcnest++;
9375         INT_ON;
9376         shellparam.nparam = argc - 1;
9377         shellparam.p = argv + 1;
9378 #if ENABLE_ASH_GETOPTS
9379         shellparam.optind = 1;
9380         shellparam.optoff = -1;
9381 #endif
9382         pushlocalvars();
9383         evaltree(func->n.narg.next, flags & EV_TESTED);
9384         poplocalvars(0);
9385  funcdone:
9386         INT_OFF;
9387         funcnest--;
9388         freefunc(func);
9389         freeparam(&shellparam);
9390         shellparam = saveparam;
9391         exception_handler = savehandler;
9392         INT_ON;
9393         evalskip &= ~SKIPFUNC;
9394         return e;
9395 }
9396
9397 /*
9398  * Make a variable a local variable.  When a variable is made local, it's
9399  * value and flags are saved in a localvar structure.  The saved values
9400  * will be restored when the shell function returns.  We handle the name
9401  * "-" as a special case: it makes changes to "set +-options" local
9402  * (options will be restored on return from the function).
9403  */
9404 static void
9405 mklocal(char *name)
9406 {
9407         struct localvar *lvp;
9408         struct var **vpp;
9409         struct var *vp;
9410         char *eq = strchr(name, '=');
9411
9412         INT_OFF;
9413         /* Cater for duplicate "local". Examples:
9414          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9415          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9416          */
9417         lvp = localvar_stack->lv;
9418         while (lvp) {
9419                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9420                         if (eq)
9421                                 setvareq(name, 0);
9422                         /* else:
9423                          * it's a duplicate "local VAR" declaration, do nothing
9424                          */
9425                         goto ret;
9426                 }
9427                 lvp = lvp->next;
9428         }
9429
9430         lvp = ckzalloc(sizeof(*lvp));
9431         if (LONE_DASH(name)) {
9432                 char *p;
9433                 p = ckmalloc(sizeof(optlist));
9434                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9435                 vp = NULL;
9436         } else {
9437                 vpp = hashvar(name);
9438                 vp = *findvar(vpp, name);
9439                 if (vp == NULL) {
9440                         /* variable did not exist yet */
9441                         if (eq)
9442                                 vp = setvareq(name, VSTRFIXED);
9443                         else
9444                                 vp = setvar(name, NULL, VSTRFIXED);
9445                         lvp->flags = VUNSET;
9446                 } else {
9447                         lvp->text = vp->var_text;
9448                         lvp->flags = vp->flags;
9449                         /* make sure neither "struct var" nor string gets freed
9450                          * during (un)setting:
9451                          */
9452                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9453                         if (eq)
9454                                 setvareq(name, 0);
9455                         else
9456                                 /* "local VAR" unsets VAR: */
9457                                 setvar0(name, NULL);
9458                 }
9459         }
9460         lvp->vp = vp;
9461         lvp->next = localvar_stack->lv;
9462         localvar_stack->lv = lvp;
9463  ret:
9464         INT_ON;
9465 }
9466
9467 /*
9468  * The "local" command.
9469  */
9470 static int FAST_FUNC
9471 localcmd(int argc UNUSED_PARAM, char **argv)
9472 {
9473         char *name;
9474
9475         if (!localvar_stack)
9476                 ash_msg_and_raise_error("not in a function");
9477
9478         argv = argptr;
9479         while ((name = *argv++) != NULL) {
9480                 mklocal(name);
9481         }
9482         return 0;
9483 }
9484
9485 static int FAST_FUNC
9486 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9487 {
9488         return 1;
9489 }
9490
9491 static int FAST_FUNC
9492 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9493 {
9494         return 0;
9495 }
9496
9497 static int FAST_FUNC
9498 execcmd(int argc UNUSED_PARAM, char **argv)
9499 {
9500         optionarg = NULL;
9501         while (nextopt("a:") != '\0')
9502                 /* nextopt() sets optionarg to "-a ARGV0" */;
9503
9504         argv = argptr;
9505         if (argv[0]) {
9506                 char *prog;
9507
9508                 iflag = 0;              /* exit on error */
9509                 mflag = 0;
9510                 optschanged();
9511                 /* We should set up signals for "exec CMD"
9512                  * the same way as for "CMD" without "exec".
9513                  * But optschanged->setinteractive->setsignal
9514                  * still thought we are a root shell. Therefore, for example,
9515                  * SIGQUIT is still set to IGN. Fix it:
9516                  */
9517                 shlvl++;
9518                 setsignal(SIGQUIT);
9519                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9520                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9521                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9522
9523                 prog = argv[0];
9524                 if (optionarg)
9525                         argv[0] = optionarg;
9526                 shellexec(prog, argv, pathval(), 0);
9527                 /* NOTREACHED */
9528         }
9529         return 0;
9530 }
9531
9532 /*
9533  * The return command.
9534  */
9535 static int FAST_FUNC
9536 returncmd(int argc UNUSED_PARAM, char **argv)
9537 {
9538         /*
9539          * If called outside a function, do what ksh does;
9540          * skip the rest of the file.
9541          */
9542         evalskip = SKIPFUNC;
9543         return argv[1] ? number(argv[1]) : exitstatus;
9544 }
9545
9546 /* Forward declarations for builtintab[] */
9547 static int breakcmd(int, char **) FAST_FUNC;
9548 static int dotcmd(int, char **) FAST_FUNC;
9549 static int evalcmd(int, char **, int) FAST_FUNC;
9550 static int exitcmd(int, char **) FAST_FUNC;
9551 static int exportcmd(int, char **) FAST_FUNC;
9552 #if ENABLE_ASH_GETOPTS
9553 static int getoptscmd(int, char **) FAST_FUNC;
9554 #endif
9555 #if ENABLE_ASH_HELP
9556 static int helpcmd(int, char **) FAST_FUNC;
9557 #endif
9558 #if MAX_HISTORY
9559 static int historycmd(int, char **) FAST_FUNC;
9560 #endif
9561 #if ENABLE_FEATURE_SH_MATH
9562 static int letcmd(int, char **) FAST_FUNC;
9563 #endif
9564 static int readcmd(int, char **) FAST_FUNC;
9565 static int setcmd(int, char **) FAST_FUNC;
9566 static int shiftcmd(int, char **) FAST_FUNC;
9567 static int timescmd(int, char **) FAST_FUNC;
9568 static int trapcmd(int, char **) FAST_FUNC;
9569 static int umaskcmd(int, char **) FAST_FUNC;
9570 static int unsetcmd(int, char **) FAST_FUNC;
9571 static int ulimitcmd(int, char **) FAST_FUNC;
9572
9573 #define BUILTIN_NOSPEC          "0"
9574 #define BUILTIN_SPECIAL         "1"
9575 #define BUILTIN_REGULAR         "2"
9576 #define BUILTIN_SPEC_REG        "3"
9577 #define BUILTIN_ASSIGN          "4"
9578 #define BUILTIN_SPEC_ASSG       "5"
9579 #define BUILTIN_REG_ASSG        "6"
9580 #define BUILTIN_SPEC_REG_ASSG   "7"
9581
9582 /* Stubs for calling non-FAST_FUNC's */
9583 #if ENABLE_ASH_ECHO
9584 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9585 #endif
9586 #if ENABLE_ASH_PRINTF
9587 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9588 #endif
9589 #if ENABLE_ASH_TEST || BASH_TEST2
9590 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9591 #endif
9592
9593 /* Keep these in proper order since it is searched via bsearch() */
9594 static const struct builtincmd builtintab[] = {
9595         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9596         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9597 #if ENABLE_ASH_TEST
9598         { BUILTIN_REGULAR       "["       , testcmd    },
9599 #endif
9600 #if BASH_TEST2
9601         { BUILTIN_REGULAR       "[["      , testcmd    },
9602 #endif
9603 #if ENABLE_ASH_ALIAS
9604         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9605 #endif
9606 #if JOBS
9607         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9608 #endif
9609         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9610         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9611         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9612 #if ENABLE_ASH_CMDCMD
9613         { BUILTIN_REGULAR       "command" , commandcmd },
9614 #endif
9615         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9616 #if ENABLE_ASH_ECHO
9617         { BUILTIN_REGULAR       "echo"    , echocmd    },
9618 #endif
9619         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9620         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9621         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9622         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9623         { BUILTIN_REGULAR       "false"   , falsecmd   },
9624 #if JOBS
9625         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9626 #endif
9627 #if ENABLE_ASH_GETOPTS
9628         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9629 #endif
9630         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9631 #if ENABLE_ASH_HELP
9632         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9633 #endif
9634 #if MAX_HISTORY
9635         { BUILTIN_NOSPEC        "history" , historycmd },
9636 #endif
9637 #if JOBS
9638         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9639         { BUILTIN_REGULAR       "kill"    , killcmd    },
9640 #endif
9641 #if ENABLE_FEATURE_SH_MATH
9642         { BUILTIN_NOSPEC        "let"     , letcmd     },
9643 #endif
9644         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9645 #if ENABLE_ASH_PRINTF
9646         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9647 #endif
9648         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9649         { BUILTIN_REGULAR       "read"    , readcmd    },
9650         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9651         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9652         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9653         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9654 #if BASH_SOURCE
9655         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9656 #endif
9657 #if ENABLE_ASH_TEST
9658         { BUILTIN_REGULAR       "test"    , testcmd    },
9659 #endif
9660         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9661         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9662         { BUILTIN_REGULAR       "true"    , truecmd    },
9663         { BUILTIN_NOSPEC        "type"    , typecmd    },
9664         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9665         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9666 #if ENABLE_ASH_ALIAS
9667         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9668 #endif
9669         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9670         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9671 };
9672
9673 /* Should match the above table! */
9674 #define COMMANDCMD (builtintab + \
9675         /* . : */       2 + \
9676         /* [ */         1 * ENABLE_ASH_TEST + \
9677         /* [[ */        1 * BASH_TEST2 + \
9678         /* alias */     1 * ENABLE_ASH_ALIAS + \
9679         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9680         /* break cd cddir  */   3)
9681 #define EVALCMD (COMMANDCMD + \
9682         /* command */   1 * ENABLE_ASH_CMDCMD + \
9683         /* continue */  1 + \
9684         /* echo */      1 * ENABLE_ASH_ECHO + \
9685         0)
9686 #define EXECCMD (EVALCMD + \
9687         /* eval */      1)
9688
9689 /*
9690  * Search the table of builtin commands.
9691  */
9692 static int
9693 pstrcmp1(const void *a, const void *b)
9694 {
9695         return strcmp((char*)a, *(char**)b + 1);
9696 }
9697 static struct builtincmd *
9698 find_builtin(const char *name)
9699 {
9700         struct builtincmd *bp;
9701
9702         bp = bsearch(
9703                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9704                 pstrcmp1
9705         );
9706         return bp;
9707 }
9708
9709 /*
9710  * Execute a simple command.
9711  */
9712 static int
9713 isassignment(const char *p)
9714 {
9715         const char *q = endofname(p);
9716         if (p == q)
9717                 return 0;
9718         return *q == '=';
9719 }
9720 static int FAST_FUNC
9721 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9722 {
9723         /* Preserve exitstatus of a previous possible redirection
9724          * as POSIX mandates */
9725         return back_exitstatus;
9726 }
9727 static int
9728 evalcommand(union node *cmd, int flags)
9729 {
9730         static const struct builtincmd null_bltin = {
9731                 "\0\0", bltincmd /* why three NULs? */
9732         };
9733         struct localvar_list *localvar_stop;
9734         struct redirtab *redir_stop;
9735         struct stackmark smark;
9736         union node *argp;
9737         struct arglist arglist;
9738         struct arglist varlist;
9739         char **argv;
9740         int argc;
9741         const struct strlist *sp;
9742         struct cmdentry cmdentry;
9743         struct job *jp;
9744         char *lastarg;
9745         const char *path;
9746         int spclbltin;
9747         int status;
9748         char **nargv;
9749         smallint cmd_is_exec;
9750
9751         /* First expand the arguments. */
9752         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9753         setstackmark(&smark);
9754         localvar_stop = pushlocalvars();
9755         back_exitstatus = 0;
9756
9757         cmdentry.cmdtype = CMDBUILTIN;
9758         cmdentry.u.cmd = &null_bltin;
9759         varlist.lastp = &varlist.list;
9760         *varlist.lastp = NULL;
9761         arglist.lastp = &arglist.list;
9762         *arglist.lastp = NULL;
9763
9764         argc = 0;
9765         if (cmd->ncmd.args) {
9766                 struct builtincmd *bcmd;
9767                 smallint pseudovarflag;
9768
9769                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9770                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9771
9772                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9773                         struct strlist **spp;
9774
9775                         spp = arglist.lastp;
9776                         if (pseudovarflag && isassignment(argp->narg.text))
9777                                 expandarg(argp, &arglist, EXP_VARTILDE);
9778                         else
9779                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9780
9781                         for (sp = *spp; sp; sp = sp->next)
9782                                 argc++;
9783                 }
9784         }
9785
9786         /* Reserve one extra spot at the front for shellexec. */
9787         nargv = stalloc(sizeof(char *) * (argc + 2));
9788         argv = ++nargv;
9789         for (sp = arglist.list; sp; sp = sp->next) {
9790                 TRACE(("evalcommand arg: %s\n", sp->text));
9791                 *nargv++ = sp->text;
9792         }
9793         *nargv = NULL;
9794
9795         lastarg = NULL;
9796         if (iflag && funcnest == 0 && argc > 0)
9797                 lastarg = nargv[-1];
9798
9799         expredir(cmd->ncmd.redirect);
9800         redir_stop = pushredir(cmd->ncmd.redirect);
9801         preverrout_fd = 2;
9802         if (BASH_XTRACEFD && xflag) {
9803                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9804                  * we do not emulate this. We only use its value.
9805                  */
9806                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9807                 if (xtracefd && is_number(xtracefd))
9808                         preverrout_fd = atoi(xtracefd);
9809
9810         }
9811         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9812
9813         path = vpath.var_text;
9814         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9815                 struct strlist **spp;
9816                 char *p;
9817
9818                 spp = varlist.lastp;
9819                 expandarg(argp, &varlist, EXP_VARTILDE);
9820
9821                 mklocal((*spp)->text);
9822
9823                 /*
9824                  * Modify the command lookup path, if a PATH= assignment
9825                  * is present
9826                  */
9827                 p = (*spp)->text;
9828                 if (varcmp(p, path) == 0)
9829                         path = p;
9830         }
9831
9832         /* Print the command if xflag is set. */
9833         if (xflag) {
9834                 const char *pfx = "";
9835
9836                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9837
9838                 sp = varlist.list;
9839                 while (sp) {
9840                         char *varval = sp->text;
9841                         char *eq = strchrnul(varval, '=');
9842                         if (*eq)
9843                                 eq++;
9844                         fdprintf(preverrout_fd, "%s%.*s%s",
9845                                 pfx,
9846                                 (int)(eq - varval), varval,
9847                                 maybe_single_quote(eq)
9848                         );
9849                         sp = sp->next;
9850                         pfx = " ";
9851                 }
9852
9853                 sp = arglist.list;
9854                 while (sp) {
9855                         fdprintf(preverrout_fd, "%s%s",
9856                                 pfx,
9857                                 /* always quote if matches reserved word: */
9858                                 findkwd(sp->text)
9859                                 ? single_quote(sp->text)
9860                                 : maybe_single_quote(sp->text)
9861                         );
9862                         sp = sp->next;
9863                         pfx = " ";
9864                 }
9865                 safe_write(preverrout_fd, "\n", 1);
9866         }
9867
9868         cmd_is_exec = 0;
9869         spclbltin = -1;
9870
9871         /* Now locate the command. */
9872         if (argc) {
9873                 int cmd_flag = DO_ERR;
9874 #if ENABLE_ASH_CMDCMD
9875                 const char *oldpath = path + 5;
9876 #endif
9877                 path += 5;
9878                 for (;;) {
9879                         find_command(argv[0], &cmdentry, cmd_flag, path);
9880                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9881                                 flush_stdout_stderr();
9882                                 status = 127;
9883                                 goto bail;
9884                         }
9885
9886                         /* implement bltin and command here */
9887                         if (cmdentry.cmdtype != CMDBUILTIN)
9888                                 break;
9889                         if (spclbltin < 0)
9890                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9891                         if (cmdentry.u.cmd == EXECCMD)
9892                                 cmd_is_exec = 1;
9893 #if ENABLE_ASH_CMDCMD
9894                         if (cmdentry.u.cmd == COMMANDCMD) {
9895                                 path = oldpath;
9896                                 nargv = parse_command_args(argv, &path);
9897                                 if (!nargv)
9898                                         break;
9899                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9900                                  * nargv => "PROG". path is updated if -p.
9901                                  */
9902                                 argc -= nargv - argv;
9903                                 argv = nargv;
9904                                 cmd_flag |= DO_NOFUNC;
9905                         } else
9906 #endif
9907                                 break;
9908                 }
9909         }
9910
9911         if (status) {
9912  bail:
9913                 exitstatus = status;
9914
9915                 /* We have a redirection error. */
9916                 if (spclbltin > 0)
9917                         raise_exception(EXERROR);
9918
9919                 goto out;
9920         }
9921
9922         /* Execute the command. */
9923         switch (cmdentry.cmdtype) {
9924         default: {
9925
9926 #if ENABLE_FEATURE_SH_NOFORK
9927 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9928  *     around run_nofork_applet() call.
9929  * (2) Should this check also be done in forkshell()?
9930  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9931  */
9932                 /* find_command() encodes applet_no as (-2 - applet_no) */
9933                 int applet_no = (- cmdentry.u.index - 2);
9934                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9935                         listsetvar(varlist.list, VEXPORT|VSTACK);
9936                         /*
9937                          * Run <applet>_main().
9938                          * Signals (^C) can't interrupt here.
9939                          * Otherwise we can mangle stdio or malloc internal state.
9940                          * This makes applets which can run for a long time
9941                          * and/or wait for user input ineligible for NOFORK:
9942                          * for example, "yes" or "rm" (rm -i waits for input).
9943                          */
9944                         INT_OFF;
9945                         status = run_nofork_applet(applet_no, argv);
9946                         /*
9947                          * Try enabling NOFORK for "yes" applet.
9948                          * ^C _will_ stop it (write returns EINTR),
9949                          * but this causes stdout FILE to be stuck
9950                          * and needing clearerr(). What if other applets
9951                          * also can get EINTRs? Do we need to switch
9952                          * our signals to SA_RESTART?
9953                          */
9954                         /*clearerr(stdout);*/
9955                         INT_ON;
9956                         break;
9957                 }
9958 #endif
9959                 /* Can we avoid forking? For example, very last command
9960                  * in a script or a subshell does not need forking,
9961                  * we can just exec it.
9962                  */
9963                 if (!(flags & EV_EXIT) || may_have_traps) {
9964                         /* No, forking off a child is necessary */
9965                         INT_OFF;
9966                         get_tty_state();
9967                         jp = makejob(/*cmd,*/ 1);
9968                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9969                                 /* parent */
9970                                 status = waitforjob(jp);
9971                                 INT_ON;
9972                                 TRACE(("forked child exited with %d\n", status));
9973                                 break;
9974                         }
9975                         /* child */
9976                         FORCE_INT_ON;
9977                         /* fall through to exec'ing external program */
9978                 }
9979                 listsetvar(varlist.list, VEXPORT|VSTACK);
9980                 shellexec(argv[0], argv, path, cmdentry.u.index);
9981                 /* NOTREACHED */
9982         } /* default */
9983         case CMDBUILTIN:
9984                 if (spclbltin > 0 || argc == 0) {
9985                         poplocalvars(1);
9986                         if (cmd_is_exec && argc > 1)
9987                                 listsetvar(varlist.list, VEXPORT);
9988                 }
9989
9990                 /* Tight loop with builtins only:
9991                  * "while kill -0 $child; do true; done"
9992                  * will never exit even if $child died, unless we do this
9993                  * to reap the zombie and make kill detect that it's gone: */
9994                 dowait(DOWAIT_NONBLOCK, NULL);
9995
9996                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9997                         if (exception_type == EXERROR && spclbltin <= 0) {
9998                                 FORCE_INT_ON;
9999                                 goto readstatus;
10000                         }
10001  raise:
10002                         longjmp(exception_handler->loc, 1);
10003                 }
10004                 goto readstatus;
10005
10006         case CMDFUNCTION:
10007                 poplocalvars(1);
10008                 /* See above for the rationale */
10009                 dowait(DOWAIT_NONBLOCK, NULL);
10010                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10011                         goto raise;
10012  readstatus:
10013                 status = exitstatus;
10014                 break;
10015         } /* switch */
10016
10017  out:
10018         if (cmd->ncmd.redirect)
10019                 popredir(/*drop:*/ cmd_is_exec);
10020         unwindredir(redir_stop);
10021         unwindlocalvars(localvar_stop);
10022         if (lastarg) {
10023                 /* dsl: I think this is intended to be used to support
10024                  * '_' in 'vi' command mode during line editing...
10025                  * However I implemented that within libedit itself.
10026                  */
10027                 setvar0("_", lastarg);
10028         }
10029         popstackmark(&smark);
10030
10031         return status;
10032 }
10033
10034 static int
10035 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10036 {
10037         char *volatile savecmdname;
10038         struct jmploc *volatile savehandler;
10039         struct jmploc jmploc;
10040         int status;
10041         int i;
10042
10043         savecmdname = commandname;
10044         savehandler = exception_handler;
10045         i = setjmp(jmploc.loc);
10046         if (i)
10047                 goto cmddone;
10048         exception_handler = &jmploc;
10049         commandname = argv[0];
10050         argptr = argv + 1;
10051         optptr = NULL;                  /* initialize nextopt */
10052         if (cmd == EVALCMD)
10053                 status = evalcmd(argc, argv, flags);
10054         else
10055                 status = (*cmd->builtin)(argc, argv);
10056         flush_stdout_stderr();
10057         status |= ferror(stdout);
10058         exitstatus = status;
10059  cmddone:
10060         clearerr(stdout);
10061         commandname = savecmdname;
10062         exception_handler = savehandler;
10063
10064         return i;
10065 }
10066
10067 static int
10068 goodname(const char *p)
10069 {
10070         return endofname(p)[0] == '\0';
10071 }
10072
10073
10074 /*
10075  * Search for a command.  This is called before we fork so that the
10076  * location of the command will be available in the parent as well as
10077  * the child.  The check for "goodname" is an overly conservative
10078  * check that the name will not be subject to expansion.
10079  */
10080 static void
10081 prehash(union node *n)
10082 {
10083         struct cmdentry entry;
10084
10085         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10086                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10087 }
10088
10089
10090 /* ============ Builtin commands
10091  *
10092  * Builtin commands whose functions are closely tied to evaluation
10093  * are implemented here.
10094  */
10095
10096 /*
10097  * Handle break and continue commands.  Break, continue, and return are
10098  * all handled by setting the evalskip flag.  The evaluation routines
10099  * above all check this flag, and if it is set they start skipping
10100  * commands rather than executing them.  The variable skipcount is
10101  * the number of loops to break/continue, or the number of function
10102  * levels to return.  (The latter is always 1.)  It should probably
10103  * be an error to break out of more loops than exist, but it isn't
10104  * in the standard shell so we don't make it one here.
10105  */
10106 static int FAST_FUNC
10107 breakcmd(int argc UNUSED_PARAM, char **argv)
10108 {
10109         int n = argv[1] ? number(argv[1]) : 1;
10110
10111         if (n <= 0)
10112                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10113         if (n > loopnest)
10114                 n = loopnest;
10115         if (n > 0) {
10116                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10117                 skipcount = n;
10118         }
10119         return 0;
10120 }
10121
10122
10123 /*
10124  * This implements the input routines used by the parser.
10125  */
10126
10127 enum {
10128         INPUT_PUSH_FILE = 1,
10129         INPUT_NOFILE_OK = 2,
10130 };
10131
10132 static smallint checkkwd;
10133 /* values of checkkwd variable */
10134 #define CHKALIAS        0x1
10135 #define CHKKWD          0x2
10136 #define CHKNL           0x4
10137 #define CHKEOFMARK      0x8
10138
10139 /*
10140  * Push a string back onto the input at this current parsefile level.
10141  * We handle aliases this way.
10142  */
10143 #if !ENABLE_ASH_ALIAS
10144 #define pushstring(s, ap) pushstring(s)
10145 #endif
10146 static void
10147 pushstring(char *s, struct alias *ap)
10148 {
10149         struct strpush *sp;
10150         int len;
10151
10152         len = strlen(s);
10153         INT_OFF;
10154         if (g_parsefile->strpush) {
10155                 sp = ckzalloc(sizeof(*sp));
10156                 sp->prev = g_parsefile->strpush;
10157         } else {
10158                 sp = &(g_parsefile->basestrpush);
10159         }
10160         g_parsefile->strpush = sp;
10161         sp->prev_string = g_parsefile->next_to_pgetc;
10162         sp->prev_left_in_line = g_parsefile->left_in_line;
10163         sp->unget = g_parsefile->unget;
10164         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10165 #if ENABLE_ASH_ALIAS
10166         sp->ap = ap;
10167         if (ap) {
10168                 ap->flag |= ALIASINUSE;
10169                 sp->string = s;
10170         }
10171 #endif
10172         g_parsefile->next_to_pgetc = s;
10173         g_parsefile->left_in_line = len;
10174         g_parsefile->unget = 0;
10175         INT_ON;
10176 }
10177
10178 static void
10179 popstring(void)
10180 {
10181         struct strpush *sp = g_parsefile->strpush;
10182
10183         INT_OFF;
10184 #if ENABLE_ASH_ALIAS
10185         if (sp->ap) {
10186                 if (g_parsefile->next_to_pgetc[-1] == ' '
10187                  || g_parsefile->next_to_pgetc[-1] == '\t'
10188                 ) {
10189                         checkkwd |= CHKALIAS;
10190                 }
10191                 if (sp->string != sp->ap->val) {
10192                         free(sp->string);
10193                 }
10194                 sp->ap->flag &= ~ALIASINUSE;
10195                 if (sp->ap->flag & ALIASDEAD) {
10196                         unalias(sp->ap->name);
10197                 }
10198         }
10199 #endif
10200         g_parsefile->next_to_pgetc = sp->prev_string;
10201         g_parsefile->left_in_line = sp->prev_left_in_line;
10202         g_parsefile->unget = sp->unget;
10203         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10204         g_parsefile->strpush = sp->prev;
10205         if (sp != &(g_parsefile->basestrpush))
10206                 free(sp);
10207         INT_ON;
10208 }
10209
10210 static int
10211 preadfd(void)
10212 {
10213         int nr;
10214         char *buf = g_parsefile->buf;
10215
10216         g_parsefile->next_to_pgetc = buf;
10217 #if ENABLE_FEATURE_EDITING
10218  retry:
10219         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10220                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10221         else {
10222 # if ENABLE_ASH_IDLE_TIMEOUT
10223                 int timeout = -1;
10224                 if (iflag) {
10225                         const char *tmout_var = lookupvar("TMOUT");
10226                         if (tmout_var) {
10227                                 timeout = atoi(tmout_var) * 1000;
10228                                 if (timeout <= 0)
10229                                         timeout = -1;
10230                         }
10231                 }
10232                 line_input_state->timeout = timeout;
10233 # endif
10234 # if ENABLE_FEATURE_TAB_COMPLETION
10235                 line_input_state->path_lookup = pathval();
10236 # endif
10237                 reinit_unicode_for_ash();
10238                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10239                 if (nr == 0) {
10240                         /* ^C pressed, "convert" to SIGINT */
10241                         write(STDOUT_FILENO, "^C", 2);
10242                         if (trap[SIGINT]) {
10243                                 buf[0] = '\n';
10244                                 buf[1] = '\0';
10245                                 raise(SIGINT);
10246                                 return 1;
10247                         }
10248                         exitstatus = 128 + SIGINT;
10249                         bb_putchar('\n');
10250                         goto retry;
10251                 }
10252                 if (nr < 0) {
10253                         if (errno == 0) {
10254                                 /* Ctrl+D pressed */
10255                                 nr = 0;
10256                         }
10257 # if ENABLE_ASH_IDLE_TIMEOUT
10258                         else if (errno == EAGAIN && timeout > 0) {
10259                                 puts("\007timed out waiting for input: auto-logout");
10260                                 exitshell();
10261                         }
10262 # endif
10263                 }
10264         }
10265 #else
10266         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10267 #endif
10268
10269 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10270         if (nr < 0) {
10271                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10272                         int flags = fcntl(0, F_GETFL);
10273                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10274                                 flags &= ~O_NONBLOCK;
10275                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10276                                         out2str("sh: turning off NDELAY mode\n");
10277                                         goto retry;
10278                                 }
10279                         }
10280                 }
10281         }
10282 #endif
10283         return nr;
10284 }
10285
10286 /*
10287  * Refill the input buffer and return the next input character:
10288  *
10289  * 1) If a string was pushed back on the input, pop it;
10290  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10291  *    or we are reading from a string so we can't refill the buffer,
10292  *    return EOF.
10293  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10294  * 4) Process input up to the next newline, deleting nul characters.
10295  */
10296 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10297 #define pgetc_debug(...) ((void)0)
10298 static int pgetc(void);
10299 static int
10300 preadbuffer(void)
10301 {
10302         char *q;
10303         int more;
10304
10305         if (g_parsefile->strpush) {
10306 #if ENABLE_ASH_ALIAS
10307                 if (g_parsefile->left_in_line == -1
10308                  && g_parsefile->strpush->ap
10309                  && g_parsefile->next_to_pgetc[-1] != ' '
10310                  && g_parsefile->next_to_pgetc[-1] != '\t'
10311                 ) {
10312                         pgetc_debug("preadbuffer PEOA");
10313                         return PEOA;
10314                 }
10315 #endif
10316                 popstring();
10317                 return pgetc();
10318         }
10319         /* on both branches above g_parsefile->left_in_line < 0.
10320          * "pgetc" needs refilling.
10321          */
10322
10323         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10324          * pungetc() may increment it a few times.
10325          * Assuming it won't increment it to less than -90.
10326          */
10327         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10328                 pgetc_debug("preadbuffer PEOF1");
10329                 /* even in failure keep left_in_line and next_to_pgetc
10330                  * in lock step, for correct multi-layer pungetc.
10331                  * left_in_line was decremented before preadbuffer(),
10332                  * must inc next_to_pgetc: */
10333                 g_parsefile->next_to_pgetc++;
10334                 return PEOF;
10335         }
10336
10337         more = g_parsefile->left_in_buffer;
10338         if (more <= 0) {
10339                 flush_stdout_stderr();
10340  again:
10341                 more = preadfd();
10342                 if (more <= 0) {
10343                         /* don't try reading again */
10344                         g_parsefile->left_in_line = -99;
10345                         pgetc_debug("preadbuffer PEOF2");
10346                         g_parsefile->next_to_pgetc++;
10347                         return PEOF;
10348                 }
10349         }
10350
10351         /* Find out where's the end of line.
10352          * Set g_parsefile->left_in_line
10353          * and g_parsefile->left_in_buffer acordingly.
10354          * NUL chars are deleted.
10355          */
10356         q = g_parsefile->next_to_pgetc;
10357         for (;;) {
10358                 char c;
10359
10360                 more--;
10361
10362                 c = *q;
10363                 if (c == '\0') {
10364                         memmove(q, q + 1, more);
10365                 } else {
10366                         q++;
10367                         if (c == '\n') {
10368                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10369                                 break;
10370                         }
10371                 }
10372
10373                 if (more <= 0) {
10374                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10375                         if (g_parsefile->left_in_line < 0)
10376                                 goto again;
10377                         break;
10378                 }
10379         }
10380         g_parsefile->left_in_buffer = more;
10381
10382         if (vflag) {
10383                 char save = *q;
10384                 *q = '\0';
10385                 out2str(g_parsefile->next_to_pgetc);
10386                 *q = save;
10387         }
10388
10389         pgetc_debug("preadbuffer at %d:%p'%s'",
10390                         g_parsefile->left_in_line,
10391                         g_parsefile->next_to_pgetc,
10392                         g_parsefile->next_to_pgetc);
10393         return (unsigned char)*g_parsefile->next_to_pgetc++;
10394 }
10395
10396 static void
10397 nlprompt(void)
10398 {
10399         g_parsefile->linno++;
10400         setprompt_if(doprompt, 2);
10401 }
10402 static void
10403 nlnoprompt(void)
10404 {
10405         g_parsefile->linno++;
10406         needprompt = doprompt;
10407 }
10408
10409 static int
10410 pgetc(void)
10411 {
10412         int c;
10413
10414         pgetc_debug("pgetc at %d:%p'%s'",
10415                         g_parsefile->left_in_line,
10416                         g_parsefile->next_to_pgetc,
10417                         g_parsefile->next_to_pgetc);
10418         if (g_parsefile->unget)
10419                 return g_parsefile->lastc[--g_parsefile->unget];
10420
10421         if (--g_parsefile->left_in_line >= 0)
10422                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10423         else
10424                 c = preadbuffer();
10425
10426         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10427         g_parsefile->lastc[0] = c;
10428
10429         return c;
10430 }
10431
10432 #if ENABLE_ASH_ALIAS
10433 static int
10434 pgetc_without_PEOA(void)
10435 {
10436         int c;
10437         do {
10438                 pgetc_debug("pgetc at %d:%p'%s'",
10439                                 g_parsefile->left_in_line,
10440                                 g_parsefile->next_to_pgetc,
10441                                 g_parsefile->next_to_pgetc);
10442                 c = pgetc();
10443         } while (c == PEOA);
10444         return c;
10445 }
10446 #else
10447 # define pgetc_without_PEOA() pgetc()
10448 #endif
10449
10450 /*
10451  * Undo a call to pgetc.  Only two characters may be pushed back.
10452  * PEOF may be pushed back.
10453  */
10454 static void
10455 pungetc(void)
10456 {
10457         g_parsefile->unget++;
10458 }
10459
10460 /* This one eats backslash+newline */
10461 static int
10462 pgetc_eatbnl(void)
10463 {
10464         int c;
10465
10466         while ((c = pgetc()) == '\\') {
10467                 if (pgetc() != '\n') {
10468                         pungetc();
10469                         break;
10470                 }
10471
10472                 nlprompt();
10473         }
10474
10475         return c;
10476 }
10477
10478 /*
10479  * To handle the "." command, a stack of input files is used.  Pushfile
10480  * adds a new entry to the stack and popfile restores the previous level.
10481  */
10482 static void
10483 pushfile(void)
10484 {
10485         struct parsefile *pf;
10486
10487         pf = ckzalloc(sizeof(*pf));
10488         pf->prev = g_parsefile;
10489         pf->pf_fd = -1;
10490         /*pf->strpush = NULL; - ckzalloc did it */
10491         /*pf->basestrpush.prev = NULL;*/
10492         /*pf->unget = 0;*/
10493         g_parsefile = pf;
10494 }
10495
10496 static void
10497 popfile(void)
10498 {
10499         struct parsefile *pf = g_parsefile;
10500
10501         if (pf == &basepf)
10502                 return;
10503
10504         INT_OFF;
10505         if (pf->pf_fd >= 0)
10506                 close(pf->pf_fd);
10507         free(pf->buf);
10508         while (pf->strpush)
10509                 popstring();
10510         g_parsefile = pf->prev;
10511         free(pf);
10512         INT_ON;
10513 }
10514
10515 /*
10516  * Return to top level.
10517  */
10518 static void
10519 popallfiles(void)
10520 {
10521         while (g_parsefile != &basepf)
10522                 popfile();
10523 }
10524
10525 /*
10526  * Close the file(s) that the shell is reading commands from.  Called
10527  * after a fork is done.
10528  */
10529 static void
10530 closescript(void)
10531 {
10532         popallfiles();
10533         if (g_parsefile->pf_fd > 0) {
10534                 close(g_parsefile->pf_fd);
10535                 g_parsefile->pf_fd = 0;
10536         }
10537 }
10538
10539 /*
10540  * Like setinputfile, but takes an open file descriptor.  Call this with
10541  * interrupts off.
10542  */
10543 static void
10544 setinputfd(int fd, int push)
10545 {
10546         if (push) {
10547                 pushfile();
10548                 g_parsefile->buf = NULL;
10549         }
10550         g_parsefile->pf_fd = fd;
10551         if (g_parsefile->buf == NULL)
10552                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10553         g_parsefile->left_in_buffer = 0;
10554         g_parsefile->left_in_line = 0;
10555         g_parsefile->linno = 1;
10556 }
10557
10558 /*
10559  * Set the input to take input from a file.  If push is set, push the
10560  * old input onto the stack first.
10561  */
10562 static int
10563 setinputfile(const char *fname, int flags)
10564 {
10565         int fd;
10566
10567         INT_OFF;
10568         fd = open(fname, O_RDONLY);
10569         if (fd < 0) {
10570                 if (flags & INPUT_NOFILE_OK)
10571                         goto out;
10572                 exitstatus = 127;
10573                 ash_msg_and_raise_error("can't open '%s'", fname);
10574         }
10575         if (fd < 10)
10576                 fd = savefd(fd);
10577         else
10578                 close_on_exec_on(fd);
10579         setinputfd(fd, flags & INPUT_PUSH_FILE);
10580  out:
10581         INT_ON;
10582         return fd;
10583 }
10584
10585 /*
10586  * Like setinputfile, but takes input from a string.
10587  */
10588 static void
10589 setinputstring(char *string)
10590 {
10591         INT_OFF;
10592         pushfile();
10593         g_parsefile->next_to_pgetc = string;
10594         g_parsefile->left_in_line = strlen(string);
10595         g_parsefile->buf = NULL;
10596         g_parsefile->linno = 1;
10597         INT_ON;
10598 }
10599
10600
10601 /*
10602  * Routines to check for mail.
10603  */
10604
10605 #if ENABLE_ASH_MAIL
10606
10607 /* Hash of mtimes of mailboxes */
10608 static unsigned mailtime_hash;
10609 /* Set if MAIL or MAILPATH is changed. */
10610 static smallint mail_var_path_changed;
10611
10612 /*
10613  * Print appropriate message(s) if mail has arrived.
10614  * If mail_var_path_changed is set,
10615  * then the value of MAIL has mail_var_path_changed,
10616  * so we just update the values.
10617  */
10618 static void
10619 chkmail(void)
10620 {
10621         const char *mpath;
10622         char *p;
10623         char *q;
10624         unsigned new_hash;
10625         struct stackmark smark;
10626         struct stat statb;
10627
10628         setstackmark(&smark);
10629         mpath = mpathset() ? mpathval() : mailval();
10630         new_hash = 0;
10631         for (;;) {
10632                 p = path_advance(&mpath, nullstr);
10633                 if (p == NULL)
10634                         break;
10635                 if (*p == '\0')
10636                         continue;
10637                 for (q = p; *q; q++)
10638                         continue;
10639 #if DEBUG
10640                 if (q[-1] != '/')
10641                         abort();
10642 #endif
10643                 q[-1] = '\0';                   /* delete trailing '/' */
10644                 if (stat(p, &statb) < 0) {
10645                         continue;
10646                 }
10647                 /* Very simplistic "hash": just a sum of all mtimes */
10648                 new_hash += (unsigned)statb.st_mtime;
10649         }
10650         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10651                 if (mailtime_hash != 0)
10652                         out2str("you have mail\n");
10653                 mailtime_hash = new_hash;
10654         }
10655         mail_var_path_changed = 0;
10656         popstackmark(&smark);
10657 }
10658
10659 static void FAST_FUNC
10660 changemail(const char *val UNUSED_PARAM)
10661 {
10662         mail_var_path_changed = 1;
10663 }
10664
10665 #endif /* ASH_MAIL */
10666
10667
10668 /* ============ ??? */
10669
10670 /*
10671  * Set the shell parameters.
10672  */
10673 static void
10674 setparam(char **argv)
10675 {
10676         char **newparam;
10677         char **ap;
10678         int nparam;
10679
10680         for (nparam = 0; argv[nparam]; nparam++)
10681                 continue;
10682         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10683         while (*argv) {
10684                 *ap++ = ckstrdup(*argv++);
10685         }
10686         *ap = NULL;
10687         freeparam(&shellparam);
10688         shellparam.malloced = 1;
10689         shellparam.nparam = nparam;
10690         shellparam.p = newparam;
10691 #if ENABLE_ASH_GETOPTS
10692         shellparam.optind = 1;
10693         shellparam.optoff = -1;
10694 #endif
10695 }
10696
10697 /*
10698  * Process shell options.  The global variable argptr contains a pointer
10699  * to the argument list; we advance it past the options.
10700  *
10701  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10702  * For a non-interactive shell, an error condition encountered
10703  * by a special built-in ... shall cause the shell to write a diagnostic message
10704  * to standard error and exit as shown in the following table:
10705  * Error                                           Special Built-In
10706  * ...
10707  * Utility syntax error (option or operand error)  Shall exit
10708  * ...
10709  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10710  * we see that bash does not do that (set "finishes" with error code 1 instead,
10711  * and shell continues), and people rely on this behavior!
10712  * Testcase:
10713  * set -o barfoo 2>/dev/null
10714  * echo $?
10715  *
10716  * Oh well. Let's mimic that.
10717  */
10718 static int
10719 plus_minus_o(char *name, int val)
10720 {
10721         int i;
10722
10723         if (name) {
10724                 for (i = 0; i < NOPTS; i++) {
10725                         if (strcmp(name, optnames(i)) == 0) {
10726                                 optlist[i] = val;
10727                                 return 0;
10728                         }
10729                 }
10730                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10731                 return 1;
10732         }
10733         for (i = 0; i < NOPTS; i++) {
10734                 if (val) {
10735                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10736                 } else {
10737                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10738                 }
10739         }
10740         return 0;
10741 }
10742 static void
10743 setoption(int flag, int val)
10744 {
10745         int i;
10746
10747         for (i = 0; i < NOPTS; i++) {
10748                 if (optletters(i) == flag) {
10749                         optlist[i] = val;
10750                         return;
10751                 }
10752         }
10753         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10754         /* NOTREACHED */
10755 }
10756 static int
10757 options(int cmdline, int *login_sh)
10758 {
10759         char *p;
10760         int val;
10761         int c;
10762
10763         if (cmdline)
10764                 minusc = NULL;
10765         while ((p = *argptr) != NULL) {
10766                 c = *p++;
10767                 if (c != '-' && c != '+')
10768                         break;
10769                 argptr++;
10770                 val = 0; /* val = 0 if c == '+' */
10771                 if (c == '-') {
10772                         val = 1;
10773                         if (p[0] == '\0' || LONE_DASH(p)) {
10774                                 if (!cmdline) {
10775                                         /* "-" means turn off -x and -v */
10776                                         if (p[0] == '\0')
10777                                                 xflag = vflag = 0;
10778                                         /* "--" means reset params */
10779                                         else if (*argptr == NULL)
10780                                                 setparam(argptr);
10781                                 }
10782                                 break;    /* "-" or "--" terminates options */
10783                         }
10784                 }
10785                 /* first char was + or - */
10786                 while ((c = *p++) != '\0') {
10787                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10788                         if (c == 'c' && cmdline) {
10789                                 minusc = p;     /* command is after shell args */
10790                         } else if (c == 'o') {
10791                                 if (plus_minus_o(*argptr, val)) {
10792                                         /* it already printed err message */
10793                                         return 1; /* error */
10794                                 }
10795                                 if (*argptr)
10796                                         argptr++;
10797                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10798                                 if (login_sh)
10799                                         *login_sh = 1;
10800                         /* bash does not accept +-login, we also won't */
10801                         } else if (cmdline && val && (c == '-')) { /* long options */
10802                                 if (strcmp(p, "login") == 0) {
10803                                         if (login_sh)
10804                                                 *login_sh = 1;
10805                                 }
10806                                 break;
10807                         } else {
10808                                 setoption(c, val);
10809                         }
10810                 }
10811         }
10812         return 0;
10813 }
10814
10815 /*
10816  * The shift builtin command.
10817  */
10818 static int FAST_FUNC
10819 shiftcmd(int argc UNUSED_PARAM, char **argv)
10820 {
10821         int n;
10822         char **ap1, **ap2;
10823
10824         n = 1;
10825         if (argv[1])
10826                 n = number(argv[1]);
10827         if (n > shellparam.nparam)
10828                 n = 0; /* bash compat, was = shellparam.nparam; */
10829         INT_OFF;
10830         shellparam.nparam -= n;
10831         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10832                 if (shellparam.malloced)
10833                         free(*ap1);
10834         }
10835         ap2 = shellparam.p;
10836         while ((*ap2++ = *ap1++) != NULL)
10837                 continue;
10838 #if ENABLE_ASH_GETOPTS
10839         shellparam.optind = 1;
10840         shellparam.optoff = -1;
10841 #endif
10842         INT_ON;
10843         return 0;
10844 }
10845
10846 /*
10847  * POSIX requires that 'set' (but not export or readonly) output the
10848  * variables in lexicographic order - by the locale's collating order (sigh).
10849  * Maybe we could keep them in an ordered balanced binary tree
10850  * instead of hashed lists.
10851  * For now just roll 'em through qsort for printing...
10852  */
10853 static int
10854 showvars(const char *sep_prefix, int on, int off)
10855 {
10856         const char *sep;
10857         char **ep, **epend;
10858
10859         ep = listvars(on, off, &epend);
10860         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10861
10862         sep = *sep_prefix ? " " : sep_prefix;
10863
10864         for (; ep < epend; ep++) {
10865                 const char *p;
10866                 const char *q;
10867
10868                 p = strchrnul(*ep, '=');
10869                 q = nullstr;
10870                 if (*p)
10871                         q = single_quote(++p);
10872                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10873         }
10874         return 0;
10875 }
10876
10877 /*
10878  * The set command builtin.
10879  */
10880 static int FAST_FUNC
10881 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10882 {
10883         int retval;
10884
10885         if (!argv[1])
10886                 return showvars(nullstr, 0, VUNSET);
10887
10888         INT_OFF;
10889         retval = options(/*cmdline:*/ 0, NULL);
10890         if (retval == 0) { /* if no parse error... */
10891                 optschanged();
10892                 if (*argptr != NULL) {
10893                         setparam(argptr);
10894                 }
10895         }
10896         INT_ON;
10897         return retval;
10898 }
10899
10900 #if ENABLE_ASH_RANDOM_SUPPORT
10901 static void FAST_FUNC
10902 change_random(const char *value)
10903 {
10904         uint32_t t;
10905
10906         if (value == NULL) {
10907                 /* "get", generate */
10908                 t = next_random(&random_gen);
10909                 /* set without recursion */
10910                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10911                 vrandom.flags &= ~VNOFUNC;
10912         } else {
10913                 /* set/reset */
10914                 t = strtoul(value, NULL, 10);
10915                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10916         }
10917 }
10918 #endif
10919
10920 #if ENABLE_ASH_GETOPTS
10921 static int
10922 getopts(char *optstr, char *optvar, char **optfirst)
10923 {
10924         char *p, *q;
10925         char c = '?';
10926         int done = 0;
10927         char sbuf[2];
10928         char **optnext;
10929         int ind = shellparam.optind;
10930         int off = shellparam.optoff;
10931
10932         sbuf[1] = '\0';
10933
10934         shellparam.optind = -1;
10935         optnext = optfirst + ind - 1;
10936
10937         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10938                 p = NULL;
10939         else
10940                 p = optnext[-1] + off;
10941         if (p == NULL || *p == '\0') {
10942                 /* Current word is done, advance */
10943                 p = *optnext;
10944                 if (p == NULL || *p != '-' || *++p == '\0') {
10945  atend:
10946                         p = NULL;
10947                         done = 1;
10948                         goto out;
10949                 }
10950                 optnext++;
10951                 if (LONE_DASH(p))        /* check for "--" */
10952                         goto atend;
10953         }
10954
10955         c = *p++;
10956         for (q = optstr; *q != c;) {
10957                 if (*q == '\0') {
10958                         if (optstr[0] == ':') {
10959                                 sbuf[0] = c;
10960                                 /*sbuf[1] = '\0'; - already is */
10961                                 setvar0("OPTARG", sbuf);
10962                         } else {
10963                                 fprintf(stderr, "Illegal option -%c\n", c);
10964                                 unsetvar("OPTARG");
10965                         }
10966                         c = '?';
10967                         goto out;
10968                 }
10969                 if (*++q == ':')
10970                         q++;
10971         }
10972
10973         if (*++q == ':') {
10974                 if (*p == '\0' && (p = *optnext) == NULL) {
10975                         if (optstr[0] == ':') {
10976                                 sbuf[0] = c;
10977                                 /*sbuf[1] = '\0'; - already is */
10978                                 setvar0("OPTARG", sbuf);
10979                                 c = ':';
10980                         } else {
10981                                 fprintf(stderr, "No arg for -%c option\n", c);
10982                                 unsetvar("OPTARG");
10983                                 c = '?';
10984                         }
10985                         goto out;
10986                 }
10987
10988                 if (p == *optnext)
10989                         optnext++;
10990                 setvar0("OPTARG", p);
10991                 p = NULL;
10992         } else
10993                 setvar0("OPTARG", nullstr);
10994  out:
10995         ind = optnext - optfirst + 1;
10996         setvar("OPTIND", itoa(ind), VNOFUNC);
10997         sbuf[0] = c;
10998         /*sbuf[1] = '\0'; - already is */
10999         setvar0(optvar, sbuf);
11000
11001         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11002         shellparam.optind = ind;
11003
11004         return done;
11005 }
11006
11007 /*
11008  * The getopts builtin.  Shellparam.optnext points to the next argument
11009  * to be processed.  Shellparam.optptr points to the next character to
11010  * be processed in the current argument.  If shellparam.optnext is NULL,
11011  * then it's the first time getopts has been called.
11012  */
11013 static int FAST_FUNC
11014 getoptscmd(int argc, char **argv)
11015 {
11016         char **optbase;
11017
11018         if (argc < 3)
11019                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11020         if (argc == 3) {
11021                 optbase = shellparam.p;
11022                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11023                         shellparam.optind = 1;
11024                         shellparam.optoff = -1;
11025                 }
11026         } else {
11027                 optbase = &argv[3];
11028                 if ((unsigned)shellparam.optind > argc - 2) {
11029                         shellparam.optind = 1;
11030                         shellparam.optoff = -1;
11031                 }
11032         }
11033
11034         return getopts(argv[1], argv[2], optbase);
11035 }
11036 #endif /* ASH_GETOPTS */
11037
11038
11039 /* ============ Shell parser */
11040
11041 struct heredoc {
11042         struct heredoc *next;   /* next here document in list */
11043         union node *here;       /* redirection node */
11044         char *eofmark;          /* string indicating end of input */
11045         smallint striptabs;     /* if set, strip leading tabs */
11046 };
11047
11048 static smallint tokpushback;           /* last token pushed back */
11049 static smallint quoteflag;             /* set if (part of) last token was quoted */
11050 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11051 static struct heredoc *heredoclist;    /* list of here documents to read */
11052 static char *wordtext;                 /* text of last word returned by readtoken */
11053 static struct nodelist *backquotelist;
11054 static union node *redirnode;
11055 static struct heredoc *heredoc;
11056
11057 static const char *
11058 tokname(char *buf, int tok)
11059 {
11060         if (tok < TSEMI)
11061                 return tokname_array[tok];
11062         sprintf(buf, "\"%s\"", tokname_array[tok]);
11063         return buf;
11064 }
11065
11066 /* raise_error_unexpected_syntax:
11067  * Called when an unexpected token is read during the parse.  The argument
11068  * is the token that is expected, or -1 if more than one type of token can
11069  * occur at this point.
11070  */
11071 static void raise_error_unexpected_syntax(int) NORETURN;
11072 static void
11073 raise_error_unexpected_syntax(int token)
11074 {
11075         char msg[64];
11076         char buf[16];
11077         int l;
11078
11079         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11080         if (token >= 0)
11081                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11082         raise_error_syntax(msg);
11083         /* NOTREACHED */
11084 }
11085
11086 /* parsing is heavily cross-recursive, need these forward decls */
11087 static union node *andor(void);
11088 static union node *pipeline(void);
11089 static union node *parse_command(void);
11090 static void parseheredoc(void);
11091 static int peektoken(void);
11092 static int readtoken(void);
11093
11094 static union node *
11095 list(int nlflag)
11096 {
11097         union node *n1, *n2, *n3;
11098         int tok;
11099
11100         n1 = NULL;
11101         for (;;) {
11102                 switch (peektoken()) {
11103                 case TNL:
11104                         if (!(nlflag & 1))
11105                                 break;
11106                         parseheredoc();
11107                         return n1;
11108
11109                 case TEOF:
11110                         if (!n1 && (nlflag & 1))
11111                                 n1 = NODE_EOF;
11112                         parseheredoc();
11113                         return n1;
11114                 }
11115
11116                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11117                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11118                         return n1;
11119                 nlflag |= 2;
11120
11121                 n2 = andor();
11122                 tok = readtoken();
11123                 if (tok == TBACKGND) {
11124                         if (n2->type == NPIPE) {
11125                                 n2->npipe.pipe_backgnd = 1;
11126                         } else {
11127                                 if (n2->type != NREDIR) {
11128                                         n3 = stzalloc(sizeof(struct nredir));
11129                                         n3->nredir.n = n2;
11130                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11131                                         n2 = n3;
11132                                 }
11133                                 n2->type = NBACKGND;
11134                         }
11135                 }
11136                 if (n1 == NULL) {
11137                         n1 = n2;
11138                 } else {
11139                         n3 = stzalloc(sizeof(struct nbinary));
11140                         n3->type = NSEMI;
11141                         n3->nbinary.ch1 = n1;
11142                         n3->nbinary.ch2 = n2;
11143                         n1 = n3;
11144                 }
11145                 switch (tok) {
11146                 case TNL:
11147                 case TEOF:
11148                         tokpushback = 1;
11149                         /* fall through */
11150                 case TBACKGND:
11151                 case TSEMI:
11152                         break;
11153                 default:
11154                         if ((nlflag & 1))
11155                                 raise_error_unexpected_syntax(-1);
11156                         tokpushback = 1;
11157                         return n1;
11158                 }
11159         }
11160 }
11161
11162 static union node *
11163 andor(void)
11164 {
11165         union node *n1, *n2, *n3;
11166         int t;
11167
11168         n1 = pipeline();
11169         for (;;) {
11170                 t = readtoken();
11171                 if (t == TAND) {
11172                         t = NAND;
11173                 } else if (t == TOR) {
11174                         t = NOR;
11175                 } else {
11176                         tokpushback = 1;
11177                         return n1;
11178                 }
11179                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11180                 n2 = pipeline();
11181                 n3 = stzalloc(sizeof(struct nbinary));
11182                 n3->type = t;
11183                 n3->nbinary.ch1 = n1;
11184                 n3->nbinary.ch2 = n2;
11185                 n1 = n3;
11186         }
11187 }
11188
11189 static union node *
11190 pipeline(void)
11191 {
11192         union node *n1, *n2, *pipenode;
11193         struct nodelist *lp, *prev;
11194         int negate;
11195
11196         negate = 0;
11197         TRACE(("pipeline: entered\n"));
11198         if (readtoken() == TNOT) {
11199                 negate = !negate;
11200                 checkkwd = CHKKWD | CHKALIAS;
11201         } else
11202                 tokpushback = 1;
11203         n1 = parse_command();
11204         if (readtoken() == TPIPE) {
11205                 pipenode = stzalloc(sizeof(struct npipe));
11206                 pipenode->type = NPIPE;
11207                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11208                 lp = stzalloc(sizeof(struct nodelist));
11209                 pipenode->npipe.cmdlist = lp;
11210                 lp->n = n1;
11211                 do {
11212                         prev = lp;
11213                         lp = stzalloc(sizeof(struct nodelist));
11214                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11215                         lp->n = parse_command();
11216                         prev->next = lp;
11217                 } while (readtoken() == TPIPE);
11218                 lp->next = NULL;
11219                 n1 = pipenode;
11220         }
11221         tokpushback = 1;
11222         if (negate) {
11223                 n2 = stzalloc(sizeof(struct nnot));
11224                 n2->type = NNOT;
11225                 n2->nnot.com = n1;
11226                 return n2;
11227         }
11228         return n1;
11229 }
11230
11231 static union node *
11232 makename(void)
11233 {
11234         union node *n;
11235
11236         n = stzalloc(sizeof(struct narg));
11237         n->type = NARG;
11238         /*n->narg.next = NULL; - stzalloc did it */
11239         n->narg.text = wordtext;
11240         n->narg.backquote = backquotelist;
11241         return n;
11242 }
11243
11244 static void
11245 fixredir(union node *n, const char *text, int err)
11246 {
11247         int fd;
11248
11249         TRACE(("Fix redir %s %d\n", text, err));
11250         if (!err)
11251                 n->ndup.vname = NULL;
11252
11253         fd = bb_strtou(text, NULL, 10);
11254         if (!errno && fd >= 0)
11255                 n->ndup.dupfd = fd;
11256         else if (LONE_DASH(text))
11257                 n->ndup.dupfd = -1;
11258         else {
11259                 if (err)
11260                         raise_error_syntax("bad fd number");
11261                 n->ndup.vname = makename();
11262         }
11263 }
11264
11265 static void
11266 parsefname(void)
11267 {
11268         union node *n = redirnode;
11269
11270         if (n->type == NHERE)
11271                 checkkwd = CHKEOFMARK;
11272         if (readtoken() != TWORD)
11273                 raise_error_unexpected_syntax(-1);
11274         if (n->type == NHERE) {
11275                 struct heredoc *here = heredoc;
11276                 struct heredoc *p;
11277
11278                 if (quoteflag == 0)
11279                         n->type = NXHERE;
11280                 TRACE(("Here document %d\n", n->type));
11281                 rmescapes(wordtext, 0);
11282                 here->eofmark = wordtext;
11283                 here->next = NULL;
11284                 if (heredoclist == NULL)
11285                         heredoclist = here;
11286                 else {
11287                         for (p = heredoclist; p->next; p = p->next)
11288                                 continue;
11289                         p->next = here;
11290                 }
11291         } else if (n->type == NTOFD || n->type == NFROMFD) {
11292                 fixredir(n, wordtext, 0);
11293         } else {
11294                 n->nfile.fname = makename();
11295         }
11296 }
11297
11298 static union node *
11299 simplecmd(void)
11300 {
11301         union node *args, **app;
11302         union node *n = NULL;
11303         union node *vars, **vpp;
11304         union node **rpp, *redir;
11305         int savecheckkwd;
11306 #if BASH_TEST2
11307         smallint double_brackets_flag = 0;
11308 #endif
11309         IF_BASH_FUNCTION(smallint function_flag = 0;)
11310
11311         args = NULL;
11312         app = &args;
11313         vars = NULL;
11314         vpp = &vars;
11315         redir = NULL;
11316         rpp = &redir;
11317
11318         savecheckkwd = CHKALIAS;
11319         for (;;) {
11320                 int t;
11321                 checkkwd = savecheckkwd;
11322                 t = readtoken();
11323                 switch (t) {
11324 #if BASH_FUNCTION
11325                 case TFUNCTION:
11326                         if (peektoken() != TWORD)
11327                                 raise_error_unexpected_syntax(TWORD);
11328                         function_flag = 1;
11329                         break;
11330 #endif
11331 #if BASH_TEST2
11332                 case TAND: /* "&&" */
11333                 case TOR: /* "||" */
11334                         if (!double_brackets_flag) {
11335                                 tokpushback = 1;
11336                                 goto out;
11337                         }
11338                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11339 #endif
11340                 case TWORD:
11341                         n = stzalloc(sizeof(struct narg));
11342                         n->type = NARG;
11343                         /*n->narg.next = NULL; - stzalloc did it */
11344                         n->narg.text = wordtext;
11345 #if BASH_TEST2
11346                         if (strcmp("[[", wordtext) == 0)
11347                                 double_brackets_flag = 1;
11348                         else if (strcmp("]]", wordtext) == 0)
11349                                 double_brackets_flag = 0;
11350 #endif
11351                         n->narg.backquote = backquotelist;
11352                         if (savecheckkwd && isassignment(wordtext)) {
11353                                 *vpp = n;
11354                                 vpp = &n->narg.next;
11355                         } else {
11356                                 *app = n;
11357                                 app = &n->narg.next;
11358                                 savecheckkwd = 0;
11359                         }
11360 #if BASH_FUNCTION
11361                         if (function_flag) {
11362                                 checkkwd = CHKNL | CHKKWD;
11363                                 switch (peektoken()) {
11364                                 case TBEGIN:
11365                                 case TIF:
11366                                 case TCASE:
11367                                 case TUNTIL:
11368                                 case TWHILE:
11369                                 case TFOR:
11370                                         goto do_func;
11371                                 case TLP:
11372                                         function_flag = 0;
11373                                         break;
11374                                 case TWORD:
11375                                         if (strcmp("[[", wordtext) == 0)
11376                                                 goto do_func;
11377                                         /* fall through */
11378                                 default:
11379                                         raise_error_unexpected_syntax(-1);
11380                                 }
11381                         }
11382 #endif
11383                         break;
11384                 case TREDIR:
11385                         *rpp = n = redirnode;
11386                         rpp = &n->nfile.next;
11387                         parsefname();   /* read name of redirection file */
11388                         break;
11389                 case TLP:
11390  IF_BASH_FUNCTION(do_func:)
11391                         if (args && app == &args->narg.next
11392                          && !vars && !redir
11393                         ) {
11394                                 struct builtincmd *bcmd;
11395                                 const char *name;
11396
11397                                 /* We have a function */
11398                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11399                                         raise_error_unexpected_syntax(TRP);
11400                                 name = n->narg.text;
11401                                 if (!goodname(name)
11402                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11403                                 ) {
11404                                         raise_error_syntax("bad function name");
11405                                 }
11406                                 n->type = NDEFUN;
11407                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11408                                 n->narg.next = parse_command();
11409                                 return n;
11410                         }
11411                         IF_BASH_FUNCTION(function_flag = 0;)
11412                         /* fall through */
11413                 default:
11414                         tokpushback = 1;
11415                         goto out;
11416                 }
11417         }
11418  out:
11419         *app = NULL;
11420         *vpp = NULL;
11421         *rpp = NULL;
11422         n = stzalloc(sizeof(struct ncmd));
11423         n->type = NCMD;
11424         n->ncmd.args = args;
11425         n->ncmd.assign = vars;
11426         n->ncmd.redirect = redir;
11427         return n;
11428 }
11429
11430 static union node *
11431 parse_command(void)
11432 {
11433         union node *n1, *n2;
11434         union node *ap, **app;
11435         union node *cp, **cpp;
11436         union node *redir, **rpp;
11437         union node **rpp2;
11438         int t;
11439
11440         redir = NULL;
11441         rpp2 = &redir;
11442
11443         switch (readtoken()) {
11444         default:
11445                 raise_error_unexpected_syntax(-1);
11446                 /* NOTREACHED */
11447         case TIF:
11448                 n1 = stzalloc(sizeof(struct nif));
11449                 n1->type = NIF;
11450                 n1->nif.test = list(0);
11451                 if (readtoken() != TTHEN)
11452                         raise_error_unexpected_syntax(TTHEN);
11453                 n1->nif.ifpart = list(0);
11454                 n2 = n1;
11455                 while (readtoken() == TELIF) {
11456                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11457                         n2 = n2->nif.elsepart;
11458                         n2->type = NIF;
11459                         n2->nif.test = list(0);
11460                         if (readtoken() != TTHEN)
11461                                 raise_error_unexpected_syntax(TTHEN);
11462                         n2->nif.ifpart = list(0);
11463                 }
11464                 if (lasttoken == TELSE)
11465                         n2->nif.elsepart = list(0);
11466                 else {
11467                         n2->nif.elsepart = NULL;
11468                         tokpushback = 1;
11469                 }
11470                 t = TFI;
11471                 break;
11472         case TWHILE:
11473         case TUNTIL: {
11474                 int got;
11475                 n1 = stzalloc(sizeof(struct nbinary));
11476                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11477                 n1->nbinary.ch1 = list(0);
11478                 got = readtoken();
11479                 if (got != TDO) {
11480                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11481                                         got == TWORD ? wordtext : ""));
11482                         raise_error_unexpected_syntax(TDO);
11483                 }
11484                 n1->nbinary.ch2 = list(0);
11485                 t = TDONE;
11486                 break;
11487         }
11488         case TFOR:
11489                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11490                         raise_error_syntax("bad for loop variable");
11491                 n1 = stzalloc(sizeof(struct nfor));
11492                 n1->type = NFOR;
11493                 n1->nfor.var = wordtext;
11494                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11495                 if (readtoken() == TIN) {
11496                         app = &ap;
11497                         while (readtoken() == TWORD) {
11498                                 n2 = stzalloc(sizeof(struct narg));
11499                                 n2->type = NARG;
11500                                 /*n2->narg.next = NULL; - stzalloc did it */
11501                                 n2->narg.text = wordtext;
11502                                 n2->narg.backquote = backquotelist;
11503                                 *app = n2;
11504                                 app = &n2->narg.next;
11505                         }
11506                         *app = NULL;
11507                         n1->nfor.args = ap;
11508                         if (lasttoken != TNL && lasttoken != TSEMI)
11509                                 raise_error_unexpected_syntax(-1);
11510                 } else {
11511                         n2 = stzalloc(sizeof(struct narg));
11512                         n2->type = NARG;
11513                         /*n2->narg.next = NULL; - stzalloc did it */
11514                         n2->narg.text = (char *)dolatstr;
11515                         /*n2->narg.backquote = NULL;*/
11516                         n1->nfor.args = n2;
11517                         /*
11518                          * Newline or semicolon here is optional (but note
11519                          * that the original Bourne shell only allowed NL).
11520                          */
11521                         if (lasttoken != TSEMI)
11522                                 tokpushback = 1;
11523                 }
11524                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11525                 if (readtoken() != TDO)
11526                         raise_error_unexpected_syntax(TDO);
11527                 n1->nfor.body = list(0);
11528                 t = TDONE;
11529                 break;
11530         case TCASE:
11531                 n1 = stzalloc(sizeof(struct ncase));
11532                 n1->type = NCASE;
11533                 if (readtoken() != TWORD)
11534                         raise_error_unexpected_syntax(TWORD);
11535                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11536                 n2->type = NARG;
11537                 /*n2->narg.next = NULL; - stzalloc did it */
11538                 n2->narg.text = wordtext;
11539                 n2->narg.backquote = backquotelist;
11540                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11541                 if (readtoken() != TIN)
11542                         raise_error_unexpected_syntax(TIN);
11543                 cpp = &n1->ncase.cases;
11544  next_case:
11545                 checkkwd = CHKNL | CHKKWD;
11546                 t = readtoken();
11547                 while (t != TESAC) {
11548                         if (lasttoken == TLP)
11549                                 readtoken();
11550                         *cpp = cp = stzalloc(sizeof(struct nclist));
11551                         cp->type = NCLIST;
11552                         app = &cp->nclist.pattern;
11553                         for (;;) {
11554                                 *app = ap = stzalloc(sizeof(struct narg));
11555                                 ap->type = NARG;
11556                                 /*ap->narg.next = NULL; - stzalloc did it */
11557                                 ap->narg.text = wordtext;
11558                                 ap->narg.backquote = backquotelist;
11559                                 if (readtoken() != TPIPE)
11560                                         break;
11561                                 app = &ap->narg.next;
11562                                 readtoken();
11563                         }
11564                         //ap->narg.next = NULL;
11565                         if (lasttoken != TRP)
11566                                 raise_error_unexpected_syntax(TRP);
11567                         cp->nclist.body = list(2);
11568
11569                         cpp = &cp->nclist.next;
11570
11571                         checkkwd = CHKNL | CHKKWD;
11572                         t = readtoken();
11573                         if (t != TESAC) {
11574                                 if (t != TENDCASE)
11575                                         raise_error_unexpected_syntax(TENDCASE);
11576                                 goto next_case;
11577                         }
11578                 }
11579                 *cpp = NULL;
11580                 goto redir;
11581         case TLP:
11582                 n1 = stzalloc(sizeof(struct nredir));
11583                 n1->type = NSUBSHELL;
11584                 n1->nredir.n = list(0);
11585                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11586                 t = TRP;
11587                 break;
11588         case TBEGIN:
11589                 n1 = list(0);
11590                 t = TEND;
11591                 break;
11592         IF_BASH_FUNCTION(case TFUNCTION:)
11593         case TWORD:
11594         case TREDIR:
11595                 tokpushback = 1;
11596                 return simplecmd();
11597         }
11598
11599         if (readtoken() != t)
11600                 raise_error_unexpected_syntax(t);
11601
11602  redir:
11603         /* Now check for redirection which may follow command */
11604         checkkwd = CHKKWD | CHKALIAS;
11605         rpp = rpp2;
11606         while (readtoken() == TREDIR) {
11607                 *rpp = n2 = redirnode;
11608                 rpp = &n2->nfile.next;
11609                 parsefname();
11610         }
11611         tokpushback = 1;
11612         *rpp = NULL;
11613         if (redir) {
11614                 if (n1->type != NSUBSHELL) {
11615                         n2 = stzalloc(sizeof(struct nredir));
11616                         n2->type = NREDIR;
11617                         n2->nredir.n = n1;
11618                         n1 = n2;
11619                 }
11620                 n1->nredir.redirect = redir;
11621         }
11622         return n1;
11623 }
11624
11625 #if BASH_DOLLAR_SQUOTE
11626 static int
11627 decode_dollar_squote(void)
11628 {
11629         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11630         int c, cnt;
11631         char *p;
11632         char buf[4];
11633
11634         c = pgetc();
11635         p = strchr(C_escapes, c);
11636         if (p) {
11637                 buf[0] = c;
11638                 p = buf;
11639                 cnt = 3;
11640                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11641                         do {
11642                                 c = pgetc();
11643                                 *++p = c;
11644                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11645                         pungetc();
11646                 } else if (c == 'x') { /* \xHH */
11647                         do {
11648                                 c = pgetc();
11649                                 *++p = c;
11650                         } while (isxdigit(c) && --cnt);
11651                         pungetc();
11652                         if (cnt == 3) { /* \x but next char is "bad" */
11653                                 c = 'x';
11654                                 goto unrecognized;
11655                         }
11656                 } else { /* simple seq like \\ or \t */
11657                         p++;
11658                 }
11659                 *p = '\0';
11660                 p = buf;
11661                 c = bb_process_escape_sequence((void*)&p);
11662         } else { /* unrecognized "\z": print both chars unless ' or " */
11663                 if (c != '\'' && c != '"') {
11664  unrecognized:
11665                         c |= 0x100; /* "please encode \, then me" */
11666                 }
11667         }
11668         return c;
11669 }
11670 #endif
11671
11672 /* Used by expandstr to get here-doc like behaviour. */
11673 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11674
11675 static ALWAYS_INLINE int
11676 realeofmark(const char *eofmark)
11677 {
11678         return eofmark && eofmark != FAKEEOFMARK;
11679 }
11680
11681 /*
11682  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11683  * is not NULL, read a here document.  In the latter case, eofmark is the
11684  * word which marks the end of the document and striptabs is true if
11685  * leading tabs should be stripped from the document.  The argument c
11686  * is the first character of the input token or document.
11687  *
11688  * Because C does not have internal subroutines, I have simulated them
11689  * using goto's to implement the subroutine linkage.  The following macros
11690  * will run code that appears at the end of readtoken1.
11691  */
11692 #define CHECKEND()      {goto checkend; checkend_return:;}
11693 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11694 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11695 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11696 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11697 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11698 static int
11699 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11700 {
11701         /* NB: syntax parameter fits into smallint */
11702         /* c parameter is an unsigned char or PEOF or PEOA */
11703         char *out;
11704         size_t len;
11705         struct nodelist *bqlist;
11706         smallint quotef;
11707         smallint dblquote;
11708         smallint oldstyle;
11709         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11710         smallint pssyntax;   /* we are expanding a prompt string */
11711         int varnest;         /* levels of variables expansion */
11712         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11713         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11714         int dqvarnest;       /* levels of variables expansion within double quotes */
11715
11716         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11717
11718         startlinno = g_parsefile->linno;
11719         bqlist = NULL;
11720         quotef = 0;
11721         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11722 #if ENABLE_ASH_EXPAND_PRMT
11723         pssyntax = (syntax == PSSYNTAX);
11724         if (pssyntax)
11725                 syntax = DQSYNTAX;
11726 #else
11727         pssyntax = 0; /* constant */
11728 #endif
11729         dblquote = (syntax == DQSYNTAX);
11730         varnest = 0;
11731         IF_FEATURE_SH_MATH(arinest = 0;)
11732         IF_FEATURE_SH_MATH(parenlevel = 0;)
11733         dqvarnest = 0;
11734
11735         STARTSTACKSTR(out);
11736  loop:
11737         /* For each line, until end of word */
11738         CHECKEND();     /* set c to PEOF if at end of here document */
11739         for (;;) {      /* until end of line or end of word */
11740                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11741                 switch (SIT(c, syntax)) {
11742                 case CNL:       /* '\n' */
11743                         if (syntax == BASESYNTAX)
11744                                 goto endword;   /* exit outer loop */
11745                         USTPUTC(c, out);
11746                         nlprompt();
11747                         c = pgetc();
11748                         goto loop;              /* continue outer loop */
11749                 case CWORD:
11750                         USTPUTC(c, out);
11751                         break;
11752                 case CCTL:
11753 #if BASH_DOLLAR_SQUOTE
11754                         if (c == '\\' && bash_dollar_squote) {
11755                                 c = decode_dollar_squote();
11756                                 if (c == '\0') {
11757                                         /* skip $'\000', $'\x00' (like bash) */
11758                                         break;
11759                                 }
11760                                 if (c & 0x100) {
11761                                         /* Unknown escape. Encode as '\z' */
11762                                         c = (unsigned char)c;
11763                                         if (eofmark == NULL || dblquote)
11764                                                 USTPUTC(CTLESC, out);
11765                                         USTPUTC('\\', out);
11766                                 }
11767                         }
11768 #endif
11769                         if (eofmark == NULL || dblquote)
11770                                 USTPUTC(CTLESC, out);
11771                         USTPUTC(c, out);
11772                         break;
11773                 case CBACK:     /* backslash */
11774                         c = pgetc_without_PEOA();
11775                         if (c == PEOF) {
11776                                 USTPUTC(CTLESC, out);
11777                                 USTPUTC('\\', out);
11778                                 pungetc();
11779                         } else if (c == '\n') {
11780                                 nlprompt();
11781                         } else {
11782                                 if (pssyntax && c == '$') {
11783                                         USTPUTC(CTLESC, out);
11784                                         USTPUTC('\\', out);
11785                                 }
11786                                 /* Backslash is retained if we are in "str" and next char isn't special */
11787                                 if (dblquote
11788                                  && c != '\\'
11789                                  && c != '`'
11790                                  && c != '$'
11791                                  && (c != '"' || eofmark != NULL)
11792                                 ) {
11793                                         USTPUTC('\\', out);
11794                                 }
11795                                 USTPUTC(CTLESC, out);
11796                                 USTPUTC(c, out);
11797                                 quotef = 1;
11798                         }
11799                         break;
11800                 case CSQUOTE:
11801                         syntax = SQSYNTAX;
11802  quotemark:
11803                         if (eofmark == NULL) {
11804                                 USTPUTC(CTLQUOTEMARK, out);
11805                         }
11806                         break;
11807                 case CDQUOTE:
11808                         syntax = DQSYNTAX;
11809                         dblquote = 1;
11810                         goto quotemark;
11811                 case CENDQUOTE:
11812                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11813                         if (eofmark != NULL && varnest == 0) {
11814                                 USTPUTC(c, out);
11815                         } else {
11816                                 if (dqvarnest == 0) {
11817                                         syntax = BASESYNTAX;
11818                                         dblquote = 0;
11819                                 }
11820                                 quotef = 1;
11821                                 goto quotemark;
11822                         }
11823                         break;
11824                 case CVAR:      /* '$' */
11825                         PARSESUB();             /* parse substitution */
11826                         break;
11827                 case CENDVAR:   /* '}' */
11828                         if (varnest > 0) {
11829                                 varnest--;
11830                                 if (dqvarnest > 0) {
11831                                         dqvarnest--;
11832                                 }
11833                                 c = CTLENDVAR;
11834                         }
11835                         USTPUTC(c, out);
11836                         break;
11837 #if ENABLE_FEATURE_SH_MATH
11838                 case CLP:       /* '(' in arithmetic */
11839                         parenlevel++;
11840                         USTPUTC(c, out);
11841                         break;
11842                 case CRP:       /* ')' in arithmetic */
11843                         if (parenlevel > 0) {
11844                                 parenlevel--;
11845                         } else {
11846                                 if (pgetc_eatbnl() == ')') {
11847                                         c = CTLENDARI;
11848                                         if (--arinest == 0) {
11849                                                 syntax = prevsyntax;
11850                                         }
11851                                 } else {
11852                                         /*
11853                                          * unbalanced parens
11854                                          * (don't 2nd guess - no error)
11855                                          */
11856                                         pungetc();
11857                                 }
11858                         }
11859                         USTPUTC(c, out);
11860                         break;
11861 #endif
11862                 case CBQUOTE:   /* '`' */
11863                         PARSEBACKQOLD();
11864                         break;
11865                 case CENDFILE:
11866                         goto endword;           /* exit outer loop */
11867                 case CIGN:
11868                         break;
11869                 default:
11870                         if (varnest == 0) {
11871 #if BASH_REDIR_OUTPUT
11872                                 if (c == '&') {
11873 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11874                                         if (pgetc() == '>')
11875                                                 c = 0x100 + '>'; /* flag &> */
11876                                         pungetc();
11877                                 }
11878 #endif
11879                                 goto endword;   /* exit outer loop */
11880                         }
11881                         IF_ASH_ALIAS(if (c != PEOA))
11882                                 USTPUTC(c, out);
11883                 }
11884                 c = pgetc();
11885         } /* for (;;) */
11886  endword:
11887
11888 #if ENABLE_FEATURE_SH_MATH
11889         if (syntax == ARISYNTAX)
11890                 raise_error_syntax("missing '))'");
11891 #endif
11892         if (syntax != BASESYNTAX && eofmark == NULL)
11893                 raise_error_syntax("unterminated quoted string");
11894         if (varnest != 0) {
11895                 startlinno = g_parsefile->linno;
11896                 /* { */
11897                 raise_error_syntax("missing '}'");
11898         }
11899         USTPUTC('\0', out);
11900         len = out - (char *)stackblock();
11901         out = stackblock();
11902         if (eofmark == NULL) {
11903                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11904                  && quotef == 0
11905                 ) {
11906                         if (isdigit_str9(out)) {
11907                                 PARSEREDIR(); /* passed as params: out, c */
11908                                 lasttoken = TREDIR;
11909                                 return lasttoken;
11910                         }
11911                         /* else: non-number X seen, interpret it
11912                          * as "NNNX>file" = "NNNX >file" */
11913                 }
11914                 pungetc();
11915         }
11916         quoteflag = quotef;
11917         backquotelist = bqlist;
11918         grabstackblock(len);
11919         wordtext = out;
11920         lasttoken = TWORD;
11921         return lasttoken;
11922 /* end of readtoken routine */
11923
11924 /*
11925  * Check to see whether we are at the end of the here document.  When this
11926  * is called, c is set to the first character of the next input line.  If
11927  * we are at the end of the here document, this routine sets the c to PEOF.
11928  */
11929 checkend: {
11930         if (realeofmark(eofmark)) {
11931                 int markloc;
11932                 char *p;
11933
11934 #if ENABLE_ASH_ALIAS
11935                 if (c == PEOA)
11936                         c = pgetc_without_PEOA();
11937 #endif
11938                 if (striptabs) {
11939                         while (c == '\t') {
11940                                 c = pgetc_without_PEOA();
11941                         }
11942                 }
11943
11944                 markloc = out - (char *)stackblock();
11945                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11946                         if (c != *p)
11947                                 goto more_heredoc;
11948
11949                         c = pgetc_without_PEOA();
11950                 }
11951
11952                 if (c == '\n' || c == PEOF) {
11953                         c = PEOF;
11954                         g_parsefile->linno++;
11955                         needprompt = doprompt;
11956                 } else {
11957                         int len_here;
11958
11959  more_heredoc:
11960                         p = (char *)stackblock() + markloc + 1;
11961                         len_here = out - p;
11962
11963                         if (len_here) {
11964                                 len_here -= (c >= PEOF);
11965                                 c = p[-1];
11966
11967                                 if (len_here) {
11968                                         char *str;
11969
11970                                         str = alloca(len_here + 1);
11971                                         *(char *)mempcpy(str, p, len_here) = '\0';
11972
11973                                         pushstring(str, NULL);
11974                                 }
11975                         }
11976                 }
11977
11978                 STADJUST((char *)stackblock() + markloc - out, out);
11979         }
11980         goto checkend_return;
11981 }
11982
11983 /*
11984  * Parse a redirection operator.  The variable "out" points to a string
11985  * specifying the fd to be redirected.  The variable "c" contains the
11986  * first character of the redirection operator.
11987  */
11988 parseredir: {
11989         /* out is already checked to be a valid number or "" */
11990         int fd = (*out == '\0' ? -1 : atoi(out));
11991         union node *np;
11992
11993         np = stzalloc(sizeof(struct nfile));
11994         if (c == '>') {
11995                 np->nfile.fd = 1;
11996                 c = pgetc();
11997                 if (c == '>')
11998                         np->type = NAPPEND;
11999                 else if (c == '|')
12000                         np->type = NCLOBBER;
12001                 else if (c == '&')
12002                         np->type = NTOFD;
12003                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12004                 else {
12005                         np->type = NTO;
12006                         pungetc();
12007                 }
12008         }
12009 #if BASH_REDIR_OUTPUT
12010         else if (c == 0x100 + '>') { /* this flags &> redirection */
12011                 np->nfile.fd = 1;
12012                 pgetc(); /* this is '>', no need to check */
12013                 np->type = NTO2;
12014         }
12015 #endif
12016         else { /* c == '<' */
12017                 /*np->nfile.fd = 0; - stzalloc did it */
12018                 c = pgetc();
12019                 switch (c) {
12020                 case '<':
12021                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12022                                 np = stzalloc(sizeof(struct nhere));
12023                                 /*np->nfile.fd = 0; - stzalloc did it */
12024                         }
12025                         np->type = NHERE;
12026                         heredoc = stzalloc(sizeof(struct heredoc));
12027                         heredoc->here = np;
12028                         c = pgetc();
12029                         if (c == '-') {
12030                                 heredoc->striptabs = 1;
12031                         } else {
12032                                 /*heredoc->striptabs = 0; - stzalloc did it */
12033                                 pungetc();
12034                         }
12035                         break;
12036
12037                 case '&':
12038                         np->type = NFROMFD;
12039                         break;
12040
12041                 case '>':
12042                         np->type = NFROMTO;
12043                         break;
12044
12045                 default:
12046                         np->type = NFROM;
12047                         pungetc();
12048                         break;
12049                 }
12050         }
12051         if (fd >= 0)
12052                 np->nfile.fd = fd;
12053         redirnode = np;
12054         goto parseredir_return;
12055 }
12056
12057 /*
12058  * Parse a substitution.  At this point, we have read the dollar sign
12059  * and nothing else.
12060  */
12061
12062 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12063  * (assuming ascii char codes, as the original implementation did) */
12064 #define is_special(c) \
12065         (((unsigned)(c) - 33 < 32) \
12066                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12067 parsesub: {
12068         unsigned char subtype;
12069         int typeloc;
12070
12071         c = pgetc_eatbnl();
12072         if ((checkkwd & CHKEOFMARK)
12073          || c > 255 /* PEOA or PEOF */
12074          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12075         ) {
12076 #if BASH_DOLLAR_SQUOTE
12077                 if (syntax != DQSYNTAX && c == '\'')
12078                         bash_dollar_squote = 1;
12079                 else
12080 #endif
12081                         USTPUTC('$', out);
12082                 pungetc();
12083         } else if (c == '(') {
12084                 /* $(command) or $((arith)) */
12085                 if (pgetc_eatbnl() == '(') {
12086 #if ENABLE_FEATURE_SH_MATH
12087                         PARSEARITH();
12088 #else
12089                         raise_error_syntax("support for $((arith)) is disabled");
12090 #endif
12091                 } else {
12092                         pungetc();
12093                         PARSEBACKQNEW();
12094                 }
12095         } else {
12096                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12097                 USTPUTC(CTLVAR, out);
12098                 typeloc = out - (char *)stackblock();
12099                 STADJUST(1, out);
12100                 subtype = VSNORMAL;
12101                 if (c == '{') {
12102                         c = pgetc_eatbnl();
12103                         subtype = 0;
12104                 }
12105  varname:
12106                 if (is_name(c)) {
12107                         /* $[{[#]]NAME[}] */
12108                         do {
12109                                 STPUTC(c, out);
12110                                 c = pgetc_eatbnl();
12111                         } while (is_in_name(c));
12112                 } else if (isdigit(c)) {
12113                         /* $[{[#]]NUM[}] */
12114                         do {
12115                                 STPUTC(c, out);
12116                                 c = pgetc_eatbnl();
12117                         } while (isdigit(c));
12118                 } else if (is_special(c)) {
12119                         /* $[{[#]]<specialchar>[}] */
12120                         int cc = c;
12121
12122                         c = pgetc_eatbnl();
12123                         if (!subtype && cc == '#') {
12124                                 subtype = VSLENGTH;
12125                                 if (c == '_' || isalnum(c))
12126                                         goto varname;
12127                                 cc = c;
12128                                 c = pgetc_eatbnl();
12129                                 if (cc == '}' || c != '}') {
12130                                         pungetc();
12131                                         subtype = 0;
12132                                         c = cc;
12133                                         cc = '#';
12134                                 }
12135                         }
12136                         USTPUTC(cc, out);
12137                 } else {
12138                         goto badsub;
12139                 }
12140                 if (c != '}' && subtype == VSLENGTH) {
12141                         /* ${#VAR didn't end with } */
12142                         goto badsub;
12143                 }
12144
12145                 if (subtype == 0) {
12146                         static const char types[] ALIGN1 = "}-+?=";
12147                         /* ${VAR...} but not $VAR or ${#VAR} */
12148                         /* c == first char after VAR */
12149                         switch (c) {
12150                         case ':':
12151                                 c = pgetc_eatbnl();
12152 #if BASH_SUBSTR
12153                                 /* This check is only needed to not misinterpret
12154                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12155                                  * constructs.
12156                                  */
12157                                 if (!strchr(types, c)) {
12158                                         subtype = VSSUBSTR;
12159                                         pungetc();
12160                                         break; /* "goto badsub" is bigger (!) */
12161                                 }
12162 #endif
12163                                 subtype = VSNUL;
12164                                 /*FALLTHROUGH*/
12165                         default: {
12166                                 const char *p = strchr(types, c);
12167                                 if (p == NULL)
12168                                         break;
12169                                 subtype |= p - types + VSNORMAL;
12170                                 break;
12171                         }
12172                         case '%':
12173                         case '#': {
12174                                 int cc = c;
12175                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12176                                 c = pgetc_eatbnl();
12177                                 if (c != cc)
12178                                         goto badsub;
12179                                 subtype++;
12180                                 break;
12181                         }
12182 #if BASH_PATTERN_SUBST
12183                         case '/':
12184                                 /* ${v/[/]pattern/repl} */
12185 //TODO: encode pattern and repl separately.
12186 // Currently ${v/$var_with_slash/repl} is horribly broken
12187                                 subtype = VSREPLACE;
12188                                 c = pgetc_eatbnl();
12189                                 if (c != '/')
12190                                         goto badsub;
12191                                 subtype++; /* VSREPLACEALL */
12192                                 break;
12193 #endif
12194                         }
12195                 } else {
12196  badsub:
12197                         pungetc();
12198                 }
12199                 ((unsigned char *)stackblock())[typeloc] = subtype;
12200                 if (subtype != VSNORMAL) {
12201                         varnest++;
12202                         if (dblquote)
12203                                 dqvarnest++;
12204                 }
12205                 STPUTC('=', out);
12206         }
12207         goto parsesub_return;
12208 }
12209
12210 /*
12211  * Called to parse command substitutions.  Newstyle is set if the command
12212  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12213  * list of commands (passed by reference), and savelen is the number of
12214  * characters on the top of the stack which must be preserved.
12215  */
12216 parsebackq: {
12217         struct nodelist **nlpp;
12218         union node *n;
12219         char *str;
12220         size_t savelen;
12221         smallint saveprompt = 0;
12222
12223         str = NULL;
12224         savelen = out - (char *)stackblock();
12225         if (savelen > 0) {
12226                 /*
12227                  * FIXME: this can allocate very large block on stack and SEGV.
12228                  * Example:
12229                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12230                  * allocates 100kb for every command subst. With about
12231                  * a hundred command substitutions stack overflows.
12232                  * With larger prepended string, SEGV happens sooner.
12233                  */
12234                 str = alloca(savelen);
12235                 memcpy(str, stackblock(), savelen);
12236         }
12237
12238         if (oldstyle) {
12239                 /* We must read until the closing backquote, giving special
12240                  * treatment to some slashes, and then push the string and
12241                  * reread it as input, interpreting it normally.
12242                  */
12243                 char *pout;
12244                 size_t psavelen;
12245                 char *pstr;
12246
12247                 STARTSTACKSTR(pout);
12248                 for (;;) {
12249                         int pc;
12250
12251                         setprompt_if(needprompt, 2);
12252                         pc = pgetc();
12253                         switch (pc) {
12254                         case '`':
12255                                 goto done;
12256
12257                         case '\\':
12258                                 pc = pgetc();
12259                                 if (pc == '\n') {
12260                                         nlprompt();
12261                                         /*
12262                                          * If eating a newline, avoid putting
12263                                          * the newline into the new character
12264                                          * stream (via the STPUTC after the
12265                                          * switch).
12266                                          */
12267                                         continue;
12268                                 }
12269                                 if (pc != '\\' && pc != '`' && pc != '$'
12270                                  && (!dblquote || pc != '"')
12271                                 ) {
12272                                         STPUTC('\\', pout);
12273                                 }
12274                                 if (pc <= 255 /* not PEOA or PEOF */) {
12275                                         break;
12276                                 }
12277                                 /* fall through */
12278
12279                         case PEOF:
12280                         IF_ASH_ALIAS(case PEOA:)
12281                                 startlinno = g_parsefile->linno;
12282                                 raise_error_syntax("EOF in backquote substitution");
12283
12284                         case '\n':
12285                                 nlnoprompt();
12286                                 break;
12287
12288                         default:
12289                                 break;
12290                         }
12291                         STPUTC(pc, pout);
12292                 }
12293  done:
12294                 STPUTC('\0', pout);
12295                 psavelen = pout - (char *)stackblock();
12296                 if (psavelen > 0) {
12297                         pstr = grabstackstr(pout);
12298                         setinputstring(pstr);
12299                 }
12300         }
12301         nlpp = &bqlist;
12302         while (*nlpp)
12303                 nlpp = &(*nlpp)->next;
12304         *nlpp = stzalloc(sizeof(**nlpp));
12305         /* (*nlpp)->next = NULL; - stzalloc did it */
12306
12307         if (oldstyle) {
12308                 saveprompt = doprompt;
12309                 doprompt = 0;
12310         }
12311
12312         n = list(2);
12313
12314         if (oldstyle)
12315                 doprompt = saveprompt;
12316         else if (readtoken() != TRP)
12317                 raise_error_unexpected_syntax(TRP);
12318
12319         (*nlpp)->n = n;
12320         if (oldstyle) {
12321                 /*
12322                  * Start reading from old file again, ignoring any pushed back
12323                  * tokens left from the backquote parsing
12324                  */
12325                 popfile();
12326                 tokpushback = 0;
12327         }
12328         while (stackblocksize() <= savelen)
12329                 growstackblock();
12330         STARTSTACKSTR(out);
12331         if (str) {
12332                 memcpy(out, str, savelen);
12333                 STADJUST(savelen, out);
12334         }
12335         USTPUTC(CTLBACKQ, out);
12336         if (oldstyle)
12337                 goto parsebackq_oldreturn;
12338         goto parsebackq_newreturn;
12339 }
12340
12341 #if ENABLE_FEATURE_SH_MATH
12342 /*
12343  * Parse an arithmetic expansion (indicate start of one and set state)
12344  */
12345 parsearith: {
12346         if (++arinest == 1) {
12347                 prevsyntax = syntax;
12348                 syntax = ARISYNTAX;
12349         }
12350         USTPUTC(CTLARI, out);
12351         goto parsearith_return;
12352 }
12353 #endif
12354 } /* end of readtoken */
12355
12356 /*
12357  * Read the next input token.
12358  * If the token is a word, we set backquotelist to the list of cmds in
12359  *      backquotes.  We set quoteflag to true if any part of the word was
12360  *      quoted.
12361  * If the token is TREDIR, then we set redirnode to a structure containing
12362  *      the redirection.
12363  * In all cases, the variable startlinno is set to the number of the line
12364  *      on which the token starts.
12365  *
12366  * [Change comment:  here documents and internal procedures]
12367  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12368  *  word parsing code into a separate routine.  In this case, readtoken
12369  *  doesn't need to have any internal procedures, but parseword does.
12370  *  We could also make parseoperator in essence the main routine, and
12371  *  have parseword (readtoken1?) handle both words and redirection.]
12372  */
12373 #define NEW_xxreadtoken
12374 #ifdef NEW_xxreadtoken
12375 /* singles must be first! */
12376 static const char xxreadtoken_chars[7] ALIGN1 = {
12377         '\n', '(', ')', /* singles */
12378         '&', '|', ';',  /* doubles */
12379         0
12380 };
12381
12382 #define xxreadtoken_singles 3
12383 #define xxreadtoken_doubles 3
12384
12385 static const char xxreadtoken_tokens[] ALIGN1 = {
12386         TNL, TLP, TRP,          /* only single occurrence allowed */
12387         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12388         TEOF,                   /* corresponds to trailing nul */
12389         TAND, TOR, TENDCASE     /* if double occurrence */
12390 };
12391
12392 static int
12393 xxreadtoken(void)
12394 {
12395         int c;
12396
12397         if (tokpushback) {
12398                 tokpushback = 0;
12399                 return lasttoken;
12400         }
12401         setprompt_if(needprompt, 2);
12402         startlinno = g_parsefile->linno;
12403         for (;;) {                      /* until token or start of word found */
12404                 c = pgetc();
12405                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12406                         continue;
12407
12408                 if (c == '#') {
12409                         while ((c = pgetc()) != '\n' && c != PEOF)
12410                                 continue;
12411                         pungetc();
12412                 } else if (c == '\\') {
12413                         if (pgetc() != '\n') {
12414                                 pungetc();
12415                                 break; /* return readtoken1(...) */
12416                         }
12417                         nlprompt();
12418                 } else {
12419                         const char *p;
12420
12421                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12422                         if (c != PEOF) {
12423                                 if (c == '\n') {
12424                                         nlnoprompt();
12425                                 }
12426
12427                                 p = strchr(xxreadtoken_chars, c);
12428                                 if (p == NULL)
12429                                         break; /* return readtoken1(...) */
12430
12431                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12432                                         int cc = pgetc();
12433                                         if (cc == c) {    /* double occurrence? */
12434                                                 p += xxreadtoken_doubles + 1;
12435                                         } else {
12436                                                 pungetc();
12437 #if BASH_REDIR_OUTPUT
12438                                                 if (c == '&' && cc == '>') /* &> */
12439                                                         break; /* return readtoken1(...) */
12440 #endif
12441                                         }
12442                                 }
12443                         }
12444                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12445                         return lasttoken;
12446                 }
12447         } /* for (;;) */
12448
12449         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12450 }
12451 #else /* old xxreadtoken */
12452 #define RETURN(token)   return lasttoken = token
12453 static int
12454 xxreadtoken(void)
12455 {
12456         int c;
12457
12458         if (tokpushback) {
12459                 tokpushback = 0;
12460                 return lasttoken;
12461         }
12462         setprompt_if(needprompt, 2);
12463         startlinno = g_parsefile->linno;
12464         for (;;) {      /* until token or start of word found */
12465                 c = pgetc();
12466                 switch (c) {
12467                 case ' ': case '\t':
12468                 IF_ASH_ALIAS(case PEOA:)
12469                         continue;
12470                 case '#':
12471                         while ((c = pgetc()) != '\n' && c != PEOF)
12472                                 continue;
12473                         pungetc();
12474                         continue;
12475                 case '\\':
12476                         if (pgetc() == '\n') {
12477                                 nlprompt();
12478                                 continue;
12479                         }
12480                         pungetc();
12481                         goto breakloop;
12482                 case '\n':
12483                         nlnoprompt();
12484                         RETURN(TNL);
12485                 case PEOF:
12486                         RETURN(TEOF);
12487                 case '&':
12488                         if (pgetc() == '&')
12489                                 RETURN(TAND);
12490                         pungetc();
12491                         RETURN(TBACKGND);
12492                 case '|':
12493                         if (pgetc() == '|')
12494                                 RETURN(TOR);
12495                         pungetc();
12496                         RETURN(TPIPE);
12497                 case ';':
12498                         if (pgetc() == ';')
12499                                 RETURN(TENDCASE);
12500                         pungetc();
12501                         RETURN(TSEMI);
12502                 case '(':
12503                         RETURN(TLP);
12504                 case ')':
12505                         RETURN(TRP);
12506                 default:
12507                         goto breakloop;
12508                 }
12509         }
12510  breakloop:
12511         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12512 #undef RETURN
12513 }
12514 #endif /* old xxreadtoken */
12515
12516 static int
12517 readtoken(void)
12518 {
12519         int t;
12520         int kwd = checkkwd;
12521 #if DEBUG
12522         smallint alreadyseen = tokpushback;
12523 #endif
12524
12525 #if ENABLE_ASH_ALIAS
12526  top:
12527 #endif
12528
12529         t = xxreadtoken();
12530
12531         /*
12532          * eat newlines
12533          */
12534         if (kwd & CHKNL) {
12535                 while (t == TNL) {
12536                         parseheredoc();
12537                         t = xxreadtoken();
12538                 }
12539         }
12540
12541         if (t != TWORD || quoteflag) {
12542                 goto out;
12543         }
12544
12545         /*
12546          * check for keywords
12547          */
12548         if (kwd & CHKKWD) {
12549                 const char *const *pp;
12550
12551                 pp = findkwd(wordtext);
12552                 if (pp) {
12553                         lasttoken = t = pp - tokname_array;
12554                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12555                         goto out;
12556                 }
12557         }
12558
12559         if (checkkwd & CHKALIAS) {
12560 #if ENABLE_ASH_ALIAS
12561                 struct alias *ap;
12562                 ap = lookupalias(wordtext, 1);
12563                 if (ap != NULL) {
12564                         if (*ap->val) {
12565                                 pushstring(ap->val, ap);
12566                         }
12567                         goto top;
12568                 }
12569 #endif
12570         }
12571  out:
12572         checkkwd = 0;
12573 #if DEBUG
12574         if (!alreadyseen)
12575                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12576         else
12577                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12578 #endif
12579         return t;
12580 }
12581
12582 static int
12583 peektoken(void)
12584 {
12585         int t;
12586
12587         t = readtoken();
12588         tokpushback = 1;
12589         return t;
12590 }
12591
12592 /*
12593  * Read and parse a command.  Returns NODE_EOF on end of file.
12594  * (NULL is a valid parse tree indicating a blank line.)
12595  */
12596 static union node *
12597 parsecmd(int interact)
12598 {
12599         tokpushback = 0;
12600         checkkwd = 0;
12601         heredoclist = 0;
12602         doprompt = interact;
12603         setprompt_if(doprompt, doprompt);
12604         needprompt = 0;
12605         return list(1);
12606 }
12607
12608 /*
12609  * Input any here documents.
12610  */
12611 static void
12612 parseheredoc(void)
12613 {
12614         struct heredoc *here;
12615         union node *n;
12616
12617         here = heredoclist;
12618         heredoclist = NULL;
12619
12620         while (here) {
12621                 setprompt_if(needprompt, 2);
12622                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12623                                 here->eofmark, here->striptabs);
12624                 n = stzalloc(sizeof(struct narg));
12625                 n->narg.type = NARG;
12626                 /*n->narg.next = NULL; - stzalloc did it */
12627                 n->narg.text = wordtext;
12628                 n->narg.backquote = backquotelist;
12629                 here->here->nhere.doc = n;
12630                 here = here->next;
12631         }
12632 }
12633
12634
12635 static const char *
12636 expandstr(const char *ps, int syntax_type)
12637 {
12638         union node n;
12639         int saveprompt;
12640
12641         /* XXX Fix (char *) cast. */
12642         setinputstring((char *)ps);
12643
12644         saveprompt = doprompt;
12645         doprompt = 0;
12646         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12647         doprompt = saveprompt;
12648
12649         popfile();
12650
12651         n.narg.type = NARG;
12652         n.narg.next = NULL;
12653         n.narg.text = wordtext;
12654         n.narg.backquote = backquotelist;
12655
12656         expandarg(&n, NULL, EXP_QUOTED);
12657         return stackblock();
12658 }
12659
12660 static inline int
12661 parser_eof(void)
12662 {
12663         return tokpushback && lasttoken == TEOF;
12664 }
12665
12666 /*
12667  * Execute a command or commands contained in a string.
12668  */
12669 static int
12670 evalstring(char *s, int flags)
12671 {
12672         struct jmploc *volatile savehandler;
12673         struct jmploc jmploc;
12674         int ex;
12675
12676         union node *n;
12677         struct stackmark smark;
12678         int status;
12679
12680         s = sstrdup(s);
12681         setinputstring(s);
12682         setstackmark(&smark);
12683
12684         status = 0;
12685         /* On exception inside execution loop, we must popfile().
12686          * Try interactively:
12687          *      readonly a=a
12688          *      command eval "a=b"  # throws "is read only" error
12689          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12690          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12691          */
12692         savehandler = exception_handler;
12693         ex = setjmp(jmploc.loc);
12694         if (ex)
12695                 goto out;
12696         exception_handler = &jmploc;
12697
12698         while ((n = parsecmd(0)) != NODE_EOF) {
12699                 int i;
12700
12701                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12702                 if (n)
12703                         status = i;
12704                 popstackmark(&smark);
12705                 if (evalskip)
12706                         break;
12707         }
12708  out:
12709         popstackmark(&smark);
12710         popfile();
12711         stunalloc(s);
12712
12713         exception_handler = savehandler;
12714         if (ex)
12715                 longjmp(exception_handler->loc, ex);
12716
12717         return status;
12718 }
12719
12720 /*
12721  * The eval command.
12722  */
12723 static int FAST_FUNC
12724 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12725 {
12726         char *p;
12727         char *concat;
12728
12729         if (argv[1]) {
12730                 p = argv[1];
12731                 argv += 2;
12732                 if (argv[0]) {
12733                         STARTSTACKSTR(concat);
12734                         for (;;) {
12735                                 concat = stack_putstr(p, concat);
12736                                 p = *argv++;
12737                                 if (p == NULL)
12738                                         break;
12739                                 STPUTC(' ', concat);
12740                         }
12741                         STPUTC('\0', concat);
12742                         p = grabstackstr(concat);
12743                 }
12744                 return evalstring(p, flags & EV_TESTED);
12745         }
12746         return 0;
12747 }
12748
12749 /*
12750  * Read and execute commands.
12751  * "Top" is nonzero for the top level command loop;
12752  * it turns on prompting if the shell is interactive.
12753  */
12754 static int
12755 cmdloop(int top)
12756 {
12757         union node *n;
12758         struct stackmark smark;
12759         int inter;
12760         int status = 0;
12761         int numeof = 0;
12762
12763         TRACE(("cmdloop(%d) called\n", top));
12764         for (;;) {
12765                 int skip;
12766
12767                 setstackmark(&smark);
12768 #if JOBS
12769                 if (doing_jobctl)
12770                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12771 #endif
12772                 inter = 0;
12773                 if (iflag && top) {
12774                         inter++;
12775                         chkmail();
12776                 }
12777                 n = parsecmd(inter);
12778 #if DEBUG
12779                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12780                         showtree(n);
12781 #endif
12782                 if (n == NODE_EOF) {
12783                         if (!top || numeof >= 50)
12784                                 break;
12785                         if (!stoppedjobs()) {
12786                                 if (!Iflag)
12787                                         break;
12788                                 out2str("\nUse \"exit\" to leave shell.\n");
12789                         }
12790                         numeof++;
12791                 } else if (nflag == 0) {
12792                         int i;
12793
12794                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12795                         job_warning >>= 1;
12796                         numeof = 0;
12797                         i = evaltree(n, 0);
12798                         if (n)
12799                                 status = i;
12800                 }
12801                 popstackmark(&smark);
12802                 skip = evalskip;
12803
12804                 if (skip) {
12805                         evalskip &= ~SKIPFUNC;
12806                         break;
12807                 }
12808         }
12809         return status;
12810 }
12811
12812 /*
12813  * Take commands from a file.  To be compatible we should do a path
12814  * search for the file, which is necessary to find sub-commands.
12815  */
12816 static char *
12817 find_dot_file(char *name)
12818 {
12819         char *fullname;
12820         const char *path = pathval();
12821         struct stat statb;
12822
12823         /* don't try this for absolute or relative paths */
12824         if (strchr(name, '/'))
12825                 return name;
12826
12827         while ((fullname = path_advance(&path, name)) != NULL) {
12828                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12829                         /*
12830                          * Don't bother freeing here, since it will
12831                          * be freed by the caller.
12832                          */
12833                         return fullname;
12834                 }
12835                 if (fullname != name)
12836                         stunalloc(fullname);
12837         }
12838
12839         /* not found in the PATH */
12840         ash_msg_and_raise_error("%s: not found", name);
12841         /* NOTREACHED */
12842 }
12843
12844 static int FAST_FUNC
12845 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12846 {
12847         /* "false; . empty_file; echo $?" should print 0, not 1: */
12848         int status = 0;
12849         char *fullname;
12850         char **argv;
12851         char *args_need_save;
12852         volatile struct shparam saveparam;
12853
12854 //???
12855 //      struct strlist *sp;
12856 //      for (sp = cmdenviron; sp; sp = sp->next)
12857 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12858
12859         nextopt(nullstr); /* handle possible "--" */
12860         argv = argptr;
12861
12862         if (!argv[0]) {
12863                 /* bash says: "bash: .: filename argument required" */
12864                 return 2; /* bash compat */
12865         }
12866
12867         /* This aborts if file isn't found, which is POSIXly correct.
12868          * bash returns exitcode 1 instead.
12869          */
12870         fullname = find_dot_file(argv[0]);
12871         argv++;
12872         args_need_save = argv[0];
12873         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12874                 int argc;
12875                 saveparam = shellparam;
12876                 shellparam.malloced = 0;
12877                 argc = 1;
12878                 while (argv[argc])
12879                         argc++;
12880                 shellparam.nparam = argc;
12881                 shellparam.p = argv;
12882         };
12883
12884         /* This aborts if file can't be opened, which is POSIXly correct.
12885          * bash returns exitcode 1 instead.
12886          */
12887         setinputfile(fullname, INPUT_PUSH_FILE);
12888         commandname = fullname;
12889         status = cmdloop(0);
12890         popfile();
12891
12892         if (args_need_save) {
12893                 freeparam(&shellparam);
12894                 shellparam = saveparam;
12895         };
12896
12897         return status;
12898 }
12899
12900 static int FAST_FUNC
12901 exitcmd(int argc UNUSED_PARAM, char **argv)
12902 {
12903         if (stoppedjobs())
12904                 return 0;
12905         if (argv[1])
12906                 exitstatus = number(argv[1]);
12907         raise_exception(EXEXIT);
12908         /* NOTREACHED */
12909 }
12910
12911 /*
12912  * Read a file containing shell functions.
12913  */
12914 static void
12915 readcmdfile(char *name)
12916 {
12917         setinputfile(name, INPUT_PUSH_FILE);
12918         cmdloop(0);
12919         popfile();
12920 }
12921
12922
12923 /* ============ find_command inplementation */
12924
12925 /*
12926  * Resolve a command name.  If you change this routine, you may have to
12927  * change the shellexec routine as well.
12928  */
12929 static void
12930 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12931 {
12932         struct tblentry *cmdp;
12933         int idx;
12934         int prev;
12935         char *fullname;
12936         struct stat statb;
12937         int e;
12938         int updatetbl;
12939         struct builtincmd *bcmd;
12940
12941         /* If name contains a slash, don't use PATH or hash table */
12942         if (strchr(name, '/') != NULL) {
12943                 entry->u.index = -1;
12944                 if (act & DO_ABS) {
12945                         while (stat(name, &statb) < 0) {
12946 #ifdef SYSV
12947                                 if (errno == EINTR)
12948                                         continue;
12949 #endif
12950                                 entry->cmdtype = CMDUNKNOWN;
12951                                 return;
12952                         }
12953                 }
12954                 entry->cmdtype = CMDNORMAL;
12955                 return;
12956         }
12957
12958 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12959
12960         updatetbl = (path == pathval());
12961         if (!updatetbl) {
12962                 act |= DO_ALTPATH;
12963                 if (strstr(path, "%builtin") != NULL)
12964                         act |= DO_ALTBLTIN;
12965         }
12966
12967         /* If name is in the table, check answer will be ok */
12968         cmdp = cmdlookup(name, 0);
12969         if (cmdp != NULL) {
12970                 int bit;
12971
12972                 switch (cmdp->cmdtype) {
12973                 default:
12974 #if DEBUG
12975                         abort();
12976 #endif
12977                 case CMDNORMAL:
12978                         bit = DO_ALTPATH;
12979                         break;
12980                 case CMDFUNCTION:
12981                         bit = DO_NOFUNC;
12982                         break;
12983                 case CMDBUILTIN:
12984                         bit = DO_ALTBLTIN;
12985                         break;
12986                 }
12987                 if (act & bit) {
12988                         updatetbl = 0;
12989                         cmdp = NULL;
12990                 } else if (cmdp->rehash == 0)
12991                         /* if not invalidated by cd, we're done */
12992                         goto success;
12993         }
12994
12995         /* If %builtin not in path, check for builtin next */
12996         bcmd = find_builtin(name);
12997         if (bcmd) {
12998                 if (IS_BUILTIN_REGULAR(bcmd))
12999                         goto builtin_success;
13000                 if (act & DO_ALTPATH) {
13001                         if (!(act & DO_ALTBLTIN))
13002                                 goto builtin_success;
13003                 } else if (builtinloc <= 0) {
13004                         goto builtin_success;
13005                 }
13006         }
13007
13008 #if ENABLE_FEATURE_SH_STANDALONE
13009         {
13010                 int applet_no = find_applet_by_name(name);
13011                 if (applet_no >= 0) {
13012                         entry->cmdtype = CMDNORMAL;
13013                         entry->u.index = -2 - applet_no;
13014                         return;
13015                 }
13016         }
13017 #endif
13018
13019         /* We have to search path. */
13020         prev = -1;              /* where to start */
13021         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13022                 if (cmdp->cmdtype == CMDBUILTIN)
13023                         prev = builtinloc;
13024                 else
13025                         prev = cmdp->param.index;
13026         }
13027
13028         e = ENOENT;
13029         idx = -1;
13030  loop:
13031         while ((fullname = path_advance(&path, name)) != NULL) {
13032                 stunalloc(fullname);
13033                 /* NB: code below will still use fullname
13034                  * despite it being "unallocated" */
13035                 idx++;
13036                 if (pathopt) {
13037                         if (prefix(pathopt, "builtin")) {
13038                                 if (bcmd)
13039                                         goto builtin_success;
13040                                 continue;
13041                         }
13042                         if ((act & DO_NOFUNC)
13043                          || !prefix(pathopt, "func")
13044                         ) {     /* ignore unimplemented options */
13045                                 continue;
13046                         }
13047                 }
13048                 /* if rehash, don't redo absolute path names */
13049                 if (fullname[0] == '/' && idx <= prev) {
13050                         if (idx < prev)
13051                                 continue;
13052                         TRACE(("searchexec \"%s\": no change\n", name));
13053                         goto success;
13054                 }
13055                 while (stat(fullname, &statb) < 0) {
13056 #ifdef SYSV
13057                         if (errno == EINTR)
13058                                 continue;
13059 #endif
13060                         if (errno != ENOENT && errno != ENOTDIR)
13061                                 e = errno;
13062                         goto loop;
13063                 }
13064                 e = EACCES;     /* if we fail, this will be the error */
13065                 if (!S_ISREG(statb.st_mode))
13066                         continue;
13067                 if (pathopt) {          /* this is a %func directory */
13068                         stalloc(strlen(fullname) + 1);
13069                         /* NB: stalloc will return space pointed by fullname
13070                          * (because we don't have any intervening allocations
13071                          * between stunalloc above and this stalloc) */
13072                         readcmdfile(fullname);
13073                         cmdp = cmdlookup(name, 0);
13074                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13075                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13076                         stunalloc(fullname);
13077                         goto success;
13078                 }
13079                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13080                 if (!updatetbl) {
13081                         entry->cmdtype = CMDNORMAL;
13082                         entry->u.index = idx;
13083                         return;
13084                 }
13085                 INT_OFF;
13086                 cmdp = cmdlookup(name, 1);
13087                 cmdp->cmdtype = CMDNORMAL;
13088                 cmdp->param.index = idx;
13089                 INT_ON;
13090                 goto success;
13091         }
13092
13093         /* We failed.  If there was an entry for this command, delete it */
13094         if (cmdp && updatetbl)
13095                 delete_cmd_entry();
13096         if (act & DO_ERR)
13097                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13098         entry->cmdtype = CMDUNKNOWN;
13099         return;
13100
13101  builtin_success:
13102         if (!updatetbl) {
13103                 entry->cmdtype = CMDBUILTIN;
13104                 entry->u.cmd = bcmd;
13105                 return;
13106         }
13107         INT_OFF;
13108         cmdp = cmdlookup(name, 1);
13109         cmdp->cmdtype = CMDBUILTIN;
13110         cmdp->param.cmd = bcmd;
13111         INT_ON;
13112  success:
13113         cmdp->rehash = 0;
13114         entry->cmdtype = cmdp->cmdtype;
13115         entry->u = cmdp->param;
13116 }
13117
13118
13119 /*
13120  * The trap builtin.
13121  */
13122 static int FAST_FUNC
13123 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13124 {
13125         char *action;
13126         char **ap;
13127         int signo, exitcode;
13128
13129         nextopt(nullstr);
13130         ap = argptr;
13131         if (!*ap) {
13132                 for (signo = 0; signo < NSIG; signo++) {
13133                         char *tr = trap_ptr[signo];
13134                         if (tr) {
13135                                 /* note: bash adds "SIG", but only if invoked
13136                                  * as "bash". If called as "sh", or if set -o posix,
13137                                  * then it prints short signal names.
13138                                  * We are printing short names: */
13139                                 out1fmt("trap -- %s %s\n",
13140                                                 single_quote(tr),
13141                                                 get_signame(signo));
13142                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13143                  * In this case, we will exit very soon, no need to free(). */
13144                                 /* if (trap_ptr != trap && tp[0]) */
13145                                 /*      free(tr); */
13146                         }
13147                 }
13148                 /*
13149                 if (trap_ptr != trap) {
13150                         free(trap_ptr);
13151                         trap_ptr = trap;
13152                 }
13153                 */
13154                 return 0;
13155         }
13156
13157         /* Why the second check?
13158          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13159          * In this case, NUM is signal no, not an action.
13160          */
13161         action = NULL;
13162         if (ap[1] && !is_number(ap[0]))
13163                 action = *ap++;
13164
13165         exitcode = 0;
13166         while (*ap) {
13167                 signo = get_signum(*ap);
13168                 if (signo < 0) {
13169                         /* Mimic bash message exactly */
13170                         ash_msg("%s: invalid signal specification", *ap);
13171                         exitcode = 1;
13172                         goto next;
13173                 }
13174                 INT_OFF;
13175                 if (action) {
13176                         if (LONE_DASH(action))
13177                                 action = NULL;
13178                         else {
13179                                 if (action[0]) /* not NULL and not "" and not "-" */
13180                                         may_have_traps = 1;
13181                                 action = ckstrdup(action);
13182                         }
13183                 }
13184                 free(trap[signo]);
13185                 trap[signo] = action;
13186                 if (signo != 0)
13187                         setsignal(signo);
13188                 INT_ON;
13189  next:
13190                 ap++;
13191         }
13192         return exitcode;
13193 }
13194
13195
13196 /* ============ Builtins */
13197
13198 #if ENABLE_ASH_HELP
13199 static int FAST_FUNC
13200 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13201 {
13202         unsigned col;
13203         unsigned i;
13204
13205         out1fmt(
13206                 "Built-in commands:\n"
13207                 "------------------\n");
13208         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13209                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13210                                         builtintab[i].name + 1);
13211                 if (col > 60) {
13212                         out1fmt("\n");
13213                         col = 0;
13214                 }
13215         }
13216 # if ENABLE_FEATURE_SH_STANDALONE
13217         {
13218                 const char *a = applet_names;
13219                 while (*a) {
13220                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13221                         if (col > 60) {
13222                                 out1fmt("\n");
13223                                 col = 0;
13224                         }
13225                         while (*a++ != '\0')
13226                                 continue;
13227                 }
13228         }
13229 # endif
13230         newline_and_flush(stdout);
13231         return EXIT_SUCCESS;
13232 }
13233 #endif
13234
13235 #if MAX_HISTORY
13236 static int FAST_FUNC
13237 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13238 {
13239         show_history(line_input_state);
13240         return EXIT_SUCCESS;
13241 }
13242 #endif
13243
13244 /*
13245  * The export and readonly commands.
13246  */
13247 static int FAST_FUNC
13248 exportcmd(int argc UNUSED_PARAM, char **argv)
13249 {
13250         struct var *vp;
13251         char *name;
13252         const char *p;
13253         char **aptr;
13254         char opt;
13255         int flag;
13256         int flag_off;
13257
13258         /* "readonly" in bash accepts, but ignores -n.
13259          * We do the same: it saves a conditional in nextopt's param.
13260          */
13261         flag_off = 0;
13262         while ((opt = nextopt("np")) != '\0') {
13263                 if (opt == 'n')
13264                         flag_off = VEXPORT;
13265         }
13266         flag = VEXPORT;
13267         if (argv[0][0] == 'r') {
13268                 flag = VREADONLY;
13269                 flag_off = 0; /* readonly ignores -n */
13270         }
13271         flag_off = ~flag_off;
13272
13273         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13274         {
13275                 aptr = argptr;
13276                 name = *aptr;
13277                 if (name) {
13278                         do {
13279                                 p = strchr(name, '=');
13280                                 if (p != NULL) {
13281                                         p++;
13282                                 } else {
13283                                         vp = *findvar(hashvar(name), name);
13284                                         if (vp) {
13285                                                 vp->flags = ((vp->flags | flag) & flag_off);
13286                                                 continue;
13287                                         }
13288                                 }
13289                                 setvar(name, p, (flag & flag_off));
13290                         } while ((name = *++aptr) != NULL);
13291                         return 0;
13292                 }
13293         }
13294
13295         /* No arguments. Show the list of exported or readonly vars.
13296          * -n is ignored.
13297          */
13298         showvars(argv[0], flag, 0);
13299         return 0;
13300 }
13301
13302 /*
13303  * Delete a function if it exists.
13304  */
13305 static void
13306 unsetfunc(const char *name)
13307 {
13308         struct tblentry *cmdp;
13309
13310         cmdp = cmdlookup(name, 0);
13311         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13312                 delete_cmd_entry();
13313 }
13314
13315 /*
13316  * The unset builtin command.  We unset the function before we unset the
13317  * variable to allow a function to be unset when there is a readonly variable
13318  * with the same name.
13319  */
13320 static int FAST_FUNC
13321 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13322 {
13323         char **ap;
13324         int i;
13325         int flag = 0;
13326
13327         while ((i = nextopt("vf")) != 0) {
13328                 flag = i;
13329         }
13330
13331         for (ap = argptr; *ap; ap++) {
13332                 if (flag != 'f') {
13333                         unsetvar(*ap);
13334                         continue;
13335                 }
13336                 if (flag != 'v')
13337                         unsetfunc(*ap);
13338         }
13339         return 0;
13340 }
13341
13342 static const unsigned char timescmd_str[] ALIGN1 = {
13343         ' ',  offsetof(struct tms, tms_utime),
13344         '\n', offsetof(struct tms, tms_stime),
13345         ' ',  offsetof(struct tms, tms_cutime),
13346         '\n', offsetof(struct tms, tms_cstime),
13347         0
13348 };
13349 static int FAST_FUNC
13350 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13351 {
13352         unsigned long clk_tck, s, t;
13353         const unsigned char *p;
13354         struct tms buf;
13355
13356         clk_tck = bb_clk_tck();
13357         times(&buf);
13358
13359         p = timescmd_str;
13360         do {
13361                 t = *(clock_t *)(((char *) &buf) + p[1]);
13362                 s = t / clk_tck;
13363                 t = t % clk_tck;
13364                 out1fmt("%lum%lu.%03lus%c",
13365                         s / 60, s % 60,
13366                         (t * 1000) / clk_tck,
13367                         p[0]);
13368                 p += 2;
13369         } while (*p);
13370
13371         return 0;
13372 }
13373
13374 #if ENABLE_FEATURE_SH_MATH
13375 /*
13376  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13377  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13378  *
13379  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13380  */
13381 static int FAST_FUNC
13382 letcmd(int argc UNUSED_PARAM, char **argv)
13383 {
13384         arith_t i;
13385
13386         argv++;
13387         if (!*argv)
13388                 ash_msg_and_raise_error("expression expected");
13389         do {
13390                 i = ash_arith(*argv);
13391         } while (*++argv);
13392
13393         return !i;
13394 }
13395 #endif
13396
13397 /*
13398  * The read builtin. Options:
13399  *      -r              Do not interpret '\' specially
13400  *      -s              Turn off echo (tty only)
13401  *      -n NCHARS       Read NCHARS max
13402  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13403  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13404  *      -u FD           Read from given FD instead of fd 0
13405  * This uses unbuffered input, which may be avoidable in some cases.
13406  * TODO: bash also has:
13407  *      -a ARRAY        Read into array[0],[1],etc
13408  *      -d DELIM        End on DELIM char, not newline
13409  *      -e              Use line editing (tty only)
13410  */
13411 static int FAST_FUNC
13412 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13413 {
13414         char *opt_n = NULL;
13415         char *opt_p = NULL;
13416         char *opt_t = NULL;
13417         char *opt_u = NULL;
13418         int read_flags = 0;
13419         const char *r;
13420         int i;
13421
13422         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13423                 switch (i) {
13424                 case 'p':
13425                         opt_p = optionarg;
13426                         break;
13427                 case 'n':
13428                         opt_n = optionarg;
13429                         break;
13430                 case 's':
13431                         read_flags |= BUILTIN_READ_SILENT;
13432                         break;
13433                 case 't':
13434                         opt_t = optionarg;
13435                         break;
13436                 case 'r':
13437                         read_flags |= BUILTIN_READ_RAW;
13438                         break;
13439                 case 'u':
13440                         opt_u = optionarg;
13441                         break;
13442                 default:
13443                         break;
13444                 }
13445         }
13446
13447         /* "read -s" needs to save/restore termios, can't allow ^C
13448          * to jump out of it.
13449          */
13450  again:
13451         INT_OFF;
13452         r = shell_builtin_read(setvar0,
13453                 argptr,
13454                 bltinlookup("IFS"), /* can be NULL */
13455                 read_flags,
13456                 opt_n,
13457                 opt_p,
13458                 opt_t,
13459                 opt_u
13460         );
13461         INT_ON;
13462
13463         if ((uintptr_t)r == 1 && errno == EINTR) {
13464                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13465                  * Correct behavior is to not exit "read"
13466                  */
13467                 if (pending_sig == 0)
13468                         goto again;
13469         }
13470
13471         if ((uintptr_t)r > 1)
13472                 ash_msg_and_raise_error(r);
13473
13474         return (uintptr_t)r;
13475 }
13476
13477 static int FAST_FUNC
13478 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13479 {
13480         static const char permuser[3] ALIGN1 = "ogu";
13481
13482         mode_t mask;
13483         int symbolic_mode = 0;
13484
13485         while (nextopt("S") != '\0') {
13486                 symbolic_mode = 1;
13487         }
13488
13489         INT_OFF;
13490         mask = umask(0);
13491         umask(mask);
13492         INT_ON;
13493
13494         if (*argptr == NULL) {
13495                 if (symbolic_mode) {
13496                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13497                         char *p = buf;
13498                         int i;
13499
13500                         i = 2;
13501                         for (;;) {
13502                                 *p++ = ',';
13503                                 *p++ = permuser[i];
13504                                 *p++ = '=';
13505                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13506                                 if (!(mask & 0400)) *p++ = 'r';
13507                                 if (!(mask & 0200)) *p++ = 'w';
13508                                 if (!(mask & 0100)) *p++ = 'x';
13509                                 mask <<= 3;
13510                                 if (--i < 0)
13511                                         break;
13512                         }
13513                         *p = '\0';
13514                         puts(buf + 1);
13515                 } else {
13516                         out1fmt("%04o\n", mask);
13517                 }
13518         } else {
13519                 char *modestr = *argptr;
13520                 /* numeric umasks are taken as-is */
13521                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13522                 if (!isdigit(modestr[0]))
13523                         mask ^= 0777;
13524                 mask = bb_parse_mode(modestr, mask);
13525                 if ((unsigned)mask > 0777) {
13526                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13527                 }
13528                 if (!isdigit(modestr[0]))
13529                         mask ^= 0777;
13530                 umask(mask);
13531         }
13532         return 0;
13533 }
13534
13535 static int FAST_FUNC
13536 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13537 {
13538         return shell_builtin_ulimit(argv);
13539 }
13540
13541 /* ============ main() and helpers */
13542
13543 /*
13544  * Called to exit the shell.
13545  */
13546 static void
13547 exitshell(void)
13548 {
13549         struct jmploc loc;
13550         char *p;
13551         int status;
13552
13553 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13554         save_history(line_input_state);
13555 #endif
13556         status = exitstatus;
13557         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13558         if (setjmp(loc.loc)) {
13559                 if (exception_type == EXEXIT)
13560                         status = exitstatus;
13561                 goto out;
13562         }
13563         exception_handler = &loc;
13564         p = trap[0];
13565         if (p) {
13566                 trap[0] = NULL;
13567                 evalskip = 0;
13568                 evalstring(p, 0);
13569                 /*free(p); - we'll exit soon */
13570         }
13571  out:
13572         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13573          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13574          */
13575         setjobctl(0);
13576         flush_stdout_stderr();
13577         _exit(status);
13578         /* NOTREACHED */
13579 }
13580
13581 /* Don't inline: conserve stack of caller from having our locals too */
13582 static NOINLINE void
13583 init(void)
13584 {
13585         /* we will never free this */
13586         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13587
13588         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13589         setsignal(SIGCHLD);
13590
13591         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13592          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13593          */
13594         signal(SIGHUP, SIG_DFL);
13595
13596         {
13597                 char **envp;
13598                 const char *p;
13599
13600                 initvar();
13601                 for (envp = environ; envp && *envp; envp++) {
13602                         p = endofname(*envp);
13603                         if (p != *envp && *p == '=') {
13604                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13605                         }
13606                 }
13607
13608                 setvareq((char*)defoptindvar, VTEXTFIXED);
13609
13610                 setvar0("PPID", utoa(getppid()));
13611 #if BASH_SHLVL_VAR
13612                 p = lookupvar("SHLVL");
13613                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13614 #endif
13615 #if BASH_HOSTNAME_VAR
13616                 if (!lookupvar("HOSTNAME")) {
13617                         struct utsname uts;
13618                         uname(&uts);
13619                         setvar0("HOSTNAME", uts.nodename);
13620                 }
13621 #endif
13622                 p = lookupvar("PWD");
13623                 if (p) {
13624                         struct stat st1, st2;
13625                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13626                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13627                         ) {
13628                                 p = NULL;
13629                         }
13630                 }
13631                 setpwd(p, 0);
13632         }
13633 }
13634
13635
13636 //usage:#define ash_trivial_usage
13637 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13638 //usage:#define ash_full_usage "\n\n"
13639 //usage:        "Unix shell interpreter"
13640
13641 /*
13642  * Process the shell command line arguments.
13643  */
13644 static int
13645 procargs(char **argv)
13646 {
13647         int i;
13648         const char *xminusc;
13649         char **xargv;
13650         int login_sh;
13651
13652         xargv = argv;
13653         login_sh = xargv[0] && xargv[0][0] == '-';
13654         arg0 = xargv[0];
13655         /* if (xargv[0]) - mmm, this is always true! */
13656                 xargv++;
13657         for (i = 0; i < NOPTS; i++)
13658                 optlist[i] = 2;
13659         argptr = xargv;
13660         if (options(/*cmdline:*/ 1, &login_sh)) {
13661                 /* it already printed err message */
13662                 raise_exception(EXERROR);
13663         }
13664         xargv = argptr;
13665         xminusc = minusc;
13666         if (*xargv == NULL) {
13667                 if (xminusc)
13668                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13669                 sflag = 1;
13670         }
13671         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13672                 iflag = 1;
13673         if (mflag == 2)
13674                 mflag = iflag;
13675         for (i = 0; i < NOPTS; i++)
13676                 if (optlist[i] == 2)
13677                         optlist[i] = 0;
13678 #if DEBUG == 2
13679         debug = 1;
13680 #endif
13681         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13682         if (xminusc) {
13683                 minusc = *xargv++;
13684                 if (*xargv)
13685                         goto setarg0;
13686         } else if (!sflag) {
13687                 setinputfile(*xargv, 0);
13688  setarg0:
13689                 arg0 = *xargv++;
13690                 commandname = arg0;
13691         }
13692
13693         shellparam.p = xargv;
13694 #if ENABLE_ASH_GETOPTS
13695         shellparam.optind = 1;
13696         shellparam.optoff = -1;
13697 #endif
13698         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13699         while (*xargv) {
13700                 shellparam.nparam++;
13701                 xargv++;
13702         }
13703         optschanged();
13704
13705         return login_sh;
13706 }
13707
13708 /*
13709  * Read /etc/profile, ~/.profile, $ENV.
13710  */
13711 static void
13712 read_profile(const char *name)
13713 {
13714         name = expandstr(name, DQSYNTAX);
13715         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13716                 return;
13717         cmdloop(0);
13718         popfile();
13719 }
13720
13721 /*
13722  * This routine is called when an error or an interrupt occurs in an
13723  * interactive shell and control is returned to the main command loop.
13724  * (In dash, this function is auto-generated by build machinery).
13725  */
13726 static void
13727 reset(void)
13728 {
13729         /* from eval.c: */
13730         evalskip = 0;
13731         loopnest = 0;
13732
13733         /* from expand.c: */
13734         ifsfree();
13735
13736         /* from input.c: */
13737         g_parsefile->left_in_buffer = 0;
13738         g_parsefile->left_in_line = 0;      /* clear input buffer */
13739         popallfiles();
13740
13741         /* from redir.c: */
13742         unwindredir(NULL);
13743
13744         /* from var.c: */
13745         unwindlocalvars(NULL);
13746 }
13747
13748 #if PROFILE
13749 static short profile_buf[16384];
13750 extern int etext();
13751 #endif
13752
13753 /*
13754  * Main routine.  We initialize things, parse the arguments, execute
13755  * profiles if we're a login shell, and then call cmdloop to execute
13756  * commands.  The setjmp call sets up the location to jump to when an
13757  * exception occurs.  When an exception occurs the variable "state"
13758  * is used to figure out how far we had gotten.
13759  */
13760 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13761 int ash_main(int argc UNUSED_PARAM, char **argv)
13762 {
13763         volatile smallint state;
13764         struct jmploc jmploc;
13765         struct stackmark smark;
13766         int login_sh;
13767
13768         /* Initialize global data */
13769         INIT_G_misc();
13770         INIT_G_memstack();
13771         INIT_G_var();
13772 #if ENABLE_ASH_ALIAS
13773         INIT_G_alias();
13774 #endif
13775         INIT_G_cmdtable();
13776
13777 #if PROFILE
13778         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13779 #endif
13780
13781 #if ENABLE_FEATURE_EDITING
13782         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13783 #endif
13784         state = 0;
13785         if (setjmp(jmploc.loc)) {
13786                 smallint e;
13787                 smallint s;
13788
13789                 reset();
13790
13791                 e = exception_type;
13792                 s = state;
13793                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13794                         exitshell();
13795                 }
13796                 if (e == EXINT) {
13797                         newline_and_flush(stderr);
13798                 }
13799
13800                 popstackmark(&smark);
13801                 FORCE_INT_ON; /* enable interrupts */
13802                 if (s == 1)
13803                         goto state1;
13804                 if (s == 2)
13805                         goto state2;
13806                 if (s == 3)
13807                         goto state3;
13808                 goto state4;
13809         }
13810         exception_handler = &jmploc;
13811         rootpid = getpid();
13812
13813         init();
13814         setstackmark(&smark);
13815         login_sh = procargs(argv);
13816 #if DEBUG
13817         TRACE(("Shell args: "));
13818         trace_puts_args(argv);
13819 #endif
13820
13821         if (login_sh) {
13822                 const char *hp;
13823
13824                 state = 1;
13825                 read_profile("/etc/profile");
13826  state1:
13827                 state = 2;
13828                 hp = lookupvar("HOME");
13829                 if (hp)
13830                         read_profile("$HOME/.profile");
13831         }
13832  state2:
13833         state = 3;
13834         if (
13835 #ifndef linux
13836          getuid() == geteuid() && getgid() == getegid() &&
13837 #endif
13838          iflag
13839         ) {
13840                 const char *shinit = lookupvar("ENV");
13841                 if (shinit != NULL && *shinit != '\0')
13842                         read_profile(shinit);
13843         }
13844         popstackmark(&smark);
13845  state3:
13846         state = 4;
13847         if (minusc) {
13848                 /* evalstring pushes parsefile stack.
13849                  * Ensure we don't falsely claim that 0 (stdin)
13850                  * is one of stacked source fds.
13851                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13852                 // if (!sflag) g_parsefile->pf_fd = -1;
13853                 // ^^ not necessary since now we special-case fd 0
13854                 // in save_fd_on_redirect()
13855                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13856         }
13857
13858         if (sflag || minusc == NULL) {
13859 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13860                 if (iflag) {
13861                         const char *hp = lookupvar("HISTFILE");
13862                         if (!hp) {
13863                                 hp = lookupvar("HOME");
13864                                 if (hp) {
13865                                         INT_OFF;
13866                                         hp = concat_path_file(hp, ".ash_history");
13867                                         setvar0("HISTFILE", hp);
13868                                         free((char*)hp);
13869                                         INT_ON;
13870                                         hp = lookupvar("HISTFILE");
13871                                 }
13872                         }
13873                         if (hp)
13874                                 line_input_state->hist_file = hp;
13875 # if ENABLE_FEATURE_SH_HISTFILESIZE
13876                         hp = lookupvar("HISTFILESIZE");
13877                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13878 # endif
13879                 }
13880 #endif
13881  state4: /* XXX ??? - why isn't this before the "if" statement */
13882                 cmdloop(1);
13883         }
13884 #if PROFILE
13885         monitor(0);
13886 #endif
13887 #ifdef GPROF
13888         {
13889                 extern void _mcleanup(void);
13890                 _mcleanup();
13891         }
13892 #endif
13893         TRACE(("End of main reached\n"));
13894         exitshell();
13895         /* NOTREACHED */
13896 }
13897
13898
13899 /*-
13900  * Copyright (c) 1989, 1991, 1993, 1994
13901  *      The Regents of the University of California.  All rights reserved.
13902  *
13903  * This code is derived from software contributed to Berkeley by
13904  * Kenneth Almquist.
13905  *
13906  * Redistribution and use in source and binary forms, with or without
13907  * modification, are permitted provided that the following conditions
13908  * are met:
13909  * 1. Redistributions of source code must retain the above copyright
13910  *    notice, this list of conditions and the following disclaimer.
13911  * 2. Redistributions in binary form must reproduce the above copyright
13912  *    notice, this list of conditions and the following disclaimer in the
13913  *    documentation and/or other materials provided with the distribution.
13914  * 3. Neither the name of the University nor the names of its contributors
13915  *    may be used to endorse or promote products derived from this software
13916  *    without specific prior written permission.
13917  *
13918  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
13919  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13920  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13921  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13922  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13923  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13924  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13925  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13926  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13927  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13928  * SUCH DAMAGE.
13929  */