config: deindent all help texts
[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
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #endif
218 #if ENABLE_ASH_RANDOM_SUPPORT
219 # include "random.h"
220 #else
221 # define CLEAR_RANDOM_T(rnd) ((void)0)
222 #endif
223
224 #include "NUM_APPLETS.h"
225 #if NUM_APPLETS == 1
226 /* STANDALONE does not make sense, and won't compile */
227 # undef CONFIG_FEATURE_SH_STANDALONE
228 # undef ENABLE_FEATURE_SH_STANDALONE
229 # undef IF_FEATURE_SH_STANDALONE
230 # undef IF_NOT_FEATURE_SH_STANDALONE
231 # define ENABLE_FEATURE_SH_STANDALONE 0
232 # define IF_FEATURE_SH_STANDALONE(...)
233 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
234 #endif
235
236 #ifndef PIPE_BUF
237 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
238 #endif
239
240 #if !BB_MMU
241 # error "Do not even bother, ash will not run on NOMMU machine"
242 #endif
243
244
245 /* ============ Hash table sizes. Configurable. */
246
247 #define VTABSIZE 39
248 #define ATABSIZE 39
249 #define CMDTABLESIZE 31         /* should be prime */
250
251
252 /* ============ Shell options */
253
254 static const char *const optletters_optnames[] = {
255         "e"   "errexit",
256         "f"   "noglob",
257         "I"   "ignoreeof",
258         "i"   "interactive",
259         "m"   "monitor",
260         "n"   "noexec",
261         "s"   "stdin",
262         "x"   "xtrace",
263         "v"   "verbose",
264         "C"   "noclobber",
265         "a"   "allexport",
266         "b"   "notify",
267         "u"   "nounset",
268         "\0"  "vi"
269 #if BASH_PIPEFAIL
270         ,"\0"  "pipefail"
271 #endif
272 #if DEBUG
273         ,"\0"  "nolog"
274         ,"\0"  "debug"
275 #endif
276 };
277
278 #define optletters(n)  optletters_optnames[n][0]
279 #define optnames(n)   (optletters_optnames[n] + 1)
280
281 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
282
283
284 /* ============ Misc data */
285
286 #define msg_illnum "Illegal number: %s"
287
288 /*
289  * We enclose jmp_buf in a structure so that we can declare pointers to
290  * jump locations.  The global variable handler contains the location to
291  * jump to when an exception occurs, and the global variable exception_type
292  * contains a code identifying the exception.  To implement nested
293  * exception handlers, the user should save the value of handler on entry
294  * to an inner scope, set handler to point to a jmploc structure for the
295  * inner scope, and restore handler on exit from the scope.
296  */
297 struct jmploc {
298         jmp_buf loc;
299 };
300
301 struct globals_misc {
302         uint8_t exitstatus;     /* exit status of last command */
303         uint8_t back_exitstatus;/* exit status of backquoted command */
304         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
305         int rootpid;            /* pid of main shell */
306         /* shell level: 0 for the main shell, 1 for its children, and so on */
307         int shlvl;
308 #define rootshell (!shlvl)
309         char *minusc;  /* argument to -c option */
310
311         char *curdir; // = nullstr;     /* current working directory */
312         char *physdir; // = nullstr;    /* physical working directory */
313
314         char *arg0; /* value of $0 */
315
316         struct jmploc *exception_handler;
317
318         volatile int suppress_int; /* counter */
319         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
320         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
321         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
322         smallint exception_type; /* kind of exception (0..5) */
323         /* exceptions */
324 #define EXINT 0         /* SIGINT received */
325 #define EXERROR 1       /* a generic error */
326 #define EXEXIT 4        /* exit the shell */
327
328         smallint isloginsh;
329         char nullstr[1];        /* zero length string */
330
331         char optlist[NOPTS];
332 #define eflag optlist[0]
333 #define fflag optlist[1]
334 #define Iflag optlist[2]
335 #define iflag optlist[3]
336 #define mflag optlist[4]
337 #define nflag optlist[5]
338 #define sflag optlist[6]
339 #define xflag optlist[7]
340 #define vflag optlist[8]
341 #define Cflag optlist[9]
342 #define aflag optlist[10]
343 #define bflag optlist[11]
344 #define uflag optlist[12]
345 #define viflag optlist[13]
346 #if BASH_PIPEFAIL
347 # define pipefail optlist[14]
348 #else
349 # define pipefail 0
350 #endif
351 #if DEBUG
352 # define nolog optlist[14 + BASH_PIPEFAIL]
353 # define debug optlist[15 + BASH_PIPEFAIL]
354 #endif
355
356         /* trap handler commands */
357         /*
358          * Sigmode records the current value of the signal handlers for the various
359          * modes.  A value of zero means that the current handler is not known.
360          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
361          */
362         char sigmode[NSIG - 1];
363 #define S_DFL      1            /* default signal handling (SIG_DFL) */
364 #define S_CATCH    2            /* signal is caught */
365 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
366 #define S_HARD_IGN 4            /* signal is ignored permanently */
367
368         /* indicates specified signal received */
369         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
370         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
371         char *trap[NSIG];
372         char **trap_ptr;        /* used only by "trap hack" */
373
374         /* Rarely referenced stuff */
375 #if ENABLE_ASH_RANDOM_SUPPORT
376         random_t random_gen;
377 #endif
378         pid_t backgndpid;        /* pid of last background process */
379 };
380 extern struct globals_misc *const ash_ptr_to_globals_misc;
381 #define G_misc (*ash_ptr_to_globals_misc)
382 #define exitstatus        (G_misc.exitstatus )
383 #define back_exitstatus   (G_misc.back_exitstatus )
384 #define job_warning       (G_misc.job_warning)
385 #define rootpid     (G_misc.rootpid    )
386 #define shlvl       (G_misc.shlvl      )
387 #define minusc      (G_misc.minusc     )
388 #define curdir      (G_misc.curdir     )
389 #define physdir     (G_misc.physdir    )
390 #define arg0        (G_misc.arg0       )
391 #define exception_handler (G_misc.exception_handler)
392 #define exception_type    (G_misc.exception_type   )
393 #define suppress_int      (G_misc.suppress_int     )
394 #define pending_int       (G_misc.pending_int      )
395 #define got_sigchld       (G_misc.got_sigchld      )
396 #define pending_sig       (G_misc.pending_sig      )
397 #define isloginsh   (G_misc.isloginsh  )
398 #define nullstr     (G_misc.nullstr    )
399 #define optlist     (G_misc.optlist    )
400 #define sigmode     (G_misc.sigmode    )
401 #define gotsig      (G_misc.gotsig     )
402 #define may_have_traps    (G_misc.may_have_traps   )
403 #define trap        (G_misc.trap       )
404 #define trap_ptr    (G_misc.trap_ptr   )
405 #define random_gen  (G_misc.random_gen )
406 #define backgndpid  (G_misc.backgndpid )
407 #define INIT_G_misc() do { \
408         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
409         barrier(); \
410         curdir = nullstr; \
411         physdir = nullstr; \
412         trap_ptr = trap; \
413 } while (0)
414
415
416 /* ============ DEBUG */
417 #if DEBUG
418 static void trace_printf(const char *fmt, ...);
419 static void trace_vprintf(const char *fmt, va_list va);
420 # define TRACE(param)    trace_printf param
421 # define TRACEV(param)   trace_vprintf param
422 # define close(fd) do { \
423         int dfd = (fd); \
424         if (close(dfd) < 0) \
425                 bb_error_msg("bug on %d: closing %d(0x%x)", \
426                         __LINE__, dfd, dfd); \
427 } while (0)
428 #else
429 # define TRACE(param)
430 # define TRACEV(param)
431 #endif
432
433
434 /* ============ Utility functions */
435 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
436 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
437
438 static int
439 isdigit_str9(const char *str)
440 {
441         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
442         while (--maxlen && isdigit(*str))
443                 str++;
444         return (*str == '\0');
445 }
446
447 static const char *
448 var_end(const char *var)
449 {
450         while (*var)
451                 if (*var++ == '=')
452                         break;
453         return var;
454 }
455
456
457 /* ============ Interrupts / exceptions */
458
459 static void exitshell(void) NORETURN;
460
461 /*
462  * These macros allow the user to suspend the handling of interrupt signals
463  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
464  * much more efficient and portable.  (But hacking the kernel is so much
465  * more fun than worrying about efficiency and portability. :-))
466  */
467 #if DEBUG_INTONOFF
468 # define INT_OFF do { \
469         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
470         suppress_int++; \
471         barrier(); \
472 } while (0)
473 #else
474 # define INT_OFF do { \
475         suppress_int++; \
476         barrier(); \
477 } while (0)
478 #endif
479
480 /*
481  * Called to raise an exception.  Since C doesn't include exceptions, we
482  * just do a longjmp to the exception handler.  The type of exception is
483  * stored in the global variable "exception_type".
484  */
485 static void raise_exception(int) NORETURN;
486 static void
487 raise_exception(int e)
488 {
489 #if DEBUG
490         if (exception_handler == NULL)
491                 abort();
492 #endif
493         INT_OFF;
494         exception_type = e;
495         longjmp(exception_handler->loc, 1);
496 }
497 #if DEBUG
498 #define raise_exception(e) do { \
499         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
500         raise_exception(e); \
501 } while (0)
502 #endif
503
504 /*
505  * Called when a SIGINT is received.  (If the user specifies
506  * that SIGINT is to be trapped or ignored using the trap builtin, then
507  * this routine is not called.)  Suppressint is nonzero when interrupts
508  * are held using the INT_OFF macro.  (The test for iflag is just
509  * defensive programming.)
510  */
511 static void raise_interrupt(void) NORETURN;
512 static void
513 raise_interrupt(void)
514 {
515         pending_int = 0;
516         /* Signal is not automatically unmasked after it is raised,
517          * do it ourself - unmask all signals */
518         sigprocmask_allsigs(SIG_UNBLOCK);
519         /* pending_sig = 0; - now done in signal_handler() */
520
521         if (!(rootshell && iflag)) {
522                 /* Kill ourself with SIGINT */
523                 signal(SIGINT, SIG_DFL);
524                 raise(SIGINT);
525         }
526         /* bash: ^C even on empty command line sets $? */
527         exitstatus = SIGINT + 128;
528         raise_exception(EXINT);
529         /* NOTREACHED */
530 }
531 #if DEBUG
532 #define raise_interrupt() do { \
533         TRACE(("raising interrupt on line %d\n", __LINE__)); \
534         raise_interrupt(); \
535 } while (0)
536 #endif
537
538 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
539 int_on(void)
540 {
541         barrier();
542         if (--suppress_int == 0 && pending_int) {
543                 raise_interrupt();
544         }
545 }
546 #if DEBUG_INTONOFF
547 # define INT_ON do { \
548         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
549         int_on(); \
550 } while (0)
551 #else
552 # define INT_ON int_on()
553 #endif
554 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
555 force_int_on(void)
556 {
557         barrier();
558         suppress_int = 0;
559         if (pending_int)
560                 raise_interrupt();
561 }
562 #define FORCE_INT_ON force_int_on()
563
564 #define SAVE_INT(v) ((v) = suppress_int)
565
566 #define RESTORE_INT(v) do { \
567         barrier(); \
568         suppress_int = (v); \
569         if (suppress_int == 0 && pending_int) \
570                 raise_interrupt(); \
571 } while (0)
572
573
574 /* ============ Stdout/stderr output */
575
576 static void
577 outstr(const char *p, FILE *file)
578 {
579         INT_OFF;
580         fputs(p, file);
581         INT_ON;
582 }
583
584 static void
585 flush_stdout_stderr(void)
586 {
587         INT_OFF;
588         fflush_all();
589         INT_ON;
590 }
591
592 /* Was called outcslow(c,FILE*), but c was always '\n' */
593 static void
594 newline_and_flush(FILE *dest)
595 {
596         INT_OFF;
597         putc('\n', dest);
598         fflush(dest);
599         INT_ON;
600 }
601
602 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
603 static int
604 out1fmt(const char *fmt, ...)
605 {
606         va_list ap;
607         int r;
608
609         INT_OFF;
610         va_start(ap, fmt);
611         r = vprintf(fmt, ap);
612         va_end(ap);
613         INT_ON;
614         return r;
615 }
616
617 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
618 static int
619 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
620 {
621         va_list ap;
622         int ret;
623
624         va_start(ap, fmt);
625         INT_OFF;
626         ret = vsnprintf(outbuf, length, fmt, ap);
627         va_end(ap);
628         INT_ON;
629         return ret;
630 }
631
632 static void
633 out1str(const char *p)
634 {
635         outstr(p, stdout);
636 }
637
638 static void
639 out2str(const char *p)
640 {
641         outstr(p, stderr);
642         flush_stdout_stderr();
643 }
644
645
646 /* ============ Parser structures */
647
648 /* control characters in argument strings */
649 #define CTL_FIRST CTLESC
650 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
651 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
652 #define CTLENDVAR    ((unsigned char)'\203')
653 #define CTLBACKQ     ((unsigned char)'\204')
654 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
655 #define CTLENDARI    ((unsigned char)'\207')
656 #define CTLQUOTEMARK ((unsigned char)'\210')
657 #define CTL_LAST CTLQUOTEMARK
658
659 /* variable substitution byte (follows CTLVAR) */
660 #define VSTYPE  0x0f            /* type of variable substitution */
661 #define VSNUL   0x10            /* colon--treat the empty string as unset */
662
663 /* values of VSTYPE field */
664 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
665 #define VSMINUS         0x2     /* ${var-text} */
666 #define VSPLUS          0x3     /* ${var+text} */
667 #define VSQUESTION      0x4     /* ${var?message} */
668 #define VSASSIGN        0x5     /* ${var=text} */
669 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
670 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
671 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
672 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
673 #define VSLENGTH        0xa     /* ${#var} */
674 #if BASH_SUBSTR
675 #define VSSUBSTR        0xc     /* ${var:position:length} */
676 #endif
677 #if BASH_PATTERN_SUBST
678 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
679 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
680 #endif
681
682 static const char dolatstr[] ALIGN1 = {
683         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
684 };
685 #define DOLATSTRLEN 6
686
687 #define NCMD      0
688 #define NPIPE     1
689 #define NREDIR    2
690 #define NBACKGND  3
691 #define NSUBSHELL 4
692 #define NAND      5
693 #define NOR       6
694 #define NSEMI     7
695 #define NIF       8
696 #define NWHILE    9
697 #define NUNTIL   10
698 #define NFOR     11
699 #define NCASE    12
700 #define NCLIST   13
701 #define NDEFUN   14
702 #define NARG     15
703 #define NTO      16
704 #if BASH_REDIR_OUTPUT
705 #define NTO2     17
706 #endif
707 #define NCLOBBER 18
708 #define NFROM    19
709 #define NFROMTO  20
710 #define NAPPEND  21
711 #define NTOFD    22
712 #define NFROMFD  23
713 #define NHERE    24
714 #define NXHERE   25
715 #define NNOT     26
716 #define N_NUMBER 27
717
718 union node;
719
720 struct ncmd {
721         smallint type; /* Nxxxx */
722         union node *assign;
723         union node *args;
724         union node *redirect;
725 };
726
727 struct npipe {
728         smallint type;
729         smallint pipe_backgnd;
730         struct nodelist *cmdlist;
731 };
732
733 struct nredir {
734         smallint type;
735         union node *n;
736         union node *redirect;
737 };
738
739 struct nbinary {
740         smallint type;
741         union node *ch1;
742         union node *ch2;
743 };
744
745 struct nif {
746         smallint type;
747         union node *test;
748         union node *ifpart;
749         union node *elsepart;
750 };
751
752 struct nfor {
753         smallint type;
754         union node *args;
755         union node *body;
756         char *var;
757 };
758
759 struct ncase {
760         smallint type;
761         union node *expr;
762         union node *cases;
763 };
764
765 struct nclist {
766         smallint type;
767         union node *next;
768         union node *pattern;
769         union node *body;
770 };
771
772 struct narg {
773         smallint type;
774         union node *next;
775         char *text;
776         struct nodelist *backquote;
777 };
778
779 /* nfile and ndup layout must match!
780  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
781  * that it is actually NTO2 (>&file), and change its type.
782  */
783 struct nfile {
784         smallint type;
785         union node *next;
786         int fd;
787         int _unused_dupfd;
788         union node *fname;
789         char *expfname;
790 };
791
792 struct ndup {
793         smallint type;
794         union node *next;
795         int fd;
796         int dupfd;
797         union node *vname;
798         char *_unused_expfname;
799 };
800
801 struct nhere {
802         smallint type;
803         union node *next;
804         int fd;
805         union node *doc;
806 };
807
808 struct nnot {
809         smallint type;
810         union node *com;
811 };
812
813 union node {
814         smallint type;
815         struct ncmd ncmd;
816         struct npipe npipe;
817         struct nredir nredir;
818         struct nbinary nbinary;
819         struct nif nif;
820         struct nfor nfor;
821         struct ncase ncase;
822         struct nclist nclist;
823         struct narg narg;
824         struct nfile nfile;
825         struct ndup ndup;
826         struct nhere nhere;
827         struct nnot nnot;
828 };
829
830 /*
831  * NODE_EOF is returned by parsecmd when it encounters an end of file.
832  * It must be distinct from NULL.
833  */
834 #define NODE_EOF ((union node *) -1L)
835
836 struct nodelist {
837         struct nodelist *next;
838         union node *n;
839 };
840
841 struct funcnode {
842         int count;
843         union node n;
844 };
845
846 /*
847  * Free a parse tree.
848  */
849 static void
850 freefunc(struct funcnode *f)
851 {
852         if (f && --f->count < 0)
853                 free(f);
854 }
855
856
857 /* ============ Debugging output */
858
859 #if DEBUG
860
861 static FILE *tracefile;
862
863 static void
864 trace_printf(const char *fmt, ...)
865 {
866         va_list va;
867
868         if (debug != 1)
869                 return;
870         if (DEBUG_TIME)
871                 fprintf(tracefile, "%u ", (int) time(NULL));
872         if (DEBUG_PID)
873                 fprintf(tracefile, "[%u] ", (int) getpid());
874         if (DEBUG_SIG)
875                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
876         va_start(va, fmt);
877         vfprintf(tracefile, fmt, va);
878         va_end(va);
879 }
880
881 static void
882 trace_vprintf(const char *fmt, va_list va)
883 {
884         if (debug != 1)
885                 return;
886         vfprintf(tracefile, fmt, va);
887         fprintf(tracefile, "\n");
888 }
889
890 static void
891 trace_puts(const char *s)
892 {
893         if (debug != 1)
894                 return;
895         fputs(s, tracefile);
896 }
897
898 static void
899 trace_puts_quoted(char *s)
900 {
901         char *p;
902         char c;
903
904         if (debug != 1)
905                 return;
906         putc('"', tracefile);
907         for (p = s; *p; p++) {
908                 switch ((unsigned char)*p) {
909                 case '\n': c = 'n'; goto backslash;
910                 case '\t': c = 't'; goto backslash;
911                 case '\r': c = 'r'; goto backslash;
912                 case '\"': c = '\"'; goto backslash;
913                 case '\\': c = '\\'; goto backslash;
914                 case CTLESC: c = 'e'; goto backslash;
915                 case CTLVAR: c = 'v'; goto backslash;
916                 case CTLBACKQ: c = 'q'; goto backslash;
917  backslash:
918                         putc('\\', tracefile);
919                         putc(c, tracefile);
920                         break;
921                 default:
922                         if (*p >= ' ' && *p <= '~')
923                                 putc(*p, tracefile);
924                         else {
925                                 putc('\\', tracefile);
926                                 putc((*p >> 6) & 03, tracefile);
927                                 putc((*p >> 3) & 07, tracefile);
928                                 putc(*p & 07, tracefile);
929                         }
930                         break;
931                 }
932         }
933         putc('"', tracefile);
934 }
935
936 static void
937 trace_puts_args(char **ap)
938 {
939         if (debug != 1)
940                 return;
941         if (!*ap)
942                 return;
943         while (1) {
944                 trace_puts_quoted(*ap);
945                 if (!*++ap) {
946                         putc('\n', tracefile);
947                         break;
948                 }
949                 putc(' ', tracefile);
950         }
951 }
952
953 static void
954 opentrace(void)
955 {
956         char s[100];
957 #ifdef O_APPEND
958         int flags;
959 #endif
960
961         if (debug != 1) {
962                 if (tracefile)
963                         fflush(tracefile);
964                 /* leave open because libedit might be using it */
965                 return;
966         }
967         strcpy(s, "./trace");
968         if (tracefile) {
969                 if (!freopen(s, "a", tracefile)) {
970                         fprintf(stderr, "Can't re-open %s\n", s);
971                         debug = 0;
972                         return;
973                 }
974         } else {
975                 tracefile = fopen(s, "a");
976                 if (tracefile == NULL) {
977                         fprintf(stderr, "Can't open %s\n", s);
978                         debug = 0;
979                         return;
980                 }
981         }
982 #ifdef O_APPEND
983         flags = fcntl(fileno(tracefile), F_GETFL);
984         if (flags >= 0)
985                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
986 #endif
987         setlinebuf(tracefile);
988         fputs("\nTracing started.\n", tracefile);
989 }
990
991 static void
992 indent(int amount, char *pfx, FILE *fp)
993 {
994         int i;
995
996         for (i = 0; i < amount; i++) {
997                 if (pfx && i == amount - 1)
998                         fputs(pfx, fp);
999                 putc('\t', fp);
1000         }
1001 }
1002
1003 /* little circular references here... */
1004 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1005
1006 static void
1007 sharg(union node *arg, FILE *fp)
1008 {
1009         char *p;
1010         struct nodelist *bqlist;
1011         unsigned char subtype;
1012
1013         if (arg->type != NARG) {
1014                 out1fmt("<node type %d>\n", arg->type);
1015                 abort();
1016         }
1017         bqlist = arg->narg.backquote;
1018         for (p = arg->narg.text; *p; p++) {
1019                 switch ((unsigned char)*p) {
1020                 case CTLESC:
1021                         p++;
1022                         putc(*p, fp);
1023                         break;
1024                 case CTLVAR:
1025                         putc('$', fp);
1026                         putc('{', fp);
1027                         subtype = *++p;
1028                         if (subtype == VSLENGTH)
1029                                 putc('#', fp);
1030
1031                         while (*p != '=') {
1032                                 putc(*p, fp);
1033                                 p++;
1034                         }
1035
1036                         if (subtype & VSNUL)
1037                                 putc(':', fp);
1038
1039                         switch (subtype & VSTYPE) {
1040                         case VSNORMAL:
1041                                 putc('}', fp);
1042                                 break;
1043                         case VSMINUS:
1044                                 putc('-', fp);
1045                                 break;
1046                         case VSPLUS:
1047                                 putc('+', fp);
1048                                 break;
1049                         case VSQUESTION:
1050                                 putc('?', fp);
1051                                 break;
1052                         case VSASSIGN:
1053                                 putc('=', fp);
1054                                 break;
1055                         case VSTRIMLEFT:
1056                                 putc('#', fp);
1057                                 break;
1058                         case VSTRIMLEFTMAX:
1059                                 putc('#', fp);
1060                                 putc('#', fp);
1061                                 break;
1062                         case VSTRIMRIGHT:
1063                                 putc('%', fp);
1064                                 break;
1065                         case VSTRIMRIGHTMAX:
1066                                 putc('%', fp);
1067                                 putc('%', fp);
1068                                 break;
1069                         case VSLENGTH:
1070                                 break;
1071                         default:
1072                                 out1fmt("<subtype %d>", subtype);
1073                         }
1074                         break;
1075                 case CTLENDVAR:
1076                         putc('}', fp);
1077                         break;
1078                 case CTLBACKQ:
1079                         putc('$', fp);
1080                         putc('(', fp);
1081                         shtree(bqlist->n, -1, NULL, fp);
1082                         putc(')', fp);
1083                         break;
1084                 default:
1085                         putc(*p, fp);
1086                         break;
1087                 }
1088         }
1089 }
1090
1091 static void
1092 shcmd(union node *cmd, FILE *fp)
1093 {
1094         union node *np;
1095         int first;
1096         const char *s;
1097         int dftfd;
1098
1099         first = 1;
1100         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1101                 if (!first)
1102                         putc(' ', fp);
1103                 sharg(np, fp);
1104                 first = 0;
1105         }
1106         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1107                 if (!first)
1108                         putc(' ', fp);
1109                 dftfd = 0;
1110                 switch (np->nfile.type) {
1111                 case NTO:      s = ">>"+1; dftfd = 1; break;
1112                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1113                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1114 #if BASH_REDIR_OUTPUT
1115                 case NTO2:
1116 #endif
1117                 case NTOFD:    s = ">&"; dftfd = 1; break;
1118                 case NFROM:    s = "<"; break;
1119                 case NFROMFD:  s = "<&"; break;
1120                 case NFROMTO:  s = "<>"; break;
1121                 default:       s = "*error*"; break;
1122                 }
1123                 if (np->nfile.fd != dftfd)
1124                         fprintf(fp, "%d", np->nfile.fd);
1125                 fputs(s, fp);
1126                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1127                         fprintf(fp, "%d", np->ndup.dupfd);
1128                 } else {
1129                         sharg(np->nfile.fname, fp);
1130                 }
1131                 first = 0;
1132         }
1133 }
1134
1135 static void
1136 shtree(union node *n, int ind, char *pfx, FILE *fp)
1137 {
1138         struct nodelist *lp;
1139         const char *s;
1140
1141         if (n == NULL)
1142                 return;
1143
1144         indent(ind, pfx, fp);
1145
1146         if (n == NODE_EOF) {
1147                 fputs("<EOF>", fp);
1148                 return;
1149         }
1150
1151         switch (n->type) {
1152         case NSEMI:
1153                 s = "; ";
1154                 goto binop;
1155         case NAND:
1156                 s = " && ";
1157                 goto binop;
1158         case NOR:
1159                 s = " || ";
1160  binop:
1161                 shtree(n->nbinary.ch1, ind, NULL, fp);
1162                 /* if (ind < 0) */
1163                         fputs(s, fp);
1164                 shtree(n->nbinary.ch2, ind, NULL, fp);
1165                 break;
1166         case NCMD:
1167                 shcmd(n, fp);
1168                 if (ind >= 0)
1169                         putc('\n', fp);
1170                 break;
1171         case NPIPE:
1172                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1173                         shtree(lp->n, 0, NULL, fp);
1174                         if (lp->next)
1175                                 fputs(" | ", fp);
1176                 }
1177                 if (n->npipe.pipe_backgnd)
1178                         fputs(" &", fp);
1179                 if (ind >= 0)
1180                         putc('\n', fp);
1181                 break;
1182         default:
1183                 fprintf(fp, "<node type %d>", n->type);
1184                 if (ind >= 0)
1185                         putc('\n', fp);
1186                 break;
1187         }
1188 }
1189
1190 static void
1191 showtree(union node *n)
1192 {
1193         trace_puts("showtree called\n");
1194         shtree(n, 1, NULL, stderr);
1195 }
1196
1197 #endif /* DEBUG */
1198
1199
1200 /* ============ Parser data */
1201
1202 /*
1203  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1204  */
1205 struct strlist {
1206         struct strlist *next;
1207         char *text;
1208 };
1209
1210 struct alias;
1211
1212 struct strpush {
1213         struct strpush *prev;   /* preceding string on stack */
1214         char *prev_string;
1215         int prev_left_in_line;
1216 #if ENABLE_ASH_ALIAS
1217         struct alias *ap;       /* if push was associated with an alias */
1218 #endif
1219         char *string;           /* remember the string since it may change */
1220
1221         /* Remember last two characters for pungetc. */
1222         int lastc[2];
1223
1224         /* Number of outstanding calls to pungetc. */
1225         int unget;
1226 };
1227
1228 struct parsefile {
1229         struct parsefile *prev; /* preceding file on stack */
1230         int linno;              /* current line */
1231         int pf_fd;              /* file descriptor (or -1 if string) */
1232         int left_in_line;       /* number of chars left in this line */
1233         int left_in_buffer;     /* number of chars left in this buffer past the line */
1234         char *next_to_pgetc;    /* next char in buffer */
1235         char *buf;              /* input buffer */
1236         struct strpush *strpush; /* for pushing strings at this level */
1237         struct strpush basestrpush; /* so pushing one is fast */
1238
1239         /* Remember last two characters for pungetc. */
1240         int lastc[2];
1241
1242         /* Number of outstanding calls to pungetc. */
1243         int unget;
1244 };
1245
1246 static struct parsefile basepf;        /* top level input file */
1247 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1248 static int startlinno;                 /* line # where last token started */
1249 static char *commandname;              /* currently executing command */
1250 static struct strlist *cmdenviron;     /* environment for builtin command */
1251
1252
1253 /* ============ Message printing */
1254
1255 static void
1256 ash_vmsg(const char *msg, va_list ap)
1257 {
1258         fprintf(stderr, "%s: ", arg0);
1259         if (commandname) {
1260                 if (strcmp(arg0, commandname))
1261                         fprintf(stderr, "%s: ", commandname);
1262                 if (!iflag || g_parsefile->pf_fd > 0)
1263                         fprintf(stderr, "line %d: ", startlinno);
1264         }
1265         vfprintf(stderr, msg, ap);
1266         newline_and_flush(stderr);
1267 }
1268
1269 /*
1270  * Exverror is called to raise the error exception.  If the second argument
1271  * is not NULL then error prints an error message using printf style
1272  * formatting.  It then raises the error exception.
1273  */
1274 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1275 static void
1276 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1277 {
1278 #if DEBUG
1279         if (msg) {
1280                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1281                 TRACEV((msg, ap));
1282         } else
1283                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1284         if (msg)
1285 #endif
1286                 ash_vmsg(msg, ap);
1287
1288         flush_stdout_stderr();
1289         raise_exception(cond);
1290         /* NOTREACHED */
1291 }
1292
1293 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1294 static void
1295 ash_msg_and_raise_error(const char *msg, ...)
1296 {
1297         va_list ap;
1298
1299         exitstatus = 2;
1300
1301         va_start(ap, msg);
1302         ash_vmsg_and_raise(EXERROR, msg, ap);
1303         /* NOTREACHED */
1304         va_end(ap);
1305 }
1306
1307 static void raise_error_syntax(const char *) NORETURN;
1308 static void
1309 raise_error_syntax(const char *msg)
1310 {
1311         ash_msg_and_raise_error("syntax error: %s", msg);
1312         /* NOTREACHED */
1313 }
1314
1315 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1316 static void
1317 ash_msg_and_raise(int cond, const char *msg, ...)
1318 {
1319         va_list ap;
1320
1321         va_start(ap, msg);
1322         ash_vmsg_and_raise(cond, msg, ap);
1323         /* NOTREACHED */
1324         va_end(ap);
1325 }
1326
1327 /*
1328  * error/warning routines for external builtins
1329  */
1330 static void
1331 ash_msg(const char *fmt, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, fmt);
1336         ash_vmsg(fmt, ap);
1337         va_end(ap);
1338 }
1339
1340 /*
1341  * Return a string describing an error.  The returned string may be a
1342  * pointer to a static buffer that will be overwritten on the next call.
1343  * Action describes the operation that got the error.
1344  */
1345 static const char *
1346 errmsg(int e, const char *em)
1347 {
1348         if (e == ENOENT || e == ENOTDIR) {
1349                 return em;
1350         }
1351         return strerror(e);
1352 }
1353
1354
1355 /* ============ Memory allocation */
1356
1357 #if 0
1358 /* I consider these wrappers nearly useless:
1359  * ok, they return you to nearest exception handler, but
1360  * how much memory do you leak in the process, making
1361  * memory starvation worse?
1362  */
1363 static void *
1364 ckrealloc(void * p, size_t nbytes)
1365 {
1366         p = realloc(p, nbytes);
1367         if (!p)
1368                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1369         return p;
1370 }
1371
1372 static void *
1373 ckmalloc(size_t nbytes)
1374 {
1375         return ckrealloc(NULL, nbytes);
1376 }
1377
1378 static void *
1379 ckzalloc(size_t nbytes)
1380 {
1381         return memset(ckmalloc(nbytes), 0, nbytes);
1382 }
1383
1384 static char *
1385 ckstrdup(const char *s)
1386 {
1387         char *p = strdup(s);
1388         if (!p)
1389                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1390         return p;
1391 }
1392 #else
1393 /* Using bbox equivalents. They exit if out of memory */
1394 # define ckrealloc xrealloc
1395 # define ckmalloc  xmalloc
1396 # define ckzalloc  xzalloc
1397 # define ckstrdup  xstrdup
1398 #endif
1399
1400 /*
1401  * It appears that grabstackstr() will barf with such alignments
1402  * because stalloc() will return a string allocated in a new stackblock.
1403  */
1404 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1405 enum {
1406         /* Most machines require the value returned from malloc to be aligned
1407          * in some way.  The following macro will get this right
1408          * on many machines.  */
1409         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1410         /* Minimum size of a block */
1411         MINSIZE = SHELL_ALIGN(504),
1412 };
1413
1414 struct stack_block {
1415         struct stack_block *prev;
1416         char space[MINSIZE];
1417 };
1418
1419 struct stackmark {
1420         struct stack_block *stackp;
1421         char *stacknxt;
1422         size_t stacknleft;
1423 };
1424
1425
1426 struct globals_memstack {
1427         struct stack_block *g_stackp; // = &stackbase;
1428         char *g_stacknxt; // = stackbase.space;
1429         char *sstrend; // = stackbase.space + MINSIZE;
1430         size_t g_stacknleft; // = MINSIZE;
1431         struct stack_block stackbase;
1432 };
1433 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1434 #define G_memstack (*ash_ptr_to_globals_memstack)
1435 #define g_stackp     (G_memstack.g_stackp    )
1436 #define g_stacknxt   (G_memstack.g_stacknxt  )
1437 #define sstrend      (G_memstack.sstrend     )
1438 #define g_stacknleft (G_memstack.g_stacknleft)
1439 #define stackbase    (G_memstack.stackbase   )
1440 #define INIT_G_memstack() do { \
1441         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1442         barrier(); \
1443         g_stackp = &stackbase; \
1444         g_stacknxt = stackbase.space; \
1445         g_stacknleft = MINSIZE; \
1446         sstrend = stackbase.space + MINSIZE; \
1447 } while (0)
1448
1449
1450 #define stackblock()     ((void *)g_stacknxt)
1451 #define stackblocksize() g_stacknleft
1452
1453 /*
1454  * Parse trees for commands are allocated in lifo order, so we use a stack
1455  * to make this more efficient, and also to avoid all sorts of exception
1456  * handling code to handle interrupts in the middle of a parse.
1457  *
1458  * The size 504 was chosen because the Ultrix malloc handles that size
1459  * well.
1460  */
1461 static void *
1462 stalloc(size_t nbytes)
1463 {
1464         char *p;
1465         size_t aligned;
1466
1467         aligned = SHELL_ALIGN(nbytes);
1468         if (aligned > g_stacknleft) {
1469                 size_t len;
1470                 size_t blocksize;
1471                 struct stack_block *sp;
1472
1473                 blocksize = aligned;
1474                 if (blocksize < MINSIZE)
1475                         blocksize = MINSIZE;
1476                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1477                 if (len < blocksize)
1478                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1479                 INT_OFF;
1480                 sp = ckmalloc(len);
1481                 sp->prev = g_stackp;
1482                 g_stacknxt = sp->space;
1483                 g_stacknleft = blocksize;
1484                 sstrend = g_stacknxt + blocksize;
1485                 g_stackp = sp;
1486                 INT_ON;
1487         }
1488         p = g_stacknxt;
1489         g_stacknxt += aligned;
1490         g_stacknleft -= aligned;
1491         return p;
1492 }
1493
1494 static void *
1495 stzalloc(size_t nbytes)
1496 {
1497         return memset(stalloc(nbytes), 0, nbytes);
1498 }
1499
1500 static void
1501 stunalloc(void *p)
1502 {
1503 #if DEBUG
1504         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1505                 write(STDERR_FILENO, "stunalloc\n", 10);
1506                 abort();
1507         }
1508 #endif
1509         g_stacknleft += g_stacknxt - (char *)p;
1510         g_stacknxt = p;
1511 }
1512
1513 /*
1514  * Like strdup but works with the ash stack.
1515  */
1516 static char *
1517 sstrdup(const char *p)
1518 {
1519         size_t len = strlen(p) + 1;
1520         return memcpy(stalloc(len), p, len);
1521 }
1522
1523 static inline void
1524 grabstackblock(size_t len)
1525 {
1526         stalloc(len);
1527 }
1528
1529 static void
1530 pushstackmark(struct stackmark *mark, size_t len)
1531 {
1532         mark->stackp = g_stackp;
1533         mark->stacknxt = g_stacknxt;
1534         mark->stacknleft = g_stacknleft;
1535         grabstackblock(len);
1536 }
1537
1538 static void
1539 setstackmark(struct stackmark *mark)
1540 {
1541         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1542 }
1543
1544 static void
1545 popstackmark(struct stackmark *mark)
1546 {
1547         struct stack_block *sp;
1548
1549         if (!mark->stackp)
1550                 return;
1551
1552         INT_OFF;
1553         while (g_stackp != mark->stackp) {
1554                 sp = g_stackp;
1555                 g_stackp = sp->prev;
1556                 free(sp);
1557         }
1558         g_stacknxt = mark->stacknxt;
1559         g_stacknleft = mark->stacknleft;
1560         sstrend = mark->stacknxt + mark->stacknleft;
1561         INT_ON;
1562 }
1563
1564 /*
1565  * When the parser reads in a string, it wants to stick the string on the
1566  * stack and only adjust the stack pointer when it knows how big the
1567  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1568  * of space on top of the stack and stackblocklen returns the length of
1569  * this block.  Growstackblock will grow this space by at least one byte,
1570  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1571  * part of the block that has been used.
1572  */
1573 static void
1574 growstackblock(void)
1575 {
1576         size_t newlen;
1577
1578         newlen = g_stacknleft * 2;
1579         if (newlen < g_stacknleft)
1580                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1581         if (newlen < 128)
1582                 newlen += 128;
1583
1584         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1585                 struct stack_block *sp;
1586                 struct stack_block *prevstackp;
1587                 size_t grosslen;
1588
1589                 INT_OFF;
1590                 sp = g_stackp;
1591                 prevstackp = sp->prev;
1592                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1593                 sp = ckrealloc(sp, grosslen);
1594                 sp->prev = prevstackp;
1595                 g_stackp = sp;
1596                 g_stacknxt = sp->space;
1597                 g_stacknleft = newlen;
1598                 sstrend = sp->space + newlen;
1599                 INT_ON;
1600         } else {
1601                 char *oldspace = g_stacknxt;
1602                 size_t oldlen = g_stacknleft;
1603                 char *p = stalloc(newlen);
1604
1605                 /* free the space we just allocated */
1606                 g_stacknxt = memcpy(p, oldspace, oldlen);
1607                 g_stacknleft += newlen;
1608         }
1609 }
1610
1611 /*
1612  * The following routines are somewhat easier to use than the above.
1613  * The user declares a variable of type STACKSTR, which may be declared
1614  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1615  * the user uses the macro STPUTC to add characters to the string.  In
1616  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1617  * grown as necessary.  When the user is done, she can just leave the
1618  * string there and refer to it using stackblock().  Or she can allocate
1619  * the space for it using grabstackstr().  If it is necessary to allow
1620  * someone else to use the stack temporarily and then continue to grow
1621  * the string, the user should use grabstack to allocate the space, and
1622  * then call ungrabstr(p) to return to the previous mode of operation.
1623  *
1624  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1625  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1626  * is space for at least one character.
1627  */
1628 static void *
1629 growstackstr(void)
1630 {
1631         size_t len = stackblocksize();
1632         growstackblock();
1633         return (char *)stackblock() + len;
1634 }
1635
1636 /*
1637  * Called from CHECKSTRSPACE.
1638  */
1639 static char *
1640 makestrspace(size_t newlen, char *p)
1641 {
1642         size_t len = p - g_stacknxt;
1643         size_t size;
1644
1645         for (;;) {
1646                 size_t nleft;
1647
1648                 size = stackblocksize();
1649                 nleft = size - len;
1650                 if (nleft >= newlen)
1651                         break;
1652                 growstackblock();
1653         }
1654         return (char *)stackblock() + len;
1655 }
1656
1657 static char *
1658 stack_nputstr(const char *s, size_t n, char *p)
1659 {
1660         p = makestrspace(n, p);
1661         p = (char *)memcpy(p, s, n) + n;
1662         return p;
1663 }
1664
1665 static char *
1666 stack_putstr(const char *s, char *p)
1667 {
1668         return stack_nputstr(s, strlen(s), p);
1669 }
1670
1671 static char *
1672 _STPUTC(int c, char *p)
1673 {
1674         if (p == sstrend)
1675                 p = growstackstr();
1676         *p++ = c;
1677         return p;
1678 }
1679
1680 #define STARTSTACKSTR(p)        ((p) = stackblock())
1681 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1682 #define CHECKSTRSPACE(n, p) do { \
1683         char *q = (p); \
1684         size_t l = (n); \
1685         size_t m = sstrend - q; \
1686         if (l > m) \
1687                 (p) = makestrspace(l, q); \
1688 } while (0)
1689 #define USTPUTC(c, p)           (*(p)++ = (c))
1690 #define STACKSTRNUL(p) do { \
1691         if ((p) == sstrend) \
1692                 (p) = growstackstr(); \
1693         *(p) = '\0'; \
1694 } while (0)
1695 #define STUNPUTC(p)             (--(p))
1696 #define STTOPC(p)               ((p)[-1])
1697 #define STADJUST(amount, p)     ((p) += (amount))
1698
1699 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1700 #define ungrabstackstr(s, p)    stunalloc(s)
1701 #define stackstrend()           ((void *)sstrend)
1702
1703
1704 /* ============ String helpers */
1705
1706 /*
1707  * prefix -- see if pfx is a prefix of string.
1708  */
1709 static char *
1710 prefix(const char *string, const char *pfx)
1711 {
1712         while (*pfx) {
1713                 if (*pfx++ != *string++)
1714                         return NULL;
1715         }
1716         return (char *) string;
1717 }
1718
1719 /*
1720  * Check for a valid number.  This should be elsewhere.
1721  */
1722 static int
1723 is_number(const char *p)
1724 {
1725         do {
1726                 if (!isdigit(*p))
1727                         return 0;
1728         } while (*++p != '\0');
1729         return 1;
1730 }
1731
1732 /*
1733  * Convert a string of digits to an integer, printing an error message on
1734  * failure.
1735  */
1736 static int
1737 number(const char *s)
1738 {
1739         if (!is_number(s))
1740                 ash_msg_and_raise_error(msg_illnum, s);
1741         return atoi(s);
1742 }
1743
1744 /*
1745  * Produce a possibly single quoted string suitable as input to the shell.
1746  * The return string is allocated on the stack.
1747  */
1748 static char *
1749 single_quote(const char *s)
1750 {
1751         char *p;
1752
1753         STARTSTACKSTR(p);
1754
1755         do {
1756                 char *q;
1757                 size_t len;
1758
1759                 len = strchrnul(s, '\'') - s;
1760
1761                 q = p = makestrspace(len + 3, p);
1762
1763                 *q++ = '\'';
1764                 q = (char *)memcpy(q, s, len) + len;
1765                 *q++ = '\'';
1766                 s += len;
1767
1768                 STADJUST(q - p, p);
1769
1770                 if (*s != '\'')
1771                         break;
1772                 len = 0;
1773                 do len++; while (*++s == '\'');
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '"';
1778                 q = (char *)memcpy(q, s - len, len) + len;
1779                 *q++ = '"';
1780
1781                 STADJUST(q - p, p);
1782         } while (*s);
1783
1784         USTPUTC('\0', p);
1785
1786         return stackblock();
1787 }
1788
1789
1790 /* ============ nextopt */
1791
1792 static char **argptr;                  /* argument list for builtin commands */
1793 static char *optionarg;                /* set by nextopt (like getopt) */
1794 static char *optptr;                   /* used by nextopt */
1795
1796 /*
1797  * XXX - should get rid of. Have all builtins use getopt(3).
1798  * The library getopt must have the BSD extension static variable
1799  * "optreset", otherwise it can't be used within the shell safely.
1800  *
1801  * Standard option processing (a la getopt) for builtin routines.
1802  * The only argument that is passed to nextopt is the option string;
1803  * the other arguments are unnecessary. It returns the character,
1804  * or '\0' on end of input.
1805  */
1806 static int
1807 nextopt(const char *optstring)
1808 {
1809         char *p;
1810         const char *q;
1811         char c;
1812
1813         p = optptr;
1814         if (p == NULL || *p == '\0') {
1815                 /* We ate entire "-param", take next one */
1816                 p = *argptr;
1817                 if (p == NULL)
1818                         return '\0';
1819                 if (*p != '-')
1820                         return '\0';
1821                 if (*++p == '\0') /* just "-" ? */
1822                         return '\0';
1823                 argptr++;
1824                 if (LONE_DASH(p)) /* "--" ? */
1825                         return '\0';
1826                 /* p => next "-param" */
1827         }
1828         /* p => some option char in the middle of a "-param" */
1829         c = *p++;
1830         for (q = optstring; *q != c;) {
1831                 if (*q == '\0')
1832                         ash_msg_and_raise_error("illegal option -%c", c);
1833                 if (*++q == ':')
1834                         q++;
1835         }
1836         if (*++q == ':') {
1837                 if (*p == '\0') {
1838                         p = *argptr++;
1839                         if (p == NULL)
1840                                 ash_msg_and_raise_error("no arg for -%c option", c);
1841                 }
1842                 optionarg = p;
1843                 p = NULL;
1844         }
1845         optptr = p;
1846         return c;
1847 }
1848
1849
1850 /* ============ Shell variables */
1851
1852 /*
1853  * The parsefile structure pointed to by the global variable parsefile
1854  * contains information about the current file being read.
1855  */
1856 struct shparam {
1857         int nparam;             /* # of positional parameters (without $0) */
1858 #if ENABLE_ASH_GETOPTS
1859         int optind;             /* next parameter to be processed by getopts */
1860         int optoff;             /* used by getopts */
1861 #endif
1862         unsigned char malloced; /* if parameter list dynamically allocated */
1863         char **p;               /* parameter list */
1864 };
1865
1866 /*
1867  * Free the list of positional parameters.
1868  */
1869 static void
1870 freeparam(volatile struct shparam *param)
1871 {
1872         if (param->malloced) {
1873                 char **ap, **ap1;
1874                 ap = ap1 = param->p;
1875                 while (*ap)
1876                         free(*ap++);
1877                 free(ap1);
1878         }
1879 }
1880
1881 #if ENABLE_ASH_GETOPTS
1882 static void FAST_FUNC getoptsreset(const char *value);
1883 #endif
1884
1885 struct var {
1886         struct var *next;               /* next entry in hash list */
1887         int flags;                      /* flags are defined above */
1888         const char *var_text;           /* name=value */
1889         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1890                                         /* the variable gets set/unset */
1891 };
1892
1893 struct localvar {
1894         struct localvar *next;          /* next local variable in list */
1895         struct var *vp;                 /* the variable that was made local */
1896         int flags;                      /* saved flags */
1897         const char *text;               /* saved text */
1898 };
1899
1900 /* flags */
1901 #define VEXPORT         0x01    /* variable is exported */
1902 #define VREADONLY       0x02    /* variable cannot be modified */
1903 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1904 #define VTEXTFIXED      0x08    /* text is statically allocated */
1905 #define VSTACK          0x10    /* text is allocated on the stack */
1906 #define VUNSET          0x20    /* the variable is not set */
1907 #define VNOFUNC         0x40    /* don't call the callback function */
1908 #define VNOSET          0x80    /* do not set variable - just readonly test */
1909 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1910 #if ENABLE_ASH_RANDOM_SUPPORT
1911 # define VDYNAMIC       0x200   /* dynamic variable */
1912 #else
1913 # define VDYNAMIC       0
1914 #endif
1915
1916
1917 /* Need to be before varinit_data[] */
1918 #if ENABLE_LOCALE_SUPPORT
1919 static void FAST_FUNC
1920 change_lc_all(const char *value)
1921 {
1922         if (value && *value != '\0')
1923                 setlocale(LC_ALL, value);
1924 }
1925 static void FAST_FUNC
1926 change_lc_ctype(const char *value)
1927 {
1928         if (value && *value != '\0')
1929                 setlocale(LC_CTYPE, value);
1930 }
1931 #endif
1932 #if ENABLE_ASH_MAIL
1933 static void chkmail(void);
1934 static void changemail(const char *var_value) FAST_FUNC;
1935 #else
1936 # define chkmail()  ((void)0)
1937 #endif
1938 static void changepath(const char *) FAST_FUNC;
1939 #if ENABLE_ASH_RANDOM_SUPPORT
1940 static void change_random(const char *) FAST_FUNC;
1941 #endif
1942
1943 static const struct {
1944         int flags;
1945         const char *var_text;
1946         void (*var_func)(const char *) FAST_FUNC;
1947 } varinit_data[] = {
1948         /*
1949          * Note: VEXPORT would not work correctly here for NOFORK applets:
1950          * some environment strings may be constant.
1951          */
1952         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1953 #if ENABLE_ASH_MAIL
1954         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1955         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1956 #endif
1957         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1958         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1959         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1960         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1961 #if ENABLE_ASH_GETOPTS
1962         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
1963 #endif
1964 #if ENABLE_ASH_RANDOM_SUPPORT
1965         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
1966 #endif
1967 #if ENABLE_LOCALE_SUPPORT
1968         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
1969         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
1970 #endif
1971 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1972         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
1973 #endif
1974 };
1975
1976 struct redirtab;
1977
1978 struct globals_var {
1979         struct shparam shellparam;      /* $@ current positional parameters */
1980         struct redirtab *redirlist;
1981         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
1982         struct var *vartab[VTABSIZE];
1983         struct var varinit[ARRAY_SIZE(varinit_data)];
1984 };
1985 extern struct globals_var *const ash_ptr_to_globals_var;
1986 #define G_var (*ash_ptr_to_globals_var)
1987 #define shellparam    (G_var.shellparam   )
1988 //#define redirlist     (G_var.redirlist    )
1989 #define preverrout_fd (G_var.preverrout_fd)
1990 #define vartab        (G_var.vartab       )
1991 #define varinit       (G_var.varinit      )
1992 #define INIT_G_var() do { \
1993         unsigned i; \
1994         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1995         barrier(); \
1996         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1997                 varinit[i].flags    = varinit_data[i].flags; \
1998                 varinit[i].var_text = varinit_data[i].var_text; \
1999                 varinit[i].var_func = varinit_data[i].var_func; \
2000         } \
2001 } while (0)
2002
2003 #define vifs      varinit[0]
2004 #if ENABLE_ASH_MAIL
2005 # define vmail    (&vifs)[1]
2006 # define vmpath   (&vmail)[1]
2007 # define vpath    (&vmpath)[1]
2008 #else
2009 # define vpath    (&vifs)[1]
2010 #endif
2011 #define vps1      (&vpath)[1]
2012 #define vps2      (&vps1)[1]
2013 #define vps4      (&vps2)[1]
2014 #if ENABLE_ASH_GETOPTS
2015 # define voptind  (&vps4)[1]
2016 # if ENABLE_ASH_RANDOM_SUPPORT
2017 #  define vrandom (&voptind)[1]
2018 # endif
2019 #else
2020 # if ENABLE_ASH_RANDOM_SUPPORT
2021 #  define vrandom (&vps4)[1]
2022 # endif
2023 #endif
2024
2025 /*
2026  * The following macros access the values of the above variables.
2027  * They have to skip over the name.  They return the null string
2028  * for unset variables.
2029  */
2030 #define ifsval()        (vifs.var_text + 4)
2031 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2032 #if ENABLE_ASH_MAIL
2033 # define mailval()      (vmail.var_text + 5)
2034 # define mpathval()     (vmpath.var_text + 9)
2035 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2036 #endif
2037 #define pathval()       (vpath.var_text + 5)
2038 #define ps1val()        (vps1.var_text + 4)
2039 #define ps2val()        (vps2.var_text + 4)
2040 #define ps4val()        (vps4.var_text + 4)
2041 #if ENABLE_ASH_GETOPTS
2042 # define optindval()    (voptind.var_text + 7)
2043 #endif
2044
2045 #if ENABLE_ASH_GETOPTS
2046 static void FAST_FUNC
2047 getoptsreset(const char *value)
2048 {
2049         shellparam.optind = number(value) ?: 1;
2050         shellparam.optoff = -1;
2051 }
2052 #endif
2053
2054 /*
2055  * Compares two strings up to the first = or '\0'.  The first
2056  * string must be terminated by '='; the second may be terminated by
2057  * either '=' or '\0'.
2058  */
2059 static int
2060 varcmp(const char *p, const char *q)
2061 {
2062         int c, d;
2063
2064         while ((c = *p) == (d = *q)) {
2065                 if (c == '\0' || c == '=')
2066                         goto out;
2067                 p++;
2068                 q++;
2069         }
2070         if (c == '=')
2071                 c = '\0';
2072         if (d == '=')
2073                 d = '\0';
2074  out:
2075         return c - d;
2076 }
2077
2078 /*
2079  * Find the appropriate entry in the hash table from the name.
2080  */
2081 static struct var **
2082 hashvar(const char *p)
2083 {
2084         unsigned hashval;
2085
2086         hashval = ((unsigned char) *p) << 4;
2087         while (*p && *p != '=')
2088                 hashval += (unsigned char) *p++;
2089         return &vartab[hashval % VTABSIZE];
2090 }
2091
2092 static int
2093 vpcmp(const void *a, const void *b)
2094 {
2095         return varcmp(*(const char **)a, *(const char **)b);
2096 }
2097
2098 /*
2099  * This routine initializes the builtin variables.
2100  */
2101 static void
2102 initvar(void)
2103 {
2104         struct var *vp;
2105         struct var *end;
2106         struct var **vpp;
2107
2108         /*
2109          * PS1 depends on uid
2110          */
2111 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2112         vps1.var_text = "PS1=\\w \\$ ";
2113 #else
2114         if (!geteuid())
2115                 vps1.var_text = "PS1=# ";
2116 #endif
2117         vp = varinit;
2118         end = vp + ARRAY_SIZE(varinit);
2119         do {
2120                 vpp = hashvar(vp->var_text);
2121                 vp->next = *vpp;
2122                 *vpp = vp;
2123         } while (++vp < end);
2124 }
2125
2126 static struct var **
2127 findvar(struct var **vpp, const char *name)
2128 {
2129         for (; *vpp; vpp = &(*vpp)->next) {
2130                 if (varcmp((*vpp)->var_text, name) == 0) {
2131                         break;
2132                 }
2133         }
2134         return vpp;
2135 }
2136
2137 /*
2138  * Find the value of a variable.  Returns NULL if not set.
2139  */
2140 static const char* FAST_FUNC
2141 lookupvar(const char *name)
2142 {
2143         struct var *v;
2144
2145         v = *findvar(hashvar(name), name);
2146         if (v) {
2147 #if ENABLE_ASH_RANDOM_SUPPORT
2148         /*
2149          * Dynamic variables are implemented roughly the same way they are
2150          * in bash. Namely, they're "special" so long as they aren't unset.
2151          * As soon as they're unset, they're no longer dynamic, and dynamic
2152          * lookup will no longer happen at that point. -- PFM.
2153          */
2154                 if (v->flags & VDYNAMIC)
2155                         v->var_func(NULL);
2156 #endif
2157                 if (!(v->flags & VUNSET))
2158                         return var_end(v->var_text);
2159         }
2160         return NULL;
2161 }
2162
2163 #if ENABLE_UNICODE_SUPPORT
2164 static void
2165 reinit_unicode_for_ash(void)
2166 {
2167         /* Unicode support should be activated even if LANG is set
2168          * _during_ shell execution, not only if it was set when
2169          * shell was started. Therefore, re-check LANG every time:
2170          */
2171         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2172          || ENABLE_UNICODE_USING_LOCALE
2173         ) {
2174                 const char *s = lookupvar("LC_ALL");
2175                 if (!s) s = lookupvar("LC_CTYPE");
2176                 if (!s) s = lookupvar("LANG");
2177                 reinit_unicode(s);
2178         }
2179 }
2180 #else
2181 # define reinit_unicode_for_ash() ((void)0)
2182 #endif
2183
2184 /*
2185  * Search the environment of a builtin command.
2186  */
2187 static const char *
2188 bltinlookup(const char *name)
2189 {
2190         struct strlist *sp;
2191
2192         for (sp = cmdenviron; sp; sp = sp->next) {
2193                 if (varcmp(sp->text, name) == 0)
2194                         return var_end(sp->text);
2195         }
2196         return lookupvar(name);
2197 }
2198
2199 /*
2200  * Same as setvar except that the variable and value are passed in
2201  * the first argument as name=value.  Since the first argument will
2202  * be actually stored in the table, it should not be a string that
2203  * will go away.
2204  * Called with interrupts off.
2205  */
2206 static void
2207 setvareq(char *s, int flags)
2208 {
2209         struct var *vp, **vpp;
2210
2211         vpp = hashvar(s);
2212         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2213         vp = *findvar(vpp, s);
2214         if (vp) {
2215                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2216                         const char *n;
2217
2218                         if (flags & VNOSAVE)
2219                                 free(s);
2220                         n = vp->var_text;
2221                         exitstatus = 1;
2222                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2223                 }
2224
2225                 if (flags & VNOSET)
2226                         return;
2227
2228                 if (vp->var_func && !(flags & VNOFUNC))
2229                         vp->var_func(var_end(s));
2230
2231                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2232                         free((char*)vp->var_text);
2233
2234                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2235         } else {
2236                 /* variable s is not found */
2237                 if (flags & VNOSET)
2238                         return;
2239                 vp = ckzalloc(sizeof(*vp));
2240                 vp->next = *vpp;
2241                 /*vp->func = NULL; - ckzalloc did it */
2242                 *vpp = vp;
2243         }
2244         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2245                 s = ckstrdup(s);
2246         vp->var_text = s;
2247         vp->flags = flags;
2248 }
2249
2250 /*
2251  * Set the value of a variable.  The flags argument is ored with the
2252  * flags of the variable.  If val is NULL, the variable is unset.
2253  */
2254 static void
2255 setvar(const char *name, const char *val, int flags)
2256 {
2257         const char *q;
2258         char *p;
2259         char *nameeq;
2260         size_t namelen;
2261         size_t vallen;
2262
2263         q = endofname(name);
2264         p = strchrnul(q, '=');
2265         namelen = p - name;
2266         if (!namelen || p != q)
2267                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2268         vallen = 0;
2269         if (val == NULL) {
2270                 flags |= VUNSET;
2271         } else {
2272                 vallen = strlen(val);
2273         }
2274
2275         INT_OFF;
2276         nameeq = ckmalloc(namelen + vallen + 2);
2277         p = memcpy(nameeq, name, namelen) + namelen;
2278         if (val) {
2279                 *p++ = '=';
2280                 p = memcpy(p, val, vallen) + vallen;
2281         }
2282         *p = '\0';
2283         setvareq(nameeq, flags | VNOSAVE);
2284         INT_ON;
2285 }
2286
2287 static void FAST_FUNC
2288 setvar0(const char *name, const char *val)
2289 {
2290         setvar(name, val, 0);
2291 }
2292
2293 /*
2294  * Unset the specified variable.
2295  */
2296 static int
2297 unsetvar(const char *s)
2298 {
2299         struct var **vpp;
2300         struct var *vp;
2301         int retval;
2302
2303         vpp = findvar(hashvar(s), s);
2304         vp = *vpp;
2305         retval = 2;
2306         if (vp) {
2307                 int flags = vp->flags;
2308
2309                 retval = 1;
2310                 if (flags & VREADONLY)
2311                         goto out;
2312 #if ENABLE_ASH_RANDOM_SUPPORT
2313                 vp->flags &= ~VDYNAMIC;
2314 #endif
2315                 if (flags & VUNSET)
2316                         goto ok;
2317                 if ((flags & VSTRFIXED) == 0) {
2318                         INT_OFF;
2319                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2320                                 free((char*)vp->var_text);
2321                         *vpp = vp->next;
2322                         free(vp);
2323                         INT_ON;
2324                 } else {
2325                         setvar0(s, NULL);
2326                         vp->flags &= ~VEXPORT;
2327                 }
2328  ok:
2329                 retval = 0;
2330         }
2331  out:
2332         return retval;
2333 }
2334
2335 /*
2336  * Process a linked list of variable assignments.
2337  */
2338 static void
2339 listsetvar(struct strlist *list_set_var, int flags)
2340 {
2341         struct strlist *lp = list_set_var;
2342
2343         if (!lp)
2344                 return;
2345         INT_OFF;
2346         do {
2347                 setvareq(lp->text, flags);
2348                 lp = lp->next;
2349         } while (lp);
2350         INT_ON;
2351 }
2352
2353 /*
2354  * Generate a list of variables satisfying the given conditions.
2355  */
2356 static char **
2357 listvars(int on, int off, char ***end)
2358 {
2359         struct var **vpp;
2360         struct var *vp;
2361         char **ep;
2362         int mask;
2363
2364         STARTSTACKSTR(ep);
2365         vpp = vartab;
2366         mask = on | off;
2367         do {
2368                 for (vp = *vpp; vp; vp = vp->next) {
2369                         if ((vp->flags & mask) == on) {
2370                                 if (ep == stackstrend())
2371                                         ep = growstackstr();
2372                                 *ep++ = (char*)vp->var_text;
2373                         }
2374                 }
2375         } while (++vpp < vartab + VTABSIZE);
2376         if (ep == stackstrend())
2377                 ep = growstackstr();
2378         if (end)
2379                 *end = ep;
2380         *ep++ = NULL;
2381         return grabstackstr(ep);
2382 }
2383
2384
2385 /* ============ Path search helper
2386  *
2387  * The variable path (passed by reference) should be set to the start
2388  * of the path before the first call; path_advance will update
2389  * this value as it proceeds.  Successive calls to path_advance will return
2390  * the possible path expansions in sequence.  If an option (indicated by
2391  * a percent sign) appears in the path entry then the global variable
2392  * pathopt will be set to point to it; otherwise pathopt will be set to
2393  * NULL.
2394  */
2395 static const char *pathopt;     /* set by path_advance */
2396
2397 static char *
2398 path_advance(const char **path, const char *name)
2399 {
2400         const char *p;
2401         char *q;
2402         const char *start;
2403         size_t len;
2404
2405         if (*path == NULL)
2406                 return NULL;
2407         start = *path;
2408         for (p = start; *p && *p != ':' && *p != '%'; p++)
2409                 continue;
2410         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2411         while (stackblocksize() < len)
2412                 growstackblock();
2413         q = stackblock();
2414         if (p != start) {
2415                 memcpy(q, start, p - start);
2416                 q += p - start;
2417                 *q++ = '/';
2418         }
2419         strcpy(q, name);
2420         pathopt = NULL;
2421         if (*p == '%') {
2422                 pathopt = ++p;
2423                 while (*p && *p != ':')
2424                         p++;
2425         }
2426         if (*p == ':')
2427                 *path = p + 1;
2428         else
2429                 *path = NULL;
2430         return stalloc(len);
2431 }
2432
2433
2434 /* ============ Prompt */
2435
2436 static smallint doprompt;                   /* if set, prompt the user */
2437 static smallint needprompt;                 /* true if interactive and at start of line */
2438
2439 #if ENABLE_FEATURE_EDITING
2440 static line_input_t *line_input_state;
2441 static const char *cmdedit_prompt;
2442 static void
2443 putprompt(const char *s)
2444 {
2445         if (ENABLE_ASH_EXPAND_PRMT) {
2446                 free((char*)cmdedit_prompt);
2447                 cmdedit_prompt = ckstrdup(s);
2448                 return;
2449         }
2450         cmdedit_prompt = s;
2451 }
2452 #else
2453 static void
2454 putprompt(const char *s)
2455 {
2456         out2str(s);
2457 }
2458 #endif
2459
2460 /* expandstr() needs parsing machinery, so it is far away ahead... */
2461 static const char *expandstr(const char *ps);
2462
2463 static void
2464 setprompt_if(smallint do_set, int whichprompt)
2465 {
2466         const char *prompt;
2467         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2468
2469         if (!do_set)
2470                 return;
2471
2472         needprompt = 0;
2473
2474         switch (whichprompt) {
2475         case 1:
2476                 prompt = ps1val();
2477                 break;
2478         case 2:
2479                 prompt = ps2val();
2480                 break;
2481         default:                        /* 0 */
2482                 prompt = nullstr;
2483         }
2484 #if ENABLE_ASH_EXPAND_PRMT
2485         pushstackmark(&smark, stackblocksize());
2486         putprompt(expandstr(prompt));
2487         popstackmark(&smark);
2488 #else
2489         putprompt(prompt);
2490 #endif
2491 }
2492
2493
2494 /* ============ The cd and pwd commands */
2495
2496 #define CD_PHYSICAL 1
2497 #define CD_PRINT 2
2498
2499 static int
2500 cdopt(void)
2501 {
2502         int flags = 0;
2503         int i, j;
2504
2505         j = 'L';
2506         while ((i = nextopt("LP")) != '\0') {
2507                 if (i != j) {
2508                         flags ^= CD_PHYSICAL;
2509                         j = i;
2510                 }
2511         }
2512
2513         return flags;
2514 }
2515
2516 /*
2517  * Update curdir (the name of the current directory) in response to a
2518  * cd command.
2519  */
2520 static const char *
2521 updatepwd(const char *dir)
2522 {
2523         char *new;
2524         char *p;
2525         char *cdcomppath;
2526         const char *lim;
2527
2528         cdcomppath = sstrdup(dir);
2529         STARTSTACKSTR(new);
2530         if (*dir != '/') {
2531                 if (curdir == nullstr)
2532                         return 0;
2533                 new = stack_putstr(curdir, new);
2534         }
2535         new = makestrspace(strlen(dir) + 2, new);
2536         lim = (char *)stackblock() + 1;
2537         if (*dir != '/') {
2538                 if (new[-1] != '/')
2539                         USTPUTC('/', new);
2540                 if (new > lim && *lim == '/')
2541                         lim++;
2542         } else {
2543                 USTPUTC('/', new);
2544                 cdcomppath++;
2545                 if (dir[1] == '/' && dir[2] != '/') {
2546                         USTPUTC('/', new);
2547                         cdcomppath++;
2548                         lim++;
2549                 }
2550         }
2551         p = strtok(cdcomppath, "/");
2552         while (p) {
2553                 switch (*p) {
2554                 case '.':
2555                         if (p[1] == '.' && p[2] == '\0') {
2556                                 while (new > lim) {
2557                                         STUNPUTC(new);
2558                                         if (new[-1] == '/')
2559                                                 break;
2560                                 }
2561                                 break;
2562                         }
2563                         if (p[1] == '\0')
2564                                 break;
2565                         /* fall through */
2566                 default:
2567                         new = stack_putstr(p, new);
2568                         USTPUTC('/', new);
2569                 }
2570                 p = strtok(NULL, "/");
2571         }
2572         if (new > lim)
2573                 STUNPUTC(new);
2574         *new = 0;
2575         return stackblock();
2576 }
2577
2578 /*
2579  * Find out what the current directory is. If we already know the current
2580  * directory, this routine returns immediately.
2581  */
2582 static char *
2583 getpwd(void)
2584 {
2585         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2586         return dir ? dir : nullstr;
2587 }
2588
2589 static void
2590 setpwd(const char *val, int setold)
2591 {
2592         char *oldcur, *dir;
2593
2594         oldcur = dir = curdir;
2595
2596         if (setold) {
2597                 setvar("OLDPWD", oldcur, VEXPORT);
2598         }
2599         INT_OFF;
2600         if (physdir != nullstr) {
2601                 if (physdir != oldcur)
2602                         free(physdir);
2603                 physdir = nullstr;
2604         }
2605         if (oldcur == val || !val) {
2606                 char *s = getpwd();
2607                 physdir = s;
2608                 if (!val)
2609                         dir = s;
2610         } else
2611                 dir = ckstrdup(val);
2612         if (oldcur != dir && oldcur != nullstr) {
2613                 free(oldcur);
2614         }
2615         curdir = dir;
2616         INT_ON;
2617         setvar("PWD", dir, VEXPORT);
2618 }
2619
2620 static void hashcd(void);
2621
2622 /*
2623  * Actually do the chdir.  We also call hashcd to let other routines
2624  * know that the current directory has changed.
2625  */
2626 static int
2627 docd(const char *dest, int flags)
2628 {
2629         const char *dir = NULL;
2630         int err;
2631
2632         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2633
2634         INT_OFF;
2635         if (!(flags & CD_PHYSICAL)) {
2636                 dir = updatepwd(dest);
2637                 if (dir)
2638                         dest = dir;
2639         }
2640         err = chdir(dest);
2641         if (err)
2642                 goto out;
2643         setpwd(dir, 1);
2644         hashcd();
2645  out:
2646         INT_ON;
2647         return err;
2648 }
2649
2650 static int FAST_FUNC
2651 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2652 {
2653         const char *dest;
2654         const char *path;
2655         const char *p;
2656         char c;
2657         struct stat statb;
2658         int flags;
2659
2660         flags = cdopt();
2661         dest = *argptr;
2662         if (!dest)
2663                 dest = bltinlookup("HOME");
2664         else if (LONE_DASH(dest)) {
2665                 dest = bltinlookup("OLDPWD");
2666                 flags |= CD_PRINT;
2667         }
2668         if (!dest)
2669                 dest = nullstr;
2670         if (*dest == '/')
2671                 goto step6;
2672         if (*dest == '.') {
2673                 c = dest[1];
2674  dotdot:
2675                 switch (c) {
2676                 case '\0':
2677                 case '/':
2678                         goto step6;
2679                 case '.':
2680                         c = dest[2];
2681                         if (c != '.')
2682                                 goto dotdot;
2683                 }
2684         }
2685         if (!*dest)
2686                 dest = ".";
2687         path = bltinlookup("CDPATH");
2688         while (path) {
2689                 c = *path;
2690                 p = path_advance(&path, dest);
2691                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2692                         if (c && c != ':')
2693                                 flags |= CD_PRINT;
2694  docd:
2695                         if (!docd(p, flags))
2696                                 goto out;
2697                         goto err;
2698                 }
2699         }
2700
2701  step6:
2702         p = dest;
2703         goto docd;
2704
2705  err:
2706         ash_msg_and_raise_error("can't cd to %s", dest);
2707         /* NOTREACHED */
2708  out:
2709         if (flags & CD_PRINT)
2710                 out1fmt("%s\n", curdir);
2711         return 0;
2712 }
2713
2714 static int FAST_FUNC
2715 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2716 {
2717         int flags;
2718         const char *dir = curdir;
2719
2720         flags = cdopt();
2721         if (flags) {
2722                 if (physdir == nullstr)
2723                         setpwd(dir, 0);
2724                 dir = physdir;
2725         }
2726         out1fmt("%s\n", dir);
2727         return 0;
2728 }
2729
2730
2731 /* ============ ... */
2732
2733
2734 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2735
2736 /* Syntax classes */
2737 #define CWORD     0             /* character is nothing special */
2738 #define CNL       1             /* newline character */
2739 #define CBACK     2             /* a backslash character */
2740 #define CSQUOTE   3             /* single quote */
2741 #define CDQUOTE   4             /* double quote */
2742 #define CENDQUOTE 5             /* a terminating quote */
2743 #define CBQUOTE   6             /* backwards single quote */
2744 #define CVAR      7             /* a dollar sign */
2745 #define CENDVAR   8             /* a '}' character */
2746 #define CLP       9             /* a left paren in arithmetic */
2747 #define CRP      10             /* a right paren in arithmetic */
2748 #define CENDFILE 11             /* end of file */
2749 #define CCTL     12             /* like CWORD, except it must be escaped */
2750 #define CSPCL    13             /* these terminate a word */
2751 #define CIGN     14             /* character should be ignored */
2752
2753 #define PEOF     256
2754 #if ENABLE_ASH_ALIAS
2755 # define PEOA    257
2756 #endif
2757
2758 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2759
2760 #if ENABLE_FEATURE_SH_MATH
2761 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2762 #else
2763 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2764 #endif
2765 static const uint16_t S_I_T[] ALIGN2 = {
2766 #if ENABLE_ASH_ALIAS
2767         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2768 #endif
2769         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2770         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2771         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2772         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2773         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2774         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2775         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2776         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2777         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2778         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2779         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2780 #if !USE_SIT_FUNCTION
2781         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2782         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2783         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2784 #endif
2785 #undef SIT_ITEM
2786 };
2787 /* Constants below must match table above */
2788 enum {
2789 #if ENABLE_ASH_ALIAS
2790         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2791 #endif
2792         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2793         CNL_CNL_CNL_CNL                    , /*  2 */
2794         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2795         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2796         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2797         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2798         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2799         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2800         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2801         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2802         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2803         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2804         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2805         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2806 };
2807
2808 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2809  * caller must ensure proper cast on it if c is *char_ptr!
2810  */
2811 /* Values for syntax param */
2812 #define BASESYNTAX 0    /* not in quotes */
2813 #define DQSYNTAX   1    /* in double quotes */
2814 #define SQSYNTAX   2    /* in single quotes */
2815 #define ARISYNTAX  3    /* in arithmetic */
2816 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2817
2818 #if USE_SIT_FUNCTION
2819
2820 static int
2821 SIT(int c, int syntax)
2822 {
2823         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2824         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2825         /*
2826          * This causes '/' to be prepended with CTLESC in dquoted string,
2827          * making "./file"* treated incorrectly because we feed
2828          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2829          * The "homegrown" glob implementation is okay with that,
2830          * but glibc one isn't. With '/' always treated as CWORD,
2831          * both work fine.
2832          */
2833 # if ENABLE_ASH_ALIAS
2834         static const uint8_t syntax_index_table[] ALIGN1 = {
2835                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2836                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2837                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2838                 11, 3                           /* "}~" */
2839         };
2840 # else
2841         static const uint8_t syntax_index_table[] ALIGN1 = {
2842                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2843                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2844                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2845                 10, 2                           /* "}~" */
2846         };
2847 # endif
2848         const char *s;
2849         int indx;
2850
2851         if (c == PEOF)
2852                 return CENDFILE;
2853 # if ENABLE_ASH_ALIAS
2854         if (c == PEOA)
2855                 indx = 0;
2856         else
2857 # endif
2858         {
2859                 /* Cast is purely for paranoia here,
2860                  * just in case someone passed signed char to us */
2861                 if ((unsigned char)c >= CTL_FIRST
2862                  && (unsigned char)c <= CTL_LAST
2863                 ) {
2864                         return CCTL;
2865                 }
2866                 s = strchrnul(spec_symbls, c);
2867                 if (*s == '\0')
2868                         return CWORD;
2869                 indx = syntax_index_table[s - spec_symbls];
2870         }
2871         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2872 }
2873
2874 #else   /* !USE_SIT_FUNCTION */
2875
2876 static const uint8_t syntax_index_table[] ALIGN1 = {
2877         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2878         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2879         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2880         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2881         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2882         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2883         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2884         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2885         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2886         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2887         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2888         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2889         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2890         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2891         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2892         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2893         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2894         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2895         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2896         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2897         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2898         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2899         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2900         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2901         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2902         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2903         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2904         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2905         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2906         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2907         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2908         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2909         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2910         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2911         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2912         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2913         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2914         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2915         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2916         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2917         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2918         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2919         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2920         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2921         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2922         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2923         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2924         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2925 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2926         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2927         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2928         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2929         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2930         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2931         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2932         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2933         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2934         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2935         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2936         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2937         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2938         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2939         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2940         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2941         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2942         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2943         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2944         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2945         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2946         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2947         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2948         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2950         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2953         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2954         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2956         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2958         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2971         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2972         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2973         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2976         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2977         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2979         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2980         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2981         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
2982         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
2983         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
2984         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
2985         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
2986         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
2987         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
2988         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
2989         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
2990         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
2991         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
2992         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
2993         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
2994         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
2995         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
2996         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
2997         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
2998         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
2999         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3000         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3001         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3002         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3003         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3004         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3005         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3006         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3007         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3008         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3009         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3010         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3011         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3012         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3013         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3014         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3015         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3016         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3017         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3018         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3019         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3020         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3021         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3022         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3023         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3024         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3025         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3026         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3027         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3028         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3029         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3030         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3031         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3032         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3033         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3034         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3135         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3136 # if ENABLE_ASH_ALIAS
3137         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3138 # endif
3139 };
3140
3141 #if 1
3142 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3143 #else /* debug version, caught one signed char bug */
3144 # define SIT(c, syntax) \
3145         ({ \
3146                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3147                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3148                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3149                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3150                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3151         })
3152 #endif
3153
3154 #endif  /* !USE_SIT_FUNCTION */
3155
3156
3157 /* ============ Alias handling */
3158
3159 #if ENABLE_ASH_ALIAS
3160
3161 #define ALIASINUSE 1
3162 #define ALIASDEAD  2
3163
3164 struct alias {
3165         struct alias *next;
3166         char *name;
3167         char *val;
3168         int flag;
3169 };
3170
3171
3172 static struct alias **atab; // [ATABSIZE];
3173 #define INIT_G_alias() do { \
3174         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3175 } while (0)
3176
3177
3178 static struct alias **
3179 __lookupalias(const char *name)
3180 {
3181         unsigned int hashval;
3182         struct alias **app;
3183         const char *p;
3184         unsigned int ch;
3185
3186         p = name;
3187
3188         ch = (unsigned char)*p;
3189         hashval = ch << 4;
3190         while (ch) {
3191                 hashval += ch;
3192                 ch = (unsigned char)*++p;
3193         }
3194         app = &atab[hashval % ATABSIZE];
3195
3196         for (; *app; app = &(*app)->next) {
3197                 if (strcmp(name, (*app)->name) == 0) {
3198                         break;
3199                 }
3200         }
3201
3202         return app;
3203 }
3204
3205 static struct alias *
3206 lookupalias(const char *name, int check)
3207 {
3208         struct alias *ap = *__lookupalias(name);
3209
3210         if (check && ap && (ap->flag & ALIASINUSE))
3211                 return NULL;
3212         return ap;
3213 }
3214
3215 static struct alias *
3216 freealias(struct alias *ap)
3217 {
3218         struct alias *next;
3219
3220         if (ap->flag & ALIASINUSE) {
3221                 ap->flag |= ALIASDEAD;
3222                 return ap;
3223         }
3224
3225         next = ap->next;
3226         free(ap->name);
3227         free(ap->val);
3228         free(ap);
3229         return next;
3230 }
3231
3232 static void
3233 setalias(const char *name, const char *val)
3234 {
3235         struct alias *ap, **app;
3236
3237         app = __lookupalias(name);
3238         ap = *app;
3239         INT_OFF;
3240         if (ap) {
3241                 if (!(ap->flag & ALIASINUSE)) {
3242                         free(ap->val);
3243                 }
3244                 ap->val = ckstrdup(val);
3245                 ap->flag &= ~ALIASDEAD;
3246         } else {
3247                 /* not found */
3248                 ap = ckzalloc(sizeof(struct alias));
3249                 ap->name = ckstrdup(name);
3250                 ap->val = ckstrdup(val);
3251                 /*ap->flag = 0; - ckzalloc did it */
3252                 /*ap->next = NULL;*/
3253                 *app = ap;
3254         }
3255         INT_ON;
3256 }
3257
3258 static int
3259 unalias(const char *name)
3260 {
3261         struct alias **app;
3262
3263         app = __lookupalias(name);
3264
3265         if (*app) {
3266                 INT_OFF;
3267                 *app = freealias(*app);
3268                 INT_ON;
3269                 return 0;
3270         }
3271
3272         return 1;
3273 }
3274
3275 static void
3276 rmaliases(void)
3277 {
3278         struct alias *ap, **app;
3279         int i;
3280
3281         INT_OFF;
3282         for (i = 0; i < ATABSIZE; i++) {
3283                 app = &atab[i];
3284                 for (ap = *app; ap; ap = *app) {
3285                         *app = freealias(*app);
3286                         if (ap == *app) {
3287                                 app = &ap->next;
3288                         }
3289                 }
3290         }
3291         INT_ON;
3292 }
3293
3294 static void
3295 printalias(const struct alias *ap)
3296 {
3297         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3298 }
3299
3300 /*
3301  * TODO - sort output
3302  */
3303 static int FAST_FUNC
3304 aliascmd(int argc UNUSED_PARAM, char **argv)
3305 {
3306         char *n, *v;
3307         int ret = 0;
3308         struct alias *ap;
3309
3310         if (!argv[1]) {
3311                 int i;
3312
3313                 for (i = 0; i < ATABSIZE; i++) {
3314                         for (ap = atab[i]; ap; ap = ap->next) {
3315                                 printalias(ap);
3316                         }
3317                 }
3318                 return 0;
3319         }
3320         while ((n = *++argv) != NULL) {
3321                 v = strchr(n+1, '=');
3322                 if (v == NULL) { /* n+1: funny ksh stuff */
3323                         ap = *__lookupalias(n);
3324                         if (ap == NULL) {
3325                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3326                                 ret = 1;
3327                         } else
3328                                 printalias(ap);
3329                 } else {
3330                         *v++ = '\0';
3331                         setalias(n, v);
3332                 }
3333         }
3334
3335         return ret;
3336 }
3337
3338 static int FAST_FUNC
3339 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3340 {
3341         int i;
3342
3343         while (nextopt("a") != '\0') {
3344                 rmaliases();
3345                 return 0;
3346         }
3347         for (i = 0; *argptr; argptr++) {
3348                 if (unalias(*argptr)) {
3349                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3350                         i = 1;
3351                 }
3352         }
3353
3354         return i;
3355 }
3356
3357 #endif /* ASH_ALIAS */
3358
3359
3360 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3361 #define FORK_FG    0
3362 #define FORK_BG    1
3363 #define FORK_NOJOB 2
3364
3365 /* mode flags for showjob(s) */
3366 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3367 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3368 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3369 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3370
3371 /*
3372  * A job structure contains information about a job.  A job is either a
3373  * single process or a set of processes contained in a pipeline.  In the
3374  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3375  * array of pids.
3376  */
3377 struct procstat {
3378         pid_t   ps_pid;         /* process id */
3379         int     ps_status;      /* last process status from wait() */
3380         char    *ps_cmd;        /* text of command being run */
3381 };
3382
3383 struct job {
3384         struct procstat ps0;    /* status of process */
3385         struct procstat *ps;    /* status or processes when more than one */
3386 #if JOBS
3387         int stopstatus;         /* status of a stopped job */
3388 #endif
3389         unsigned nprocs;        /* number of processes */
3390
3391 #define JOBRUNNING      0       /* at least one proc running */
3392 #define JOBSTOPPED      1       /* all procs are stopped */
3393 #define JOBDONE         2       /* all procs are completed */
3394         unsigned
3395                 state: 8,
3396 #if JOBS
3397                 sigint: 1,      /* job was killed by SIGINT */
3398                 jobctl: 1,      /* job running under job control */
3399 #endif
3400                 waited: 1,      /* true if this entry has been waited for */
3401                 used: 1,        /* true if this entry is in used */
3402                 changed: 1;     /* true if status has changed */
3403         struct job *prev_job;   /* previous job */
3404 };
3405
3406 static struct job *makejob(/*union node *,*/ int);
3407 static int forkshell(struct job *, union node *, int);
3408 static int waitforjob(struct job *);
3409
3410 #if !JOBS
3411 enum { doing_jobctl = 0 };
3412 #define setjobctl(on) do {} while (0)
3413 #else
3414 static smallint doing_jobctl; //references:8
3415 static void setjobctl(int);
3416 #endif
3417
3418 /*
3419  * Ignore a signal.
3420  */
3421 static void
3422 ignoresig(int signo)
3423 {
3424         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3425         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3426                 /* No, need to do it */
3427                 signal(signo, SIG_IGN);
3428         }
3429         sigmode[signo - 1] = S_HARD_IGN;
3430 }
3431
3432 /*
3433  * Only one usage site - in setsignal()
3434  */
3435 static void
3436 signal_handler(int signo)
3437 {
3438         if (signo == SIGCHLD) {
3439                 got_sigchld = 1;
3440                 if (!trap[SIGCHLD])
3441                         return;
3442         }
3443
3444         gotsig[signo - 1] = 1;
3445         pending_sig = signo;
3446
3447         if (signo == SIGINT && !trap[SIGINT]) {
3448                 if (!suppress_int) {
3449                         pending_sig = 0;
3450                         raise_interrupt(); /* does not return */
3451                 }
3452                 pending_int = 1;
3453         }
3454 }
3455
3456 /*
3457  * Set the signal handler for the specified signal.  The routine figures
3458  * out what it should be set to.
3459  */
3460 static void
3461 setsignal(int signo)
3462 {
3463         char *t;
3464         char cur_act, new_act;
3465         struct sigaction act;
3466
3467         t = trap[signo];
3468         new_act = S_DFL;
3469         if (t != NULL) { /* trap for this sig is set */
3470                 new_act = S_CATCH;
3471                 if (t[0] == '\0') /* trap is "": ignore this sig */
3472                         new_act = S_IGN;
3473         }
3474
3475         if (rootshell && new_act == S_DFL) {
3476                 switch (signo) {
3477                 case SIGINT:
3478                         if (iflag || minusc || sflag == 0)
3479                                 new_act = S_CATCH;
3480                         break;
3481                 case SIGQUIT:
3482 #if DEBUG
3483                         if (debug)
3484                                 break;
3485 #endif
3486                         /* man bash:
3487                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3488                          * commands run by bash have signal handlers
3489                          * set to the values inherited by the shell
3490                          * from its parent". */
3491                         new_act = S_IGN;
3492                         break;
3493                 case SIGTERM:
3494                         if (iflag)
3495                                 new_act = S_IGN;
3496                         break;
3497 #if JOBS
3498                 case SIGTSTP:
3499                 case SIGTTOU:
3500                         if (mflag)
3501                                 new_act = S_IGN;
3502                         break;
3503 #endif
3504                 }
3505         }
3506 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3507 //whereas we have to restore it to what shell got on entry
3508 //from the parent. See comment above
3509
3510         if (signo == SIGCHLD)
3511                 new_act = S_CATCH;
3512
3513         t = &sigmode[signo - 1];
3514         cur_act = *t;
3515         if (cur_act == 0) {
3516                 /* current setting is not yet known */
3517                 if (sigaction(signo, NULL, &act)) {
3518                         /* pretend it worked; maybe we should give a warning,
3519                          * but other shells don't. We don't alter sigmode,
3520                          * so we retry every time.
3521                          * btw, in Linux it never fails. --vda */
3522                         return;
3523                 }
3524                 if (act.sa_handler == SIG_IGN) {
3525                         cur_act = S_HARD_IGN;
3526                         if (mflag
3527                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3528                         ) {
3529                                 cur_act = S_IGN;   /* don't hard ignore these */
3530                         }
3531                 }
3532         }
3533         if (cur_act == S_HARD_IGN || cur_act == new_act)
3534                 return;
3535
3536         act.sa_handler = SIG_DFL;
3537         switch (new_act) {
3538         case S_CATCH:
3539                 act.sa_handler = signal_handler;
3540                 break;
3541         case S_IGN:
3542                 act.sa_handler = SIG_IGN;
3543                 break;
3544         }
3545
3546         /* flags and mask matter only if !DFL and !IGN, but we do it
3547          * for all cases for more deterministic behavior:
3548          */
3549         act.sa_flags = 0;
3550         sigfillset(&act.sa_mask);
3551
3552         sigaction_set(signo, &act);
3553
3554         *t = new_act;
3555 }
3556
3557 /* mode flags for set_curjob */
3558 #define CUR_DELETE 2
3559 #define CUR_RUNNING 1
3560 #define CUR_STOPPED 0
3561
3562 #if JOBS
3563 /* pgrp of shell on invocation */
3564 static int initialpgrp; //references:2
3565 static int ttyfd = -1; //5
3566 #endif
3567 /* array of jobs */
3568 static struct job *jobtab; //5
3569 /* size of array */
3570 static unsigned njobs; //4
3571 /* current job */
3572 static struct job *curjob; //lots
3573 /* number of presumed living untracked jobs */
3574 static int jobless; //4
3575
3576 #if 0
3577 /* Bash has a feature: it restores termios after a successful wait for
3578  * a foreground job which had at least one stopped or sigkilled member.
3579  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3580  * properly restoring tty state. Should we do this too?
3581  * A reproducer: ^Z an interactive python:
3582  *
3583  * # python
3584  * Python 2.7.12 (...)
3585  * >>> ^Z
3586  *      { python leaves tty in -icanon -echo state. We do survive that... }
3587  *  [1]+  Stopped                    python
3588  *      { ...however, next program (python #2) does not survive it well: }
3589  * # python
3590  * Python 2.7.12 (...)
3591  * >>> Traceback (most recent call last):
3592  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3593  *   File "<stdin>", line 1, in <module>
3594  * NameError: name 'qwerty' is not defined
3595  *
3596  * The implementation below is modeled on bash code and seems to work.
3597  * However, I'm not sure we should do this. For one: what if I'd fg
3598  * the stopped python instead? It'll be confused by "restored" tty state.
3599  */
3600 static struct termios shell_tty_info;
3601 static void
3602 get_tty_state(void)
3603 {
3604         if (rootshell && ttyfd >= 0)
3605                 tcgetattr(ttyfd, &shell_tty_info);
3606 }
3607 static void
3608 set_tty_state(void)
3609 {
3610         /* if (rootshell) - caller ensures this */
3611         if (ttyfd >= 0)
3612                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3613 }
3614 static int
3615 job_signal_status(struct job *jp)
3616 {
3617         int status;
3618         unsigned i;
3619         struct procstat *ps = jp->ps;
3620         for (i = 0; i < jp->nprocs; i++) {
3621                 status = ps[i].ps_status;
3622                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3623                         return status;
3624         }
3625         return 0;
3626 }
3627 static void
3628 restore_tty_if_stopped_or_signaled(struct job *jp)
3629 {
3630 //TODO: check what happens if we come from waitforjob() in expbackq()
3631         if (rootshell) {
3632                 int s = job_signal_status(jp);
3633                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3634                         set_tty_state();
3635         }
3636 }
3637 #else
3638 # define get_tty_state() ((void)0)
3639 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3640 #endif
3641
3642 static void
3643 set_curjob(struct job *jp, unsigned mode)
3644 {
3645         struct job *jp1;
3646         struct job **jpp, **curp;
3647
3648         /* first remove from list */
3649         jpp = curp = &curjob;
3650         while (1) {
3651                 jp1 = *jpp;
3652                 if (jp1 == jp)
3653                         break;
3654                 jpp = &jp1->prev_job;
3655         }
3656         *jpp = jp1->prev_job;
3657
3658         /* Then re-insert in correct position */
3659         jpp = curp;
3660         switch (mode) {
3661         default:
3662 #if DEBUG
3663                 abort();
3664 #endif
3665         case CUR_DELETE:
3666                 /* job being deleted */
3667                 break;
3668         case CUR_RUNNING:
3669                 /* newly created job or backgrounded job,
3670                  * put after all stopped jobs.
3671                  */
3672                 while (1) {
3673                         jp1 = *jpp;
3674 #if JOBS
3675                         if (!jp1 || jp1->state != JOBSTOPPED)
3676 #endif
3677                                 break;
3678                         jpp = &jp1->prev_job;
3679                 }
3680                 /* FALLTHROUGH */
3681 #if JOBS
3682         case CUR_STOPPED:
3683 #endif
3684                 /* newly stopped job - becomes curjob */
3685                 jp->prev_job = *jpp;
3686                 *jpp = jp;
3687                 break;
3688         }
3689 }
3690
3691 #if JOBS || DEBUG
3692 static int
3693 jobno(const struct job *jp)
3694 {
3695         return jp - jobtab + 1;
3696 }
3697 #endif
3698
3699 /*
3700  * Convert a job name to a job structure.
3701  */
3702 #if !JOBS
3703 #define getjob(name, getctl) getjob(name)
3704 #endif
3705 static struct job *
3706 getjob(const char *name, int getctl)
3707 {
3708         struct job *jp;
3709         struct job *found;
3710         const char *err_msg = "%s: no such job";
3711         unsigned num;
3712         int c;
3713         const char *p;
3714         char *(*match)(const char *, const char *);
3715
3716         jp = curjob;
3717         p = name;
3718         if (!p)
3719                 goto currentjob;
3720
3721         if (*p != '%')
3722                 goto err;
3723
3724         c = *++p;
3725         if (!c)
3726                 goto currentjob;
3727
3728         if (!p[1]) {
3729                 if (c == '+' || c == '%') {
3730  currentjob:
3731                         err_msg = "No current job";
3732                         goto check;
3733                 }
3734                 if (c == '-') {
3735                         if (jp)
3736                                 jp = jp->prev_job;
3737                         err_msg = "No previous job";
3738  check:
3739                         if (!jp)
3740                                 goto err;
3741                         goto gotit;
3742                 }
3743         }
3744
3745         if (is_number(p)) {
3746                 num = atoi(p);
3747                 if (num > 0 && num <= njobs) {
3748                         jp = jobtab + num - 1;
3749                         if (jp->used)
3750                                 goto gotit;
3751                         goto err;
3752                 }
3753         }
3754
3755         match = prefix;
3756         if (*p == '?') {
3757                 match = strstr;
3758                 p++;
3759         }
3760
3761         found = NULL;
3762         while (jp) {
3763                 if (match(jp->ps[0].ps_cmd, p)) {
3764                         if (found)
3765                                 goto err;
3766                         found = jp;
3767                         err_msg = "%s: ambiguous";
3768                 }
3769                 jp = jp->prev_job;
3770         }
3771         if (!found)
3772                 goto err;
3773         jp = found;
3774
3775  gotit:
3776 #if JOBS
3777         err_msg = "job %s not created under job control";
3778         if (getctl && jp->jobctl == 0)
3779                 goto err;
3780 #endif
3781         return jp;
3782  err:
3783         ash_msg_and_raise_error(err_msg, name);
3784 }
3785
3786 /*
3787  * Mark a job structure as unused.
3788  */
3789 static void
3790 freejob(struct job *jp)
3791 {
3792         struct procstat *ps;
3793         int i;
3794
3795         INT_OFF;
3796         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3797                 if (ps->ps_cmd != nullstr)
3798                         free(ps->ps_cmd);
3799         }
3800         if (jp->ps != &jp->ps0)
3801                 free(jp->ps);
3802         jp->used = 0;
3803         set_curjob(jp, CUR_DELETE);
3804         INT_ON;
3805 }
3806
3807 #if JOBS
3808 static void
3809 xtcsetpgrp(int fd, pid_t pgrp)
3810 {
3811         if (tcsetpgrp(fd, pgrp))
3812                 ash_msg_and_raise_error("can't set tty process group (%m)");
3813 }
3814
3815 /*
3816  * Turn job control on and off.
3817  *
3818  * Note:  This code assumes that the third arg to ioctl is a character
3819  * pointer, which is true on Berkeley systems but not System V.  Since
3820  * System V doesn't have job control yet, this isn't a problem now.
3821  *
3822  * Called with interrupts off.
3823  */
3824 static void
3825 setjobctl(int on)
3826 {
3827         int fd;
3828         int pgrp;
3829
3830         if (on == doing_jobctl || rootshell == 0)
3831                 return;
3832         if (on) {
3833                 int ofd;
3834                 ofd = fd = open(_PATH_TTY, O_RDWR);
3835                 if (fd < 0) {
3836         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3837          * That sometimes helps to acquire controlling tty.
3838          * Obviously, a workaround for bugs when someone
3839          * failed to provide a controlling tty to bash! :) */
3840                         fd = 2;
3841                         while (!isatty(fd))
3842                                 if (--fd < 0)
3843                                         goto out;
3844                 }
3845                 /* fd is a tty at this point */
3846                 fd = fcntl(fd, F_DUPFD, 10);
3847                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3848                         close(ofd);
3849                 if (fd < 0)
3850                         goto out; /* F_DUPFD failed */
3851                 close_on_exec_on(fd);
3852                 while (1) { /* while we are in the background */
3853                         pgrp = tcgetpgrp(fd);
3854                         if (pgrp < 0) {
3855  out:
3856                                 ash_msg("can't access tty; job control turned off");
3857                                 mflag = on = 0;
3858                                 goto close;
3859                         }
3860                         if (pgrp == getpgrp())
3861                                 break;
3862                         killpg(0, SIGTTIN);
3863                 }
3864                 initialpgrp = pgrp;
3865
3866                 setsignal(SIGTSTP);
3867                 setsignal(SIGTTOU);
3868                 setsignal(SIGTTIN);
3869                 pgrp = rootpid;
3870                 setpgid(0, pgrp);
3871                 xtcsetpgrp(fd, pgrp);
3872         } else {
3873                 /* turning job control off */
3874                 fd = ttyfd;
3875                 pgrp = initialpgrp;
3876                 /* was xtcsetpgrp, but this can make exiting ash
3877                  * loop forever if pty is already deleted */
3878                 tcsetpgrp(fd, pgrp);
3879                 setpgid(0, pgrp);
3880                 setsignal(SIGTSTP);
3881                 setsignal(SIGTTOU);
3882                 setsignal(SIGTTIN);
3883  close:
3884                 if (fd >= 0)
3885                         close(fd);
3886                 fd = -1;
3887         }
3888         ttyfd = fd;
3889         doing_jobctl = on;
3890 }
3891
3892 static int FAST_FUNC
3893 killcmd(int argc, char **argv)
3894 {
3895         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3896                 int i = 1;
3897                 do {
3898                         if (argv[i][0] == '%') {
3899                                 /*
3900                                  * "kill %N" - job kill
3901                                  * Converting to pgrp / pid kill
3902                                  */
3903                                 struct job *jp;
3904                                 char *dst;
3905                                 int j, n;
3906
3907                                 jp = getjob(argv[i], 0);
3908                                 /*
3909                                  * In jobs started under job control, we signal
3910                                  * entire process group by kill -PGRP_ID.
3911                                  * This happens, f.e., in interactive shell.
3912                                  *
3913                                  * Otherwise, we signal each child via
3914                                  * kill PID1 PID2 PID3.
3915                                  * Testcases:
3916                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3917                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3918                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3919                                  */
3920                                 n = jp->nprocs; /* can't be 0 (I hope) */
3921                                 if (jp->jobctl)
3922                                         n = 1;
3923                                 dst = alloca(n * sizeof(int)*4);
3924                                 argv[i] = dst;
3925                                 for (j = 0; j < n; j++) {
3926                                         struct procstat *ps = &jp->ps[j];
3927                                         /* Skip non-running and not-stopped members
3928                                          * (i.e. dead members) of the job
3929                                          */
3930                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3931                                                 continue;
3932                                         /*
3933                                          * kill_main has matching code to expect
3934                                          * leading space. Needed to not confuse
3935                                          * negative pids with "kill -SIGNAL_NO" syntax
3936                                          */
3937                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3938                                 }
3939                                 *dst = '\0';
3940                         }
3941                 } while (argv[++i]);
3942         }
3943         return kill_main(argc, argv);
3944 }
3945
3946 static void
3947 showpipe(struct job *jp /*, FILE *out*/)
3948 {
3949         struct procstat *ps;
3950         struct procstat *psend;
3951
3952         psend = jp->ps + jp->nprocs;
3953         for (ps = jp->ps + 1; ps < psend; ps++)
3954                 printf(" | %s", ps->ps_cmd);
3955         newline_and_flush(stdout);
3956         flush_stdout_stderr();
3957 }
3958
3959
3960 static int
3961 restartjob(struct job *jp, int mode)
3962 {
3963         struct procstat *ps;
3964         int i;
3965         int status;
3966         pid_t pgid;
3967
3968         INT_OFF;
3969         if (jp->state == JOBDONE)
3970                 goto out;
3971         jp->state = JOBRUNNING;
3972         pgid = jp->ps[0].ps_pid;
3973         if (mode == FORK_FG) {
3974                 get_tty_state();
3975                 xtcsetpgrp(ttyfd, pgid);
3976         }
3977         killpg(pgid, SIGCONT);
3978         ps = jp->ps;
3979         i = jp->nprocs;
3980         do {
3981                 if (WIFSTOPPED(ps->ps_status)) {
3982                         ps->ps_status = -1;
3983                 }
3984                 ps++;
3985         } while (--i);
3986  out:
3987         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3988         INT_ON;
3989         return status;
3990 }
3991
3992 static int FAST_FUNC
3993 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3994 {
3995         struct job *jp;
3996         int mode;
3997         int retval;
3998
3999         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4000         nextopt(nullstr);
4001         argv = argptr;
4002         do {
4003                 jp = getjob(*argv, 1);
4004                 if (mode == FORK_BG) {
4005                         set_curjob(jp, CUR_RUNNING);
4006                         printf("[%d] ", jobno(jp));
4007                 }
4008                 out1str(jp->ps[0].ps_cmd);
4009                 showpipe(jp /*, stdout*/);
4010                 retval = restartjob(jp, mode);
4011         } while (*argv && *++argv);
4012         return retval;
4013 }
4014 #endif
4015
4016 static int
4017 sprint_status48(char *s, int status, int sigonly)
4018 {
4019         int col;
4020         int st;
4021
4022         col = 0;
4023         if (!WIFEXITED(status)) {
4024 #if JOBS
4025                 if (WIFSTOPPED(status))
4026                         st = WSTOPSIG(status);
4027                 else
4028 #endif
4029                         st = WTERMSIG(status);
4030                 if (sigonly) {
4031                         if (st == SIGINT || st == SIGPIPE)
4032                                 goto out;
4033 #if JOBS
4034                         if (WIFSTOPPED(status))
4035                                 goto out;
4036 #endif
4037                 }
4038                 st &= 0x7f;
4039 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4040                 col = fmtstr(s, 32, strsignal(st));
4041                 if (WCOREDUMP(status)) {
4042                         strcpy(s + col, " (core dumped)");
4043                         col += sizeof(" (core dumped)")-1;
4044                 }
4045         } else if (!sigonly) {
4046                 st = WEXITSTATUS(status);
4047                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4048         }
4049  out:
4050         return col;
4051 }
4052
4053 static int
4054 wait_block_or_sig(int *status)
4055 {
4056         int pid;
4057
4058         do {
4059                 sigset_t mask;
4060
4061                 /* Poll all children for changes in their state */
4062                 got_sigchld = 0;
4063                 /* if job control is active, accept stopped processes too */
4064                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4065                 if (pid != 0)
4066                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4067
4068                 /* Children exist, but none are ready. Sleep until interesting signal */
4069 #if 1
4070                 sigfillset(&mask);
4071                 sigprocmask(SIG_SETMASK, &mask, &mask);
4072                 while (!got_sigchld && !pending_sig)
4073                         sigsuspend(&mask);
4074                 sigprocmask(SIG_SETMASK, &mask, NULL);
4075 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4076                 while (!got_sigchld && !pending_sig)
4077                         pause();
4078 #endif
4079
4080                 /* If it was SIGCHLD, poll children again */
4081         } while (got_sigchld);
4082
4083         return pid;
4084 }
4085
4086 #define DOWAIT_NONBLOCK 0
4087 #define DOWAIT_BLOCK    1
4088 #define DOWAIT_BLOCK_OR_SIG 2
4089
4090 static int
4091 dowait(int block, struct job *job)
4092 {
4093         int pid;
4094         int status;
4095         struct job *jp;
4096         struct job *thisjob = NULL;
4097
4098         TRACE(("dowait(0x%x) called\n", block));
4099
4100         /* It's wrong to call waitpid() outside of INT_OFF region:
4101          * signal can arrive just after syscall return and handler can
4102          * longjmp away, losing stop/exit notification processing.
4103          * Thus, for "jobs" builtin, and for waiting for a fg job,
4104          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4105          *
4106          * However, for "wait" builtin it is wrong to simply call waitpid()
4107          * in INT_OFF region: "wait" needs to wait for any running job
4108          * to change state, but should exit on any trap too.
4109          * In INT_OFF region, a signal just before syscall entry can set
4110          * pending_sig variables, but we can't check them, and we would
4111          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4112          *
4113          * Because of this, we run inside INT_OFF, but use a special routine
4114          * which combines waitpid() and sigsuspend().
4115          * This is the reason why we need to have a handler for SIGCHLD:
4116          * SIG_DFL handler does not wake sigsuspend().
4117          */
4118         INT_OFF;
4119         if (block == DOWAIT_BLOCK_OR_SIG) {
4120                 pid = wait_block_or_sig(&status);
4121         } else {
4122                 int wait_flags = 0;
4123                 if (block == DOWAIT_NONBLOCK)
4124                         wait_flags = WNOHANG;
4125                 /* if job control is active, accept stopped processes too */
4126                 if (doing_jobctl)
4127                         wait_flags |= WUNTRACED;
4128                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4129                 pid = waitpid(-1, &status, wait_flags);
4130         }
4131         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4132                                 pid, status, errno, strerror(errno)));
4133         if (pid <= 0)
4134                 goto out;
4135
4136         thisjob = NULL;
4137         for (jp = curjob; jp; jp = jp->prev_job) {
4138                 int jobstate;
4139                 struct procstat *ps;
4140                 struct procstat *psend;
4141                 if (jp->state == JOBDONE)
4142                         continue;
4143                 jobstate = JOBDONE;
4144                 ps = jp->ps;
4145                 psend = ps + jp->nprocs;
4146                 do {
4147                         if (ps->ps_pid == pid) {
4148                                 TRACE(("Job %d: changing status of proc %d "
4149                                         "from 0x%x to 0x%x\n",
4150                                         jobno(jp), pid, ps->ps_status, status));
4151                                 ps->ps_status = status;
4152                                 thisjob = jp;
4153                         }
4154                         if (ps->ps_status == -1)
4155                                 jobstate = JOBRUNNING;
4156 #if JOBS
4157                         if (jobstate == JOBRUNNING)
4158                                 continue;
4159                         if (WIFSTOPPED(ps->ps_status)) {
4160                                 jp->stopstatus = ps->ps_status;
4161                                 jobstate = JOBSTOPPED;
4162                         }
4163 #endif
4164                 } while (++ps < psend);
4165                 if (!thisjob)
4166                         continue;
4167
4168                 /* Found the job where one of its processes changed its state.
4169                  * Is there at least one live and running process in this job? */
4170                 if (jobstate != JOBRUNNING) {
4171                         /* No. All live processes in the job are stopped
4172                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4173                          */
4174                         thisjob->changed = 1;
4175                         if (thisjob->state != jobstate) {
4176                                 TRACE(("Job %d: changing state from %d to %d\n",
4177                                         jobno(thisjob), thisjob->state, jobstate));
4178                                 thisjob->state = jobstate;
4179 #if JOBS
4180                                 if (jobstate == JOBSTOPPED)
4181                                         set_curjob(thisjob, CUR_STOPPED);
4182 #endif
4183                         }
4184                 }
4185                 goto out;
4186         }
4187         /* The process wasn't found in job list */
4188 #if JOBS
4189         if (!WIFSTOPPED(status))
4190                 jobless--;
4191 #endif
4192  out:
4193         INT_ON;
4194
4195         if (thisjob && thisjob == job) {
4196                 char s[48 + 1];
4197                 int len;
4198
4199                 len = sprint_status48(s, status, 1);
4200                 if (len) {
4201                         s[len] = '\n';
4202                         s[len + 1] = '\0';
4203                         out2str(s);
4204                 }
4205         }
4206         return pid;
4207 }
4208
4209 #if JOBS
4210 static void
4211 showjob(struct job *jp, int mode)
4212 {
4213         struct procstat *ps;
4214         struct procstat *psend;
4215         int col;
4216         int indent_col;
4217         char s[16 + 16 + 48];
4218         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4219
4220         ps = jp->ps;
4221
4222         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4223                 /* just output process (group) id of pipeline */
4224                 fprintf(out, "%d\n", ps->ps_pid);
4225                 return;
4226         }
4227
4228         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4229         indent_col = col;
4230
4231         if (jp == curjob)
4232                 s[col - 3] = '+';
4233         else if (curjob && jp == curjob->prev_job)
4234                 s[col - 3] = '-';
4235
4236         if (mode & SHOW_PIDS)
4237                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4238
4239         psend = ps + jp->nprocs;
4240
4241         if (jp->state == JOBRUNNING) {
4242                 strcpy(s + col, "Running");
4243                 col += sizeof("Running") - 1;
4244         } else {
4245                 int status = psend[-1].ps_status;
4246                 if (jp->state == JOBSTOPPED)
4247                         status = jp->stopstatus;
4248                 col += sprint_status48(s + col, status, 0);
4249         }
4250         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4251
4252         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4253          * or prints several "PID             | <cmdN>" lines,
4254          * depending on SHOW_PIDS bit.
4255          * We do not print status of individual processes
4256          * between PID and <cmdN>. bash does it, but not very well:
4257          * first line shows overall job status, not process status,
4258          * making it impossible to know 1st process status.
4259          */
4260         goto start;
4261         do {
4262                 /* for each process */
4263                 s[0] = '\0';
4264                 col = 33;
4265                 if (mode & SHOW_PIDS)
4266                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4267  start:
4268                 fprintf(out, "%s%*c%s%s",
4269                                 s,
4270                                 33 - col >= 0 ? 33 - col : 0, ' ',
4271                                 ps == jp->ps ? "" : "| ",
4272                                 ps->ps_cmd
4273                 );
4274         } while (++ps != psend);
4275         newline_and_flush(out);
4276
4277         jp->changed = 0;
4278
4279         if (jp->state == JOBDONE) {
4280                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4281                 freejob(jp);
4282         }
4283 }
4284
4285 /*
4286  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4287  * statuses have changed since the last call to showjobs.
4288  */
4289 static void
4290 showjobs(int mode)
4291 {
4292         struct job *jp;
4293
4294         TRACE(("showjobs(0x%x) called\n", mode));
4295
4296         /* Handle all finished jobs */
4297         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4298                 continue;
4299
4300         for (jp = curjob; jp; jp = jp->prev_job) {
4301                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4302                         showjob(jp, mode);
4303                 }
4304         }
4305 }
4306
4307 static int FAST_FUNC
4308 jobscmd(int argc UNUSED_PARAM, char **argv)
4309 {
4310         int mode, m;
4311
4312         mode = 0;
4313         while ((m = nextopt("lp")) != '\0') {
4314                 if (m == 'l')
4315                         mode |= SHOW_PIDS;
4316                 else
4317                         mode |= SHOW_ONLY_PGID;
4318         }
4319
4320         argv = argptr;
4321         if (*argv) {
4322                 do
4323                         showjob(getjob(*argv, 0), mode);
4324                 while (*++argv);
4325         } else {
4326                 showjobs(mode);
4327         }
4328
4329         return 0;
4330 }
4331 #endif /* JOBS */
4332
4333 /* Called only on finished or stopped jobs (no members are running) */
4334 static int
4335 getstatus(struct job *job)
4336 {
4337         int status;
4338         int retval;
4339         struct procstat *ps;
4340
4341         /* Fetch last member's status */
4342         ps = job->ps + job->nprocs - 1;
4343         status = ps->ps_status;
4344         if (pipefail) {
4345                 /* "set -o pipefail" mode: use last _nonzero_ status */
4346                 while (status == 0 && --ps >= job->ps)
4347                         status = ps->ps_status;
4348         }
4349
4350         retval = WEXITSTATUS(status);
4351         if (!WIFEXITED(status)) {
4352 #if JOBS
4353                 retval = WSTOPSIG(status);
4354                 if (!WIFSTOPPED(status))
4355 #endif
4356                 {
4357                         /* XXX: limits number of signals */
4358                         retval = WTERMSIG(status);
4359 #if JOBS
4360                         if (retval == SIGINT)
4361                                 job->sigint = 1;
4362 #endif
4363                 }
4364                 retval += 128;
4365         }
4366         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4367                 jobno(job), job->nprocs, status, retval));
4368         return retval;
4369 }
4370
4371 static int FAST_FUNC
4372 waitcmd(int argc UNUSED_PARAM, char **argv)
4373 {
4374         struct job *job;
4375         int retval;
4376         struct job *jp;
4377
4378         nextopt(nullstr);
4379         retval = 0;
4380
4381         argv = argptr;
4382         if (!*argv) {
4383                 /* wait for all jobs */
4384                 for (;;) {
4385                         jp = curjob;
4386                         while (1) {
4387                                 if (!jp) /* no running procs */
4388                                         goto ret;
4389                                 if (jp->state == JOBRUNNING)
4390                                         break;
4391                                 jp->waited = 1;
4392                                 jp = jp->prev_job;
4393                         }
4394         /* man bash:
4395          * "When bash is waiting for an asynchronous command via
4396          * the wait builtin, the reception of a signal for which a trap
4397          * has been set will cause the wait builtin to return immediately
4398          * with an exit status greater than 128, immediately after which
4399          * the trap is executed."
4400          */
4401                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4402         /* if child sends us a signal *and immediately exits*,
4403          * dowait() returns pid > 0. Check this case,
4404          * not "if (dowait() < 0)"!
4405          */
4406                         if (pending_sig)
4407                                 goto sigout;
4408                 }
4409         }
4410
4411         retval = 127;
4412         do {
4413                 if (**argv != '%') {
4414                         pid_t pid = number(*argv);
4415                         job = curjob;
4416                         while (1) {
4417                                 if (!job)
4418                                         goto repeat;
4419                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4420                                         break;
4421                                 job = job->prev_job;
4422                         }
4423                 } else {
4424                         job = getjob(*argv, 0);
4425                 }
4426                 /* loop until process terminated or stopped */
4427                 while (job->state == JOBRUNNING) {
4428                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4429                         if (pending_sig)
4430                                 goto sigout;
4431                 }
4432                 job->waited = 1;
4433                 retval = getstatus(job);
4434  repeat: ;
4435         } while (*++argv);
4436
4437  ret:
4438         return retval;
4439  sigout:
4440         retval = 128 + pending_sig;
4441         return retval;
4442 }
4443
4444 static struct job *
4445 growjobtab(void)
4446 {
4447         size_t len;
4448         ptrdiff_t offset;
4449         struct job *jp, *jq;
4450
4451         len = njobs * sizeof(*jp);
4452         jq = jobtab;
4453         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4454
4455         offset = (char *)jp - (char *)jq;
4456         if (offset) {
4457                 /* Relocate pointers */
4458                 size_t l = len;
4459
4460                 jq = (struct job *)((char *)jq + l);
4461                 while (l) {
4462                         l -= sizeof(*jp);
4463                         jq--;
4464 #define joff(p) ((struct job *)((char *)(p) + l))
4465 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4466                         if (joff(jp)->ps == &jq->ps0)
4467                                 jmove(joff(jp)->ps);
4468                         if (joff(jp)->prev_job)
4469                                 jmove(joff(jp)->prev_job);
4470                 }
4471                 if (curjob)
4472                         jmove(curjob);
4473 #undef joff
4474 #undef jmove
4475         }
4476
4477         njobs += 4;
4478         jobtab = jp;
4479         jp = (struct job *)((char *)jp + len);
4480         jq = jp + 3;
4481         do {
4482                 jq->used = 0;
4483         } while (--jq >= jp);
4484         return jp;
4485 }
4486
4487 /*
4488  * Return a new job structure.
4489  * Called with interrupts off.
4490  */
4491 static struct job *
4492 makejob(/*union node *node,*/ int nprocs)
4493 {
4494         int i;
4495         struct job *jp;
4496
4497         for (i = njobs, jp = jobtab; ; jp++) {
4498                 if (--i < 0) {
4499                         jp = growjobtab();
4500                         break;
4501                 }
4502                 if (jp->used == 0)
4503                         break;
4504                 if (jp->state != JOBDONE || !jp->waited)
4505                         continue;
4506 #if JOBS
4507                 if (doing_jobctl)
4508                         continue;
4509 #endif
4510                 freejob(jp);
4511                 break;
4512         }
4513         memset(jp, 0, sizeof(*jp));
4514 #if JOBS
4515         /* jp->jobctl is a bitfield.
4516          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4517         if (doing_jobctl)
4518                 jp->jobctl = 1;
4519 #endif
4520         jp->prev_job = curjob;
4521         curjob = jp;
4522         jp->used = 1;
4523         jp->ps = &jp->ps0;
4524         if (nprocs > 1) {
4525                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4526         }
4527         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4528                                 jobno(jp)));
4529         return jp;
4530 }
4531
4532 #if JOBS
4533 /*
4534  * Return a string identifying a command (to be printed by the
4535  * jobs command).
4536  */
4537 static char *cmdnextc;
4538
4539 static void
4540 cmdputs(const char *s)
4541 {
4542         static const char vstype[VSTYPE + 1][3] = {
4543                 "", "}", "-", "+", "?", "=",
4544                 "%", "%%", "#", "##"
4545                 IF_BASH_SUBSTR(, ":")
4546                 IF_BASH_PATTERN_SUBST(, "/", "//")
4547         };
4548
4549         const char *p, *str;
4550         char cc[2];
4551         char *nextc;
4552         unsigned char c;
4553         unsigned char subtype = 0;
4554         int quoted = 0;
4555
4556         cc[1] = '\0';
4557         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4558         p = s;
4559         while ((c = *p++) != '\0') {
4560                 str = NULL;
4561                 switch (c) {
4562                 case CTLESC:
4563                         c = *p++;
4564                         break;
4565                 case CTLVAR:
4566                         subtype = *p++;
4567                         if ((subtype & VSTYPE) == VSLENGTH)
4568                                 str = "${#";
4569                         else
4570                                 str = "${";
4571                         goto dostr;
4572                 case CTLENDVAR:
4573                         str = "\"}" + !(quoted & 1);
4574                         quoted >>= 1;
4575                         subtype = 0;
4576                         goto dostr;
4577                 case CTLBACKQ:
4578                         str = "$(...)";
4579                         goto dostr;
4580 #if ENABLE_FEATURE_SH_MATH
4581                 case CTLARI:
4582                         str = "$((";
4583                         goto dostr;
4584                 case CTLENDARI:
4585                         str = "))";
4586                         goto dostr;
4587 #endif
4588                 case CTLQUOTEMARK:
4589                         quoted ^= 1;
4590                         c = '"';
4591                         break;
4592                 case '=':
4593                         if (subtype == 0)
4594                                 break;
4595                         if ((subtype & VSTYPE) != VSNORMAL)
4596                                 quoted <<= 1;
4597                         str = vstype[subtype & VSTYPE];
4598                         if (subtype & VSNUL)
4599                                 c = ':';
4600                         else
4601                                 goto checkstr;
4602                         break;
4603                 case '\'':
4604                 case '\\':
4605                 case '"':
4606                 case '$':
4607                         /* These can only happen inside quotes */
4608                         cc[0] = c;
4609                         str = cc;
4610                         c = '\\';
4611                         break;
4612                 default:
4613                         break;
4614                 }
4615                 USTPUTC(c, nextc);
4616  checkstr:
4617                 if (!str)
4618                         continue;
4619  dostr:
4620                 while ((c = *str++) != '\0') {
4621                         USTPUTC(c, nextc);
4622                 }
4623         } /* while *p++ not NUL */
4624
4625         if (quoted & 1) {
4626                 USTPUTC('"', nextc);
4627         }
4628         *nextc = 0;
4629         cmdnextc = nextc;
4630 }
4631
4632 /* cmdtxt() and cmdlist() call each other */
4633 static void cmdtxt(union node *n);
4634
4635 static void
4636 cmdlist(union node *np, int sep)
4637 {
4638         for (; np; np = np->narg.next) {
4639                 if (!sep)
4640                         cmdputs(" ");
4641                 cmdtxt(np);
4642                 if (sep && np->narg.next)
4643                         cmdputs(" ");
4644         }
4645 }
4646
4647 static void
4648 cmdtxt(union node *n)
4649 {
4650         union node *np;
4651         struct nodelist *lp;
4652         const char *p;
4653
4654         if (!n)
4655                 return;
4656         switch (n->type) {
4657         default:
4658 #if DEBUG
4659                 abort();
4660 #endif
4661         case NPIPE:
4662                 lp = n->npipe.cmdlist;
4663                 for (;;) {
4664                         cmdtxt(lp->n);
4665                         lp = lp->next;
4666                         if (!lp)
4667                                 break;
4668                         cmdputs(" | ");
4669                 }
4670                 break;
4671         case NSEMI:
4672                 p = "; ";
4673                 goto binop;
4674         case NAND:
4675                 p = " && ";
4676                 goto binop;
4677         case NOR:
4678                 p = " || ";
4679  binop:
4680                 cmdtxt(n->nbinary.ch1);
4681                 cmdputs(p);
4682                 n = n->nbinary.ch2;
4683                 goto donode;
4684         case NREDIR:
4685         case NBACKGND:
4686                 n = n->nredir.n;
4687                 goto donode;
4688         case NNOT:
4689                 cmdputs("!");
4690                 n = n->nnot.com;
4691  donode:
4692                 cmdtxt(n);
4693                 break;
4694         case NIF:
4695                 cmdputs("if ");
4696                 cmdtxt(n->nif.test);
4697                 cmdputs("; then ");
4698                 if (n->nif.elsepart) {
4699                         cmdtxt(n->nif.ifpart);
4700                         cmdputs("; else ");
4701                         n = n->nif.elsepart;
4702                 } else {
4703                         n = n->nif.ifpart;
4704                 }
4705                 p = "; fi";
4706                 goto dotail;
4707         case NSUBSHELL:
4708                 cmdputs("(");
4709                 n = n->nredir.n;
4710                 p = ")";
4711                 goto dotail;
4712         case NWHILE:
4713                 p = "while ";
4714                 goto until;
4715         case NUNTIL:
4716                 p = "until ";
4717  until:
4718                 cmdputs(p);
4719                 cmdtxt(n->nbinary.ch1);
4720                 n = n->nbinary.ch2;
4721                 p = "; done";
4722  dodo:
4723                 cmdputs("; do ");
4724  dotail:
4725                 cmdtxt(n);
4726                 goto dotail2;
4727         case NFOR:
4728                 cmdputs("for ");
4729                 cmdputs(n->nfor.var);
4730                 cmdputs(" in ");
4731                 cmdlist(n->nfor.args, 1);
4732                 n = n->nfor.body;
4733                 p = "; done";
4734                 goto dodo;
4735         case NDEFUN:
4736                 cmdputs(n->narg.text);
4737                 p = "() { ... }";
4738                 goto dotail2;
4739         case NCMD:
4740                 cmdlist(n->ncmd.args, 1);
4741                 cmdlist(n->ncmd.redirect, 0);
4742                 break;
4743         case NARG:
4744                 p = n->narg.text;
4745  dotail2:
4746                 cmdputs(p);
4747                 break;
4748         case NHERE:
4749         case NXHERE:
4750                 p = "<<...";
4751                 goto dotail2;
4752         case NCASE:
4753                 cmdputs("case ");
4754                 cmdputs(n->ncase.expr->narg.text);
4755                 cmdputs(" in ");
4756                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4757                         cmdtxt(np->nclist.pattern);
4758                         cmdputs(") ");
4759                         cmdtxt(np->nclist.body);
4760                         cmdputs(";; ");
4761                 }
4762                 p = "esac";
4763                 goto dotail2;
4764         case NTO:
4765                 p = ">";
4766                 goto redir;
4767         case NCLOBBER:
4768                 p = ">|";
4769                 goto redir;
4770         case NAPPEND:
4771                 p = ">>";
4772                 goto redir;
4773 #if BASH_REDIR_OUTPUT
4774         case NTO2:
4775 #endif
4776         case NTOFD:
4777                 p = ">&";
4778                 goto redir;
4779         case NFROM:
4780                 p = "<";
4781                 goto redir;
4782         case NFROMFD:
4783                 p = "<&";
4784                 goto redir;
4785         case NFROMTO:
4786                 p = "<>";
4787  redir:
4788                 cmdputs(utoa(n->nfile.fd));
4789                 cmdputs(p);
4790                 if (n->type == NTOFD || n->type == NFROMFD) {
4791                         cmdputs(utoa(n->ndup.dupfd));
4792                         break;
4793                 }
4794                 n = n->nfile.fname;
4795                 goto donode;
4796         }
4797 }
4798
4799 static char *
4800 commandtext(union node *n)
4801 {
4802         char *name;
4803
4804         STARTSTACKSTR(cmdnextc);
4805         cmdtxt(n);
4806         name = stackblock();
4807         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4808         return ckstrdup(name);
4809 }
4810 #endif /* JOBS */
4811
4812 /*
4813  * Fork off a subshell.  If we are doing job control, give the subshell its
4814  * own process group.  Jp is a job structure that the job is to be added to.
4815  * N is the command that will be evaluated by the child.  Both jp and n may
4816  * be NULL.  The mode parameter can be one of the following:
4817  *      FORK_FG - Fork off a foreground process.
4818  *      FORK_BG - Fork off a background process.
4819  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4820  *                   process group even if job control is on.
4821  *
4822  * When job control is turned off, background processes have their standard
4823  * input redirected to /dev/null (except for the second and later processes
4824  * in a pipeline).
4825  *
4826  * Called with interrupts off.
4827  */
4828 /*
4829  * Clear traps on a fork.
4830  */
4831 static void
4832 clear_traps(void)
4833 {
4834         char **tp;
4835
4836         INT_OFF;
4837         for (tp = trap; tp < &trap[NSIG]; tp++) {
4838                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4839                         if (trap_ptr == trap)
4840                                 free(*tp);
4841                         /* else: it "belongs" to trap_ptr vector, don't free */
4842                         *tp = NULL;
4843                         if ((tp - trap) != 0)
4844                                 setsignal(tp - trap);
4845                 }
4846         }
4847         may_have_traps = 0;
4848         INT_ON;
4849 }
4850
4851 /* Lives far away from here, needed for forkchild */
4852 static void closescript(void);
4853
4854 /* Called after fork(), in child */
4855 /* jp and n are NULL when called by openhere() for heredoc support */
4856 static NOINLINE void
4857 forkchild(struct job *jp, union node *n, int mode)
4858 {
4859         int oldlvl;
4860
4861         TRACE(("Child shell %d\n", getpid()));
4862         oldlvl = shlvl;
4863         shlvl++;
4864
4865         /* man bash: "Non-builtin commands run by bash have signal handlers
4866          * set to the values inherited by the shell from its parent".
4867          * Do we do it correctly? */
4868
4869         closescript();
4870
4871         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4872          && n && n->type == NCMD        /* is it single cmd? */
4873         /* && n->ncmd.args->type == NARG - always true? */
4874          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4875          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4876         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4877         ) {
4878                 TRACE(("Trap hack\n"));
4879                 /* Awful hack for `trap` or $(trap).
4880                  *
4881                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4882                  * contains an example where "trap" is executed in a subshell:
4883                  *
4884                  * save_traps=$(trap)
4885                  * ...
4886                  * eval "$save_traps"
4887                  *
4888                  * Standard does not say that "trap" in subshell shall print
4889                  * parent shell's traps. It only says that its output
4890                  * must have suitable form, but then, in the above example
4891                  * (which is not supposed to be normative), it implies that.
4892                  *
4893                  * bash (and probably other shell) does implement it
4894                  * (traps are reset to defaults, but "trap" still shows them),
4895                  * but as a result, "trap" logic is hopelessly messed up:
4896                  *
4897                  * # trap
4898                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4899                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4900                  * # true | trap   <--- trap is in subshell - no output (ditto)
4901                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4902                  * trap -- 'echo Ho' SIGWINCH
4903                  * # echo `(trap)`         <--- in subshell in subshell - output
4904                  * trap -- 'echo Ho' SIGWINCH
4905                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4906                  * trap -- 'echo Ho' SIGWINCH
4907                  *
4908                  * The rules when to forget and when to not forget traps
4909                  * get really complex and nonsensical.
4910                  *
4911                  * Our solution: ONLY bare $(trap) or `trap` is special.
4912                  */
4913                 /* Save trap handler strings for trap builtin to print */
4914                 trap_ptr = xmemdup(trap, sizeof(trap));
4915                 /* Fall through into clearing traps */
4916         }
4917         clear_traps();
4918 #if JOBS
4919         /* do job control only in root shell */
4920         doing_jobctl = 0;
4921         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4922                 pid_t pgrp;
4923
4924                 if (jp->nprocs == 0)
4925                         pgrp = getpid();
4926                 else
4927                         pgrp = jp->ps[0].ps_pid;
4928                 /* this can fail because we are doing it in the parent also */
4929                 setpgid(0, pgrp);
4930                 if (mode == FORK_FG)
4931                         xtcsetpgrp(ttyfd, pgrp);
4932                 setsignal(SIGTSTP);
4933                 setsignal(SIGTTOU);
4934         } else
4935 #endif
4936         if (mode == FORK_BG) {
4937                 /* man bash: "When job control is not in effect,
4938                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4939                 ignoresig(SIGINT);
4940                 ignoresig(SIGQUIT);
4941                 if (jp->nprocs == 0) {
4942                         close(0);
4943                         if (open(bb_dev_null, O_RDONLY) != 0)
4944                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4945                 }
4946         }
4947         if (oldlvl == 0) {
4948                 if (iflag) { /* why if iflag only? */
4949                         setsignal(SIGINT);
4950                         setsignal(SIGTERM);
4951                 }
4952                 /* man bash:
4953                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4954                  * commands run by bash have signal handlers
4955                  * set to the values inherited by the shell
4956                  * from its parent".
4957                  * Take care of the second rule: */
4958                 setsignal(SIGQUIT);
4959         }
4960 #if JOBS
4961         if (n && n->type == NCMD
4962          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4963         ) {
4964                 TRACE(("Job hack\n"));
4965                 /* "jobs": we do not want to clear job list for it,
4966                  * instead we remove only _its_ own_ job from job list.
4967                  * This makes "jobs .... | cat" more useful.
4968                  */
4969                 freejob(curjob);
4970                 return;
4971         }
4972 #endif
4973         for (jp = curjob; jp; jp = jp->prev_job)
4974                 freejob(jp);
4975         jobless = 0;
4976 }
4977
4978 /* Called after fork(), in parent */
4979 #if !JOBS
4980 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4981 #endif
4982 static void
4983 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4984 {
4985         TRACE(("In parent shell: child = %d\n", pid));
4986         if (!jp) {
4987                 /* jp is NULL when called by openhere() for heredoc support */
4988                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4989                         continue;
4990                 jobless++;
4991                 return;
4992         }
4993 #if JOBS
4994         if (mode != FORK_NOJOB && jp->jobctl) {
4995                 int pgrp;
4996
4997                 if (jp->nprocs == 0)
4998                         pgrp = pid;
4999                 else
5000                         pgrp = jp->ps[0].ps_pid;
5001                 /* This can fail because we are doing it in the child also */
5002                 setpgid(pid, pgrp);
5003         }
5004 #endif
5005         if (mode == FORK_BG) {
5006                 backgndpid = pid;               /* set $! */
5007                 set_curjob(jp, CUR_RUNNING);
5008         }
5009         if (jp) {
5010                 struct procstat *ps = &jp->ps[jp->nprocs++];
5011                 ps->ps_pid = pid;
5012                 ps->ps_status = -1;
5013                 ps->ps_cmd = nullstr;
5014 #if JOBS
5015                 if (doing_jobctl && n)
5016                         ps->ps_cmd = commandtext(n);
5017 #endif
5018         }
5019 }
5020
5021 /* jp and n are NULL when called by openhere() for heredoc support */
5022 static int
5023 forkshell(struct job *jp, union node *n, int mode)
5024 {
5025         int pid;
5026
5027         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5028         pid = fork();
5029         if (pid < 0) {
5030                 TRACE(("Fork failed, errno=%d", errno));
5031                 if (jp)
5032                         freejob(jp);
5033                 ash_msg_and_raise_error("can't fork");
5034         }
5035         if (pid == 0) {
5036                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5037                 forkchild(jp, n, mode);
5038         } else {
5039                 forkparent(jp, n, mode, pid);
5040         }
5041         return pid;
5042 }
5043
5044 /*
5045  * Wait for job to finish.
5046  *
5047  * Under job control we have the problem that while a child process
5048  * is running interrupts generated by the user are sent to the child
5049  * but not to the shell.  This means that an infinite loop started by
5050  * an interactive user may be hard to kill.  With job control turned off,
5051  * an interactive user may place an interactive program inside a loop.
5052  * If the interactive program catches interrupts, the user doesn't want
5053  * these interrupts to also abort the loop.  The approach we take here
5054  * is to have the shell ignore interrupt signals while waiting for a
5055  * foreground process to terminate, and then send itself an interrupt
5056  * signal if the child process was terminated by an interrupt signal.
5057  * Unfortunately, some programs want to do a bit of cleanup and then
5058  * exit on interrupt; unless these processes terminate themselves by
5059  * sending a signal to themselves (instead of calling exit) they will
5060  * confuse this approach.
5061  *
5062  * Called with interrupts off.
5063  */
5064 static int
5065 waitforjob(struct job *jp)
5066 {
5067         int st;
5068
5069         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5070
5071         INT_OFF;
5072         while (jp->state == JOBRUNNING) {
5073                 /* In non-interactive shells, we _can_ get
5074                  * a keyboard signal here and be EINTRed,
5075                  * but we just loop back, waiting for command to complete.
5076                  *
5077                  * man bash:
5078                  * "If bash is waiting for a command to complete and receives
5079                  * a signal for which a trap has been set, the trap
5080                  * will not be executed until the command completes."
5081                  *
5082                  * Reality is that even if trap is not set, bash
5083                  * will not act on the signal until command completes.
5084                  * Try this. sleep5intoff.c:
5085                  * #include <signal.h>
5086                  * #include <unistd.h>
5087                  * int main() {
5088                  *         sigset_t set;
5089                  *         sigemptyset(&set);
5090                  *         sigaddset(&set, SIGINT);
5091                  *         sigaddset(&set, SIGQUIT);
5092                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5093                  *         sleep(5);
5094                  *         return 0;
5095                  * }
5096                  * $ bash -c './sleep5intoff; echo hi'
5097                  * ^C^C^C^C <--- pressing ^C once a second
5098                  * $ _
5099                  * $ bash -c './sleep5intoff; echo hi'
5100                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5101                  * $ _
5102                  */
5103                 dowait(DOWAIT_BLOCK, jp);
5104         }
5105         INT_ON;
5106
5107         st = getstatus(jp);
5108 #if JOBS
5109         if (jp->jobctl) {
5110                 xtcsetpgrp(ttyfd, rootpid);
5111                 restore_tty_if_stopped_or_signaled(jp);
5112
5113                 /*
5114                  * This is truly gross.
5115                  * If we're doing job control, then we did a TIOCSPGRP which
5116                  * caused us (the shell) to no longer be in the controlling
5117                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5118                  * intuit from the subprocess exit status whether a SIGINT
5119                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5120                  */
5121                 if (jp->sigint) /* TODO: do the same with all signals */
5122                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5123         }
5124         if (jp->state == JOBDONE)
5125 #endif
5126                 freejob(jp);
5127         return st;
5128 }
5129
5130 /*
5131  * return 1 if there are stopped jobs, otherwise 0
5132  */
5133 static int
5134 stoppedjobs(void)
5135 {
5136         struct job *jp;
5137         int retval;
5138
5139         retval = 0;
5140         if (job_warning)
5141                 goto out;
5142         jp = curjob;
5143         if (jp && jp->state == JOBSTOPPED) {
5144                 out2str("You have stopped jobs.\n");
5145                 job_warning = 2;
5146                 retval++;
5147         }
5148  out:
5149         return retval;
5150 }
5151
5152
5153 /*
5154  * Code for dealing with input/output redirection.
5155  */
5156
5157 #undef EMPTY
5158 #undef CLOSED
5159 #define EMPTY -2                /* marks an unused slot in redirtab */
5160 #define CLOSED -3               /* marks a slot of previously-closed fd */
5161
5162 /*
5163  * Open a file in noclobber mode.
5164  * The code was copied from bash.
5165  */
5166 static int
5167 noclobberopen(const char *fname)
5168 {
5169         int r, fd;
5170         struct stat finfo, finfo2;
5171
5172         /*
5173          * If the file exists and is a regular file, return an error
5174          * immediately.
5175          */
5176         r = stat(fname, &finfo);
5177         if (r == 0 && S_ISREG(finfo.st_mode)) {
5178                 errno = EEXIST;
5179                 return -1;
5180         }
5181
5182         /*
5183          * If the file was not present (r != 0), make sure we open it
5184          * exclusively so that if it is created before we open it, our open
5185          * will fail.  Make sure that we do not truncate an existing file.
5186          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5187          * file was not a regular file, we leave O_EXCL off.
5188          */
5189         if (r != 0)
5190                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5191         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5192
5193         /* If the open failed, return the file descriptor right away. */
5194         if (fd < 0)
5195                 return fd;
5196
5197         /*
5198          * OK, the open succeeded, but the file may have been changed from a
5199          * non-regular file to a regular file between the stat and the open.
5200          * We are assuming that the O_EXCL open handles the case where FILENAME
5201          * did not exist and is symlinked to an existing file between the stat
5202          * and open.
5203          */
5204
5205         /*
5206          * If we can open it and fstat the file descriptor, and neither check
5207          * revealed that it was a regular file, and the file has not been
5208          * replaced, return the file descriptor.
5209          */
5210         if (fstat(fd, &finfo2) == 0
5211          && !S_ISREG(finfo2.st_mode)
5212          && finfo.st_dev == finfo2.st_dev
5213          && finfo.st_ino == finfo2.st_ino
5214         ) {
5215                 return fd;
5216         }
5217
5218         /* The file has been replaced.  badness. */
5219         close(fd);
5220         errno = EEXIST;
5221         return -1;
5222 }
5223
5224 /*
5225  * Handle here documents.  Normally we fork off a process to write the
5226  * data to a pipe.  If the document is short, we can stuff the data in
5227  * the pipe without forking.
5228  */
5229 /* openhere needs this forward reference */
5230 static void expandhere(union node *arg, int fd);
5231 static int
5232 openhere(union node *redir)
5233 {
5234         int pip[2];
5235         size_t len = 0;
5236
5237         if (pipe(pip) < 0)
5238                 ash_msg_and_raise_error("pipe call failed");
5239         if (redir->type == NHERE) {
5240                 len = strlen(redir->nhere.doc->narg.text);
5241                 if (len <= PIPE_BUF) {
5242                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5243                         goto out;
5244                 }
5245         }
5246         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5247                 /* child */
5248                 close(pip[0]);
5249                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5250                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5251                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5252                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5253                 signal(SIGPIPE, SIG_DFL);
5254                 if (redir->type == NHERE)
5255                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5256                 else /* NXHERE */
5257                         expandhere(redir->nhere.doc, pip[1]);
5258                 _exit(EXIT_SUCCESS);
5259         }
5260  out:
5261         close(pip[1]);
5262         return pip[0];
5263 }
5264
5265 static int
5266 openredirect(union node *redir)
5267 {
5268         char *fname;
5269         int f;
5270
5271         switch (redir->nfile.type) {
5272 /* Can't happen, our single caller does this itself */
5273 //      case NTOFD:
5274 //      case NFROMFD:
5275 //              return -1;
5276         case NHERE:
5277         case NXHERE:
5278                 return openhere(redir);
5279         }
5280
5281         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5282          * allocated space. Do it only when we know it is safe.
5283          */
5284         fname = redir->nfile.expfname;
5285
5286         switch (redir->nfile.type) {
5287         default:
5288 #if DEBUG
5289                 abort();
5290 #endif
5291         case NFROM:
5292                 f = open(fname, O_RDONLY);
5293                 if (f < 0)
5294                         goto eopen;
5295                 break;
5296         case NFROMTO:
5297                 f = open(fname, O_RDWR|O_CREAT, 0666);
5298                 if (f < 0)
5299                         goto ecreate;
5300                 break;
5301         case NTO:
5302 #if BASH_REDIR_OUTPUT
5303         case NTO2:
5304 #endif
5305                 /* Take care of noclobber mode. */
5306                 if (Cflag) {
5307                         f = noclobberopen(fname);
5308                         if (f < 0)
5309                                 goto ecreate;
5310                         break;
5311                 }
5312                 /* FALLTHROUGH */
5313         case NCLOBBER:
5314                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5315                 if (f < 0)
5316                         goto ecreate;
5317                 break;
5318         case NAPPEND:
5319                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5320                 if (f < 0)
5321                         goto ecreate;
5322                 break;
5323         }
5324
5325         return f;
5326  ecreate:
5327         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5328  eopen:
5329         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5330 }
5331
5332 /*
5333  * Copy a file descriptor to be >= 10. Throws exception on error.
5334  */
5335 static int
5336 savefd(int from)
5337 {
5338         int newfd;
5339         int err;
5340
5341         newfd = fcntl(from, F_DUPFD, 10);
5342         err = newfd < 0 ? errno : 0;
5343         if (err != EBADF) {
5344                 if (err)
5345                         ash_msg_and_raise_error("%d: %m", from);
5346                 close(from);
5347                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5348         }
5349
5350         return newfd;
5351 }
5352 static int
5353 dup2_or_raise(int from, int to)
5354 {
5355         int newfd;
5356
5357         newfd = (from != to) ? dup2(from, to) : to;
5358         if (newfd < 0) {
5359                 /* Happens when source fd is not open: try "echo >&99" */
5360                 ash_msg_and_raise_error("%d: %m", from);
5361         }
5362         return newfd;
5363 }
5364
5365 /* Struct def and variable are moved down to the first usage site */
5366 struct two_fd_t {
5367         int orig, copy;
5368 };
5369 struct redirtab {
5370         struct redirtab *next;
5371         int pair_count;
5372         struct two_fd_t two_fd[];
5373 };
5374 #define redirlist (G_var.redirlist)
5375 enum {
5376         COPYFD_RESTORE = (int)~(INT_MAX),
5377 };
5378
5379 static int
5380 need_to_remember(struct redirtab *rp, int fd)
5381 {
5382         int i;
5383
5384         if (!rp) /* remembering was not requested */
5385                 return 0;
5386
5387         for (i = 0; i < rp->pair_count; i++) {
5388                 if (rp->two_fd[i].orig == fd) {
5389                         /* already remembered */
5390                         return 0;
5391                 }
5392         }
5393         return 1;
5394 }
5395
5396 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5397 static int
5398 is_hidden_fd(struct redirtab *rp, int fd)
5399 {
5400         int i;
5401         struct parsefile *pf;
5402
5403         if (fd == -1)
5404                 return 0;
5405         /* Check open scripts' fds */
5406         pf = g_parsefile;
5407         while (pf) {
5408                 /* We skip pf_fd == 0 case because of the following case:
5409                  * $ ash  # running ash interactively
5410                  * $ . ./script.sh
5411                  * and in script.sh: "exec 9>&0".
5412                  * Even though top-level pf_fd _is_ 0,
5413                  * it's still ok to use it: "read" builtin uses it,
5414                  * why should we cripple "exec" builtin?
5415                  */
5416                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5417                         return 1;
5418                 }
5419                 pf = pf->prev;
5420         }
5421
5422         if (!rp)
5423                 return 0;
5424         /* Check saved fds of redirects */
5425         fd |= COPYFD_RESTORE;
5426         for (i = 0; i < rp->pair_count; i++) {
5427                 if (rp->two_fd[i].copy == fd) {
5428                         return 1;
5429                 }
5430         }
5431         return 0;
5432 }
5433
5434 /*
5435  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5436  * old file descriptors are stashed away so that the redirection can be
5437  * undone by calling popredir.
5438  */
5439 /* flags passed to redirect */
5440 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5441 #define REDIR_SAVEFD2 03        /* set preverrout */
5442 static void
5443 redirect(union node *redir, int flags)
5444 {
5445         struct redirtab *sv;
5446         int sv_pos;
5447         int i;
5448         int fd;
5449         int newfd;
5450         int copied_fd2 = -1;
5451
5452         if (!redir) {
5453                 return;
5454         }
5455
5456         sv = NULL;
5457         sv_pos = 0;
5458         INT_OFF;
5459         if (flags & REDIR_PUSH) {
5460                 union node *tmp = redir;
5461                 do {
5462                         sv_pos++;
5463 #if BASH_REDIR_OUTPUT
5464                         if (tmp->nfile.type == NTO2)
5465                                 sv_pos++;
5466 #endif
5467                         tmp = tmp->nfile.next;
5468                 } while (tmp);
5469                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5470                 sv->next = redirlist;
5471                 sv->pair_count = sv_pos;
5472                 redirlist = sv;
5473                 while (sv_pos > 0) {
5474                         sv_pos--;
5475                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5476                 }
5477         }
5478
5479         do {
5480                 int right_fd = -1;
5481                 fd = redir->nfile.fd;
5482                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5483                         right_fd = redir->ndup.dupfd;
5484                         //bb_error_msg("doing %d > %d", fd, right_fd);
5485                         /* redirect from/to same file descriptor? */
5486                         if (right_fd == fd)
5487                                 continue;
5488                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5489                         if (is_hidden_fd(sv, right_fd)) {
5490                                 errno = EBADF; /* as if it is closed */
5491                                 ash_msg_and_raise_error("%d: %m", right_fd);
5492                         }
5493                         newfd = -1;
5494                 } else {
5495                         newfd = openredirect(redir); /* always >= 0 */
5496                         if (fd == newfd) {
5497                                 /* Descriptor wasn't open before redirect.
5498                                  * Mark it for close in the future */
5499                                 if (need_to_remember(sv, fd)) {
5500                                         goto remember_to_close;
5501                                 }
5502                                 continue;
5503                         }
5504                 }
5505 #if BASH_REDIR_OUTPUT
5506  redirect_more:
5507 #endif
5508                 if (need_to_remember(sv, fd)) {
5509                         /* Copy old descriptor */
5510                         /* Careful to not accidentally "save"
5511                          * to the same fd as right side fd in N>&M */
5512                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5513 #if defined(F_DUPFD_CLOEXEC)
5514                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5515 #else
5516                         i = fcntl(fd, F_DUPFD, minfd);
5517 #endif
5518                         if (i == -1) {
5519                                 i = errno;
5520                                 if (i != EBADF) {
5521                                         /* Strange error (e.g. "too many files" EMFILE?) */
5522                                         if (newfd >= 0)
5523                                                 close(newfd);
5524                                         errno = i;
5525                                         ash_msg_and_raise_error("%d: %m", fd);
5526                                         /* NOTREACHED */
5527                                 }
5528                                 /* EBADF: it is not open - good, remember to close it */
5529  remember_to_close:
5530                                 i = CLOSED;
5531                         } else { /* fd is open, save its copy */
5532 #if !defined(F_DUPFD_CLOEXEC)
5533                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5534 #endif
5535                                 /* "exec fd>&-" should not close fds
5536                                  * which point to script file(s).
5537                                  * Force them to be restored afterwards */
5538                                 if (is_hidden_fd(sv, fd))
5539                                         i |= COPYFD_RESTORE;
5540                         }
5541                         if (fd == 2)
5542                                 copied_fd2 = i;
5543                         sv->two_fd[sv_pos].orig = fd;
5544                         sv->two_fd[sv_pos].copy = i;
5545                         sv_pos++;
5546                 }
5547                 if (newfd < 0) {
5548                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5549                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5550                                 /* Don't want to trigger debugging */
5551                                 if (fd != -1)
5552                                         close(fd);
5553                         } else {
5554                                 dup2_or_raise(redir->ndup.dupfd, fd);
5555                         }
5556                 } else if (fd != newfd) { /* move newfd to fd */
5557                         dup2_or_raise(newfd, fd);
5558 #if BASH_REDIR_OUTPUT
5559                         if (!(redir->nfile.type == NTO2 && fd == 2))
5560 #endif
5561                                 close(newfd);
5562                 }
5563 #if BASH_REDIR_OUTPUT
5564                 if (redir->nfile.type == NTO2 && fd == 1) {
5565                         /* We already redirected it to fd 1, now copy it to 2 */
5566                         newfd = 1;
5567                         fd = 2;
5568                         goto redirect_more;
5569                 }
5570 #endif
5571         } while ((redir = redir->nfile.next) != NULL);
5572
5573         INT_ON;
5574         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5575                 preverrout_fd = copied_fd2;
5576 }
5577
5578 /*
5579  * Undo the effects of the last redirection.
5580  */
5581 static void
5582 popredir(int drop, int restore)
5583 {
5584         struct redirtab *rp;
5585         int i;
5586
5587         if (redirlist == NULL)
5588                 return;
5589         INT_OFF;
5590         rp = redirlist;
5591         for (i = 0; i < rp->pair_count; i++) {
5592                 int fd = rp->two_fd[i].orig;
5593                 int copy = rp->two_fd[i].copy;
5594                 if (copy == CLOSED) {
5595                         if (!drop)
5596                                 close(fd);
5597                         continue;
5598                 }
5599                 if (copy != EMPTY) {
5600                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5601                                 copy &= ~COPYFD_RESTORE;
5602                                 /*close(fd);*/
5603                                 dup2_or_raise(copy, fd);
5604                         }
5605                         close(copy & ~COPYFD_RESTORE);
5606                 }
5607         }
5608         redirlist = rp->next;
5609         free(rp);
5610         INT_ON;
5611 }
5612
5613 /*
5614  * Undo all redirections.  Called on error or interrupt.
5615  */
5616
5617 static int
5618 redirectsafe(union node *redir, int flags)
5619 {
5620         int err;
5621         volatile int saveint;
5622         struct jmploc *volatile savehandler = exception_handler;
5623         struct jmploc jmploc;
5624
5625         SAVE_INT(saveint);
5626         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5627         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5628         if (!err) {
5629                 exception_handler = &jmploc;
5630                 redirect(redir, flags);
5631         }
5632         exception_handler = savehandler;
5633         if (err && exception_type != EXERROR)
5634                 longjmp(exception_handler->loc, 1);
5635         RESTORE_INT(saveint);
5636         return err;
5637 }
5638
5639
5640 /* ============ Routines to expand arguments to commands
5641  *
5642  * We have to deal with backquotes, shell variables, and file metacharacters.
5643  */
5644
5645 #if ENABLE_FEATURE_SH_MATH
5646 static arith_t
5647 ash_arith(const char *s)
5648 {
5649         arith_state_t math_state;
5650         arith_t result;
5651
5652         math_state.lookupvar = lookupvar;
5653         math_state.setvar    = setvar0;
5654         //math_state.endofname = endofname;
5655
5656         INT_OFF;
5657         result = arith(&math_state, s);
5658         if (math_state.errmsg)
5659                 ash_msg_and_raise_error(math_state.errmsg);
5660         INT_ON;
5661
5662         return result;
5663 }
5664 #endif
5665
5666 /*
5667  * expandarg flags
5668  */
5669 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5670 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5671 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5672 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5673 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5674  * POSIX says for this case:
5675  *  Pathname expansion shall not be performed on the word by a
5676  *  non-interactive shell; an interactive shell may perform it, but shall
5677  *  do so only when the expansion would result in one word.
5678  * Currently, our code complies to the above rule by never globbing
5679  * redirection filenames.
5680  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5681  * (this means that on a typical Linux distro, bash almost always
5682  * performs globbing, and thus diverges from what we do).
5683  */
5684 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5685 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5686 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5687 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5688 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5689 /*
5690  * rmescape() flags
5691  */
5692 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5693 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5694 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5695 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5696 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5697
5698 /* Add CTLESC when necessary. */
5699 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR)
5700 /* Do not skip NUL characters. */
5701 #define QUOTES_KEEPNUL EXP_TILDE
5702
5703 /*
5704  * Structure specifying which parts of the string should be searched
5705  * for IFS characters.
5706  */
5707 struct ifsregion {
5708         struct ifsregion *next; /* next region in list */
5709         int begoff;             /* offset of start of region */
5710         int endoff;             /* offset of end of region */
5711         int nulonly;            /* search for nul bytes only */
5712 };
5713
5714 struct arglist {
5715         struct strlist *list;
5716         struct strlist **lastp;
5717 };
5718
5719 /* output of current string */
5720 static char *expdest;
5721 /* list of back quote expressions */
5722 static struct nodelist *argbackq;
5723 /* first struct in list of ifs regions */
5724 static struct ifsregion ifsfirst;
5725 /* last struct in list */
5726 static struct ifsregion *ifslastp;
5727 /* holds expanded arg list */
5728 static struct arglist exparg;
5729
5730 /*
5731  * Our own itoa().
5732  */
5733 #if !ENABLE_FEATURE_SH_MATH
5734 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5735 typedef long arith_t;
5736 # define ARITH_FMT "%ld"
5737 #endif
5738 static int
5739 cvtnum(arith_t num)
5740 {
5741         int len;
5742
5743         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5744         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5745         STADJUST(len, expdest);
5746         return len;
5747 }
5748
5749 /*
5750  * Break the argument string into pieces based upon IFS and add the
5751  * strings to the argument list.  The regions of the string to be
5752  * searched for IFS characters have been stored by recordregion.
5753  */
5754 static void
5755 ifsbreakup(char *string, struct arglist *arglist)
5756 {
5757         struct ifsregion *ifsp;
5758         struct strlist *sp;
5759         char *start;
5760         char *p;
5761         char *q;
5762         const char *ifs, *realifs;
5763         int ifsspc;
5764         int nulonly;
5765
5766         start = string;
5767         if (ifslastp != NULL) {
5768                 ifsspc = 0;
5769                 nulonly = 0;
5770                 realifs = ifsset() ? ifsval() : defifs;
5771                 ifsp = &ifsfirst;
5772                 do {
5773                         p = string + ifsp->begoff;
5774                         nulonly = ifsp->nulonly;
5775                         ifs = nulonly ? nullstr : realifs;
5776                         ifsspc = 0;
5777                         while (p < string + ifsp->endoff) {
5778                                 q = p;
5779                                 if ((unsigned char)*p == CTLESC)
5780                                         p++;
5781                                 if (!strchr(ifs, *p)) {
5782                                         p++;
5783                                         continue;
5784                                 }
5785                                 if (!nulonly)
5786                                         ifsspc = (strchr(defifs, *p) != NULL);
5787                                 /* Ignore IFS whitespace at start */
5788                                 if (q == start && ifsspc) {
5789                                         p++;
5790                                         start = p;
5791                                         continue;
5792                                 }
5793                                 *q = '\0';
5794                                 sp = stzalloc(sizeof(*sp));
5795                                 sp->text = start;
5796                                 *arglist->lastp = sp;
5797                                 arglist->lastp = &sp->next;
5798                                 p++;
5799                                 if (!nulonly) {
5800                                         for (;;) {
5801                                                 if (p >= string + ifsp->endoff) {
5802                                                         break;
5803                                                 }
5804                                                 q = p;
5805                                                 if ((unsigned char)*p == CTLESC)
5806                                                         p++;
5807                                                 if (strchr(ifs, *p) == NULL) {
5808                                                         p = q;
5809                                                         break;
5810                                                 }
5811                                                 if (strchr(defifs, *p) == NULL) {
5812                                                         if (ifsspc) {
5813                                                                 p++;
5814                                                                 ifsspc = 0;
5815                                                         } else {
5816                                                                 p = q;
5817                                                                 break;
5818                                                         }
5819                                                 } else
5820                                                         p++;
5821                                         }
5822                                 }
5823                                 start = p;
5824                         } /* while */
5825                         ifsp = ifsp->next;
5826                 } while (ifsp != NULL);
5827                 if (nulonly)
5828                         goto add;
5829         }
5830
5831         if (!*start)
5832                 return;
5833
5834  add:
5835         sp = stzalloc(sizeof(*sp));
5836         sp->text = start;
5837         *arglist->lastp = sp;
5838         arglist->lastp = &sp->next;
5839 }
5840
5841 static void
5842 ifsfree(void)
5843 {
5844         struct ifsregion *p = ifsfirst.next;
5845
5846         if (!p)
5847                 goto out;
5848
5849         INT_OFF;
5850         do {
5851                 struct ifsregion *ifsp;
5852                 ifsp = p->next;
5853                 free(p);
5854                 p = ifsp;
5855         } while (p);
5856         ifsfirst.next = NULL;
5857         INT_ON;
5858  out:
5859         ifslastp = NULL;
5860 }
5861
5862 static size_t
5863 esclen(const char *start, const char *p)
5864 {
5865         size_t esc = 0;
5866
5867         while (p > start && (unsigned char)*--p == CTLESC) {
5868                 esc++;
5869         }
5870         return esc;
5871 }
5872
5873 /*
5874  * Remove any CTLESC characters from a string.
5875  */
5876 static char *
5877 rmescapes(char *str, int flag)
5878 {
5879         static const char qchars[] ALIGN1 = {
5880                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5881
5882         char *p, *q, *r;
5883         unsigned inquotes;
5884         unsigned protect_against_glob;
5885         unsigned globbing;
5886         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5887
5888         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5889         if (!p)
5890                 return str;
5891
5892         q = p;
5893         r = str;
5894         if (flag & RMESCAPE_ALLOC) {
5895                 size_t len = p - str;
5896                 size_t fulllen = len + strlen(p) + 1;
5897
5898                 if (flag & RMESCAPE_GROW) {
5899                         int strloc = str - (char *)stackblock();
5900                         r = makestrspace(fulllen, expdest);
5901                         /* p and str may be invalidated by makestrspace */
5902                         str = (char *)stackblock() + strloc;
5903                         p = str + len;
5904                 } else if (flag & RMESCAPE_HEAP) {
5905                         r = ckmalloc(fulllen);
5906                 } else {
5907                         r = stalloc(fulllen);
5908                 }
5909                 q = r;
5910                 if (len > 0) {
5911                         q = (char *)memcpy(q, str, len) + len;
5912                 }
5913         }
5914
5915         inquotes = 0;
5916         globbing = flag & RMESCAPE_GLOB;
5917         protect_against_glob = globbing;
5918         while (*p) {
5919                 if ((unsigned char)*p == CTLQUOTEMARK) {
5920 // Note: both inquotes and protect_against_glob only affect whether
5921 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5922                         inquotes = ~inquotes;
5923                         p++;
5924                         protect_against_glob = globbing;
5925                         continue;
5926                 }
5927                 if ((unsigned char)*p == CTLESC) {
5928                         p++;
5929 #if DEBUG
5930                         if (*p == '\0')
5931                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5932 #endif
5933                         if (protect_against_glob) {
5934                                 /*
5935                                  * We used to trust glob() and fnmatch() to eat
5936                                  * superfluous escapes (\z where z has no
5937                                  * special meaning anyway). But this causes
5938                                  * bugs such as string of one greek letter rho
5939                                  * (unicode-encoded as two bytes "cf,81")
5940                                  * getting encoded as "cf,CTLESC,81"
5941                                  * and here, converted to "cf,\,81" -
5942                                  * which does not go well with some flavors
5943                                  * of fnmatch() in unicode locales
5944                                  * (for example, glibc <= 2.22).
5945                                  *
5946                                  * Lets add "\" only on the chars which need it.
5947                                  * Testcases for less obvious chars are shown.
5948                                  */
5949                                 if (*p == '*'
5950                                  || *p == '?'
5951                                  || *p == '['
5952                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5953                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5954                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5955                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5956                                 /* Some libc support [^negate], that's why "^" also needs love */
5957                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5958                                 ) {
5959                                         *q++ = '\\';
5960                                 }
5961                         }
5962                 } else if (*p == '\\' && !inquotes) {
5963                         /* naked back slash */
5964                         protect_against_glob = 0;
5965                         goto copy;
5966                 }
5967 #if BASH_PATTERN_SUBST
5968                 else if (*p == '/' && slash) {
5969                         /* stop handling globbing and mark location of slash */
5970                         globbing = slash = 0;
5971                         *p = CTLESC;
5972                 }
5973 #endif
5974                 protect_against_glob = globbing;
5975  copy:
5976                 *q++ = *p++;
5977         }
5978         *q = '\0';
5979         if (flag & RMESCAPE_GROW) {
5980                 expdest = r;
5981                 STADJUST(q - r + 1, expdest);
5982         }
5983         return r;
5984 }
5985 #define pmatch(a, b) !fnmatch((a), (b), 0)
5986
5987 /*
5988  * Prepare a pattern for a expmeta (internal glob(3)) call.
5989  *
5990  * Returns an stalloced string.
5991  */
5992 static char *
5993 preglob(const char *pattern, int flag)
5994 {
5995         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5996 }
5997
5998 /*
5999  * Put a string on the stack.
6000  */
6001 static void
6002 memtodest(const char *p, size_t len, int syntax, int quotes)
6003 {
6004         char *q;
6005
6006         if (!len)
6007                 return;
6008
6009         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6010
6011         do {
6012                 unsigned char c = *p++;
6013                 if (c) {
6014                         if (quotes & QUOTES_ESC) {
6015                                 int n = SIT(c, syntax);
6016                                 if (n == CCTL
6017                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6018                                      && n == CBACK
6019                                     )
6020                                 ) {
6021                                         USTPUTC(CTLESC, q);
6022                                 }
6023                         }
6024                 } else if (!(quotes & QUOTES_KEEPNUL))
6025                         continue;
6026                 USTPUTC(c, q);
6027         } while (--len);
6028
6029         expdest = q;
6030 }
6031
6032 static size_t
6033 strtodest(const char *p, int syntax, int quotes)
6034 {
6035         size_t len = strlen(p);
6036         memtodest(p, len, syntax, quotes);
6037         return len;
6038 }
6039
6040 /*
6041  * Record the fact that we have to scan this region of the
6042  * string for IFS characters.
6043  */
6044 static void
6045 recordregion(int start, int end, int nulonly)
6046 {
6047         struct ifsregion *ifsp;
6048
6049         if (ifslastp == NULL) {
6050                 ifsp = &ifsfirst;
6051         } else {
6052                 INT_OFF;
6053                 ifsp = ckzalloc(sizeof(*ifsp));
6054                 /*ifsp->next = NULL; - ckzalloc did it */
6055                 ifslastp->next = ifsp;
6056                 INT_ON;
6057         }
6058         ifslastp = ifsp;
6059         ifslastp->begoff = start;
6060         ifslastp->endoff = end;
6061         ifslastp->nulonly = nulonly;
6062 }
6063
6064 static void
6065 removerecordregions(int endoff)
6066 {
6067         if (ifslastp == NULL)
6068                 return;
6069
6070         if (ifsfirst.endoff > endoff) {
6071                 while (ifsfirst.next) {
6072                         struct ifsregion *ifsp;
6073                         INT_OFF;
6074                         ifsp = ifsfirst.next->next;
6075                         free(ifsfirst.next);
6076                         ifsfirst.next = ifsp;
6077                         INT_ON;
6078                 }
6079                 if (ifsfirst.begoff > endoff) {
6080                         ifslastp = NULL;
6081                 } else {
6082                         ifslastp = &ifsfirst;
6083                         ifsfirst.endoff = endoff;
6084                 }
6085                 return;
6086         }
6087
6088         ifslastp = &ifsfirst;
6089         while (ifslastp->next && ifslastp->next->begoff < endoff)
6090                 ifslastp = ifslastp->next;
6091         while (ifslastp->next) {
6092                 struct ifsregion *ifsp;
6093                 INT_OFF;
6094                 ifsp = ifslastp->next->next;
6095                 free(ifslastp->next);
6096                 ifslastp->next = ifsp;
6097                 INT_ON;
6098         }
6099         if (ifslastp->endoff > endoff)
6100                 ifslastp->endoff = endoff;
6101 }
6102
6103 static char *
6104 exptilde(char *startp, char *p, int flags)
6105 {
6106         unsigned char c;
6107         char *name;
6108         struct passwd *pw;
6109         const char *home;
6110         int quotes = flags & QUOTES_ESC;
6111
6112         name = p + 1;
6113
6114         while ((c = *++p) != '\0') {
6115                 switch (c) {
6116                 case CTLESC:
6117                         return startp;
6118                 case CTLQUOTEMARK:
6119                         return startp;
6120                 case ':':
6121                         if (flags & EXP_VARTILDE)
6122                                 goto done;
6123                         break;
6124                 case '/':
6125                 case CTLENDVAR:
6126                         goto done;
6127                 }
6128         }
6129  done:
6130         *p = '\0';
6131         if (*name == '\0') {
6132                 home = lookupvar("HOME");
6133         } else {
6134                 pw = getpwnam(name);
6135                 if (pw == NULL)
6136                         goto lose;
6137                 home = pw->pw_dir;
6138         }
6139         if (!home || !*home)
6140                 goto lose;
6141         *p = c;
6142         strtodest(home, SQSYNTAX, quotes);
6143         return p;
6144  lose:
6145         *p = c;
6146         return startp;
6147 }
6148
6149 /*
6150  * Execute a command inside back quotes.  If it's a builtin command, we
6151  * want to save its output in a block obtained from malloc.  Otherwise
6152  * we fork off a subprocess and get the output of the command via a pipe.
6153  * Should be called with interrupts off.
6154  */
6155 struct backcmd {                /* result of evalbackcmd */
6156         int fd;                 /* file descriptor to read from */
6157         int nleft;              /* number of chars in buffer */
6158         char *buf;              /* buffer */
6159         struct job *jp;         /* job structure for command */
6160 };
6161
6162 /* These forward decls are needed to use "eval" code for backticks handling: */
6163 #define EV_EXIT 01              /* exit after evaluating tree */
6164 static int evaltree(union node *, int);
6165
6166 static void FAST_FUNC
6167 evalbackcmd(union node *n, struct backcmd *result)
6168 {
6169         int pip[2];
6170         struct job *jp;
6171
6172         result->fd = -1;
6173         result->buf = NULL;
6174         result->nleft = 0;
6175         result->jp = NULL;
6176         if (n == NULL) {
6177                 goto out;
6178         }
6179
6180         if (pipe(pip) < 0)
6181                 ash_msg_and_raise_error("pipe call failed");
6182         jp = makejob(/*n,*/ 1);
6183         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6184                 /* child */
6185                 FORCE_INT_ON;
6186                 close(pip[0]);
6187                 if (pip[1] != 1) {
6188                         /*close(1);*/
6189                         dup2_or_raise(pip[1], 1);
6190                         close(pip[1]);
6191                 }
6192 /* TODO: eflag clearing makes the following not abort:
6193  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6194  * which is what bash does (unless it is in POSIX mode).
6195  * dash deleted "eflag = 0" line in the commit
6196  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6197  *  [EVAL] Don't clear eflag in evalbackcmd
6198  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6199  */
6200                 eflag = 0;
6201                 ifsfree();
6202                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6203                 /* NOTREACHED */
6204         }
6205         /* parent */
6206         close(pip[1]);
6207         result->fd = pip[0];
6208         result->jp = jp;
6209
6210  out:
6211         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6212                 result->fd, result->buf, result->nleft, result->jp));
6213 }
6214
6215 /*
6216  * Expand stuff in backwards quotes.
6217  */
6218 static void
6219 expbackq(union node *cmd, int flag)
6220 {
6221         struct backcmd in;
6222         int i;
6223         char buf[128];
6224         char *p;
6225         char *dest;
6226         int startloc;
6227         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6228         struct stackmark smark;
6229
6230         INT_OFF;
6231         startloc = expdest - (char *)stackblock();
6232         pushstackmark(&smark, startloc);
6233         evalbackcmd(cmd, &in);
6234         popstackmark(&smark);
6235
6236         p = in.buf;
6237         i = in.nleft;
6238         if (i == 0)
6239                 goto read;
6240         for (;;) {
6241                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6242  read:
6243                 if (in.fd < 0)
6244                         break;
6245                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6246                 TRACE(("expbackq: read returns %d\n", i));
6247                 if (i <= 0)
6248                         break;
6249                 p = buf;
6250         }
6251
6252         free(in.buf);
6253         if (in.fd >= 0) {
6254                 close(in.fd);
6255                 back_exitstatus = waitforjob(in.jp);
6256         }
6257         INT_ON;
6258
6259         /* Eat all trailing newlines */
6260         dest = expdest;
6261         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6262                 STUNPUTC(dest);
6263         expdest = dest;
6264
6265         if (!(flag & EXP_QUOTED))
6266                 recordregion(startloc, dest - (char *)stackblock(), 0);
6267         TRACE(("evalbackq: size:%d:'%.*s'\n",
6268                 (int)((dest - (char *)stackblock()) - startloc),
6269                 (int)((dest - (char *)stackblock()) - startloc),
6270                 stackblock() + startloc));
6271 }
6272
6273 #if ENABLE_FEATURE_SH_MATH
6274 /*
6275  * Expand arithmetic expression.  Backup to start of expression,
6276  * evaluate, place result in (backed up) result, adjust string position.
6277  */
6278 static void
6279 expari(int flag)
6280 {
6281         char *p, *start;
6282         int begoff;
6283         int len;
6284
6285         /* ifsfree(); */
6286
6287         /*
6288          * This routine is slightly over-complicated for
6289          * efficiency.  Next we scan backwards looking for the
6290          * start of arithmetic.
6291          */
6292         start = stackblock();
6293         p = expdest - 1;
6294         *p = '\0';
6295         p--;
6296         while (1) {
6297                 int esc;
6298
6299                 while ((unsigned char)*p != CTLARI) {
6300                         p--;
6301 #if DEBUG
6302                         if (p < start) {
6303                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6304                         }
6305 #endif
6306                 }
6307
6308                 esc = esclen(start, p);
6309                 if (!(esc % 2)) {
6310                         break;
6311                 }
6312
6313                 p -= esc + 1;
6314         }
6315
6316         begoff = p - start;
6317
6318         removerecordregions(begoff);
6319
6320         expdest = p;
6321
6322         if (flag & QUOTES_ESC)
6323                 rmescapes(p + 1, 0);
6324
6325         len = cvtnum(ash_arith(p + 1));
6326
6327         if (!(flag & EXP_QUOTED))
6328                 recordregion(begoff, begoff + len, 0);
6329 }
6330 #endif
6331
6332 /* argstr needs it */
6333 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6334
6335 /*
6336  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6337  * characters to allow for further processing.  Otherwise treat
6338  * $@ like $* since no splitting will be performed.
6339  *
6340  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6341  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6342  * for correct expansion of "B=$A" word.
6343  */
6344 static void
6345 argstr(char *p, int flags, struct strlist *var_str_list)
6346 {
6347         static const char spclchars[] ALIGN1 = {
6348                 '=',
6349                 ':',
6350                 CTLQUOTEMARK,
6351                 CTLENDVAR,
6352                 CTLESC,
6353                 CTLVAR,
6354                 CTLBACKQ,
6355 #if ENABLE_FEATURE_SH_MATH
6356                 CTLENDARI,
6357 #endif
6358                 '\0'
6359         };
6360         const char *reject = spclchars;
6361         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6362         int inquotes;
6363         size_t length;
6364         int startloc;
6365
6366         if (!(flags & EXP_VARTILDE)) {
6367                 reject += 2;
6368         } else if (flags & EXP_VARTILDE2) {
6369                 reject++;
6370         }
6371         inquotes = 0;
6372         length = 0;
6373         if (flags & EXP_TILDE) {
6374                 char *q;
6375
6376                 flags &= ~EXP_TILDE;
6377  tilde:
6378                 q = p;
6379                 if (*q == '~')
6380                         p = exptilde(p, q, flags);
6381         }
6382  start:
6383         startloc = expdest - (char *)stackblock();
6384         for (;;) {
6385                 unsigned char c;
6386
6387                 length += strcspn(p + length, reject);
6388                 c = p[length];
6389                 if (c) {
6390                         if (!(c & 0x80)
6391                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6392                         ) {
6393                                 /* c == '=' || c == ':' || c == CTLENDARI */
6394                                 length++;
6395                         }
6396                 }
6397                 if (length > 0) {
6398                         int newloc;
6399                         expdest = stack_nputstr(p, length, expdest);
6400                         newloc = expdest - (char *)stackblock();
6401                         if (breakall && !inquotes && newloc > startloc) {
6402                                 recordregion(startloc, newloc, 0);
6403                         }
6404                         startloc = newloc;
6405                 }
6406                 p += length + 1;
6407                 length = 0;
6408
6409                 switch (c) {
6410                 case '\0':
6411                         goto breakloop;
6412                 case '=':
6413                         if (flags & EXP_VARTILDE2) {
6414                                 p--;
6415                                 continue;
6416                         }
6417                         flags |= EXP_VARTILDE2;
6418                         reject++;
6419                         /* fall through */
6420                 case ':':
6421                         /*
6422                          * sort of a hack - expand tildes in variable
6423                          * assignments (after the first '=' and after ':'s).
6424                          */
6425                         if (*--p == '~') {
6426                                 goto tilde;
6427                         }
6428                         continue;
6429                 }
6430
6431                 switch (c) {
6432                 case CTLENDVAR: /* ??? */
6433                         goto breakloop;
6434                 case CTLQUOTEMARK:
6435                         inquotes ^= EXP_QUOTED;
6436                         /* "$@" syntax adherence hack */
6437                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6438                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6439                                 goto start;
6440                         }
6441  addquote:
6442                         if (flags & QUOTES_ESC) {
6443                                 p--;
6444                                 length++;
6445                                 startloc++;
6446                         }
6447                         break;
6448                 case CTLESC:
6449                         startloc++;
6450                         length++;
6451
6452                         /*
6453                          * Quoted parameter expansion pattern: remove quote
6454                          * unless inside inner quotes or we have a literal
6455                          * backslash.
6456                          */
6457                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6458                             EXP_QPAT && *p != '\\')
6459                                 break;
6460
6461                         goto addquote;
6462                 case CTLVAR:
6463                         TRACE(("argstr: evalvar('%s')\n", p));
6464                         p = evalvar(p, flags | inquotes, var_str_list);
6465                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6466                         goto start;
6467                 case CTLBACKQ:
6468                         expbackq(argbackq->n, flags | inquotes);
6469                         argbackq = argbackq->next;
6470                         goto start;
6471 #if ENABLE_FEATURE_SH_MATH
6472                 case CTLENDARI:
6473                         p--;
6474                         expari(flags | inquotes);
6475                         goto start;
6476 #endif
6477                 }
6478         }
6479  breakloop: ;
6480 }
6481
6482 static char *
6483 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6484                 char *pattern, int quotes, int zero)
6485 {
6486         char *loc, *loc2;
6487         char c;
6488
6489         loc = startp;
6490         loc2 = rmesc;
6491         do {
6492                 int match;
6493                 const char *s = loc2;
6494
6495                 c = *loc2;
6496                 if (zero) {
6497                         *loc2 = '\0';
6498                         s = rmesc;
6499                 }
6500                 match = pmatch(pattern, s);
6501
6502                 *loc2 = c;
6503                 if (match)
6504                         return loc;
6505                 if (quotes && (unsigned char)*loc == CTLESC)
6506                         loc++;
6507                 loc++;
6508                 loc2++;
6509         } while (c);
6510         return NULL;
6511 }
6512
6513 static char *
6514 scanright(char *startp, char *rmesc, char *rmescend,
6515                 char *pattern, int quotes, int match_at_start)
6516 {
6517 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6518         int try2optimize = match_at_start;
6519 #endif
6520         int esc = 0;
6521         char *loc;
6522         char *loc2;
6523
6524         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6525          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6526          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6527          * Logic:
6528          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6529          * and on each iteration they go back two/one char until they reach the beginning.
6530          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6531          */
6532         /* TODO: document in what other circumstances we are called. */
6533
6534         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6535                 int match;
6536                 char c = *loc2;
6537                 const char *s = loc2;
6538                 if (match_at_start) {
6539                         *loc2 = '\0';
6540                         s = rmesc;
6541                 }
6542                 match = pmatch(pattern, s);
6543                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6544                 *loc2 = c;
6545                 if (match)
6546                         return loc;
6547 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6548                 if (try2optimize) {
6549                         /* Maybe we can optimize this:
6550                          * if pattern ends with unescaped *, we can avoid checking
6551                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6552                          * it won't match truncated "raw_value_of_" strings too.
6553                          */
6554                         unsigned plen = strlen(pattern);
6555                         /* Does it end with "*"? */
6556                         if (plen != 0 && pattern[--plen] == '*') {
6557                                 /* "xxxx*" is not escaped */
6558                                 /* "xxx\*" is escaped */
6559                                 /* "xx\\*" is not escaped */
6560                                 /* "x\\\*" is escaped */
6561                                 int slashes = 0;
6562                                 while (plen != 0 && pattern[--plen] == '\\')
6563                                         slashes++;
6564                                 if (!(slashes & 1))
6565                                         break; /* ends with unescaped "*" */
6566                         }
6567                         try2optimize = 0;
6568                 }
6569 #endif
6570                 loc--;
6571                 if (quotes) {
6572                         if (--esc < 0) {
6573                                 esc = esclen(startp, loc);
6574                         }
6575                         if (esc % 2) {
6576                                 esc--;
6577                                 loc--;
6578                         }
6579                 }
6580         }
6581         return NULL;
6582 }
6583
6584 static void varunset(const char *, const char *, const char *, int) NORETURN;
6585 static void
6586 varunset(const char *end, const char *var, const char *umsg, int varflags)
6587 {
6588         const char *msg;
6589         const char *tail;
6590
6591         tail = nullstr;
6592         msg = "parameter not set";
6593         if (umsg) {
6594                 if ((unsigned char)*end == CTLENDVAR) {
6595                         if (varflags & VSNUL)
6596                                 tail = " or null";
6597                 } else {
6598                         msg = umsg;
6599                 }
6600         }
6601         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6602 }
6603
6604 static const char *
6605 subevalvar(char *p, char *varname, int strloc, int subtype,
6606                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6607 {
6608         struct nodelist *saveargbackq = argbackq;
6609         int quotes = flag & QUOTES_ESC;
6610         char *startp;
6611         char *loc;
6612         char *rmesc, *rmescend;
6613         char *str;
6614         int amount, resetloc;
6615         IF_BASH_PATTERN_SUBST(int workloc;)
6616         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6617         int zero;
6618         char *(*scan)(char*, char*, char*, char*, int, int);
6619
6620         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6621         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6622
6623         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6624                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6625                         var_str_list);
6626         STPUTC('\0', expdest);
6627         argbackq = saveargbackq;
6628         startp = (char *)stackblock() + startloc;
6629
6630         switch (subtype) {
6631         case VSASSIGN:
6632                 setvar0(varname, startp);
6633                 amount = startp - expdest;
6634                 STADJUST(amount, expdest);
6635                 return startp;
6636
6637         case VSQUESTION:
6638                 varunset(p, varname, startp, varflags);
6639                 /* NOTREACHED */
6640
6641 #if BASH_SUBSTR
6642         case VSSUBSTR: {
6643                 int pos, len, orig_len;
6644                 char *colon;
6645
6646                 loc = str = stackblock() + strloc;
6647
6648 # if !ENABLE_FEATURE_SH_MATH
6649 #  define ash_arith number
6650 # endif
6651                 /* Read POS in ${var:POS:LEN} */
6652                 colon = strchr(loc, ':');
6653                 if (colon) *colon = '\0';
6654                 pos = ash_arith(loc);
6655                 if (colon) *colon = ':';
6656
6657                 /* Read LEN in ${var:POS:LEN} */
6658                 len = str - startp - 1;
6659                 /* *loc != '\0', guaranteed by parser */
6660                 if (quotes) {
6661                         char *ptr;
6662
6663                         /* Adjust the length by the number of escapes */
6664                         for (ptr = startp; ptr < (str - 1); ptr++) {
6665                                 if ((unsigned char)*ptr == CTLESC) {
6666                                         len--;
6667                                         ptr++;
6668                                 }
6669                         }
6670                 }
6671                 orig_len = len;
6672                 if (*loc++ == ':') {
6673                         /* ${var::LEN} */
6674                         len = ash_arith(loc);
6675                 } else {
6676                         /* Skip POS in ${var:POS:LEN} */
6677                         len = orig_len;
6678                         while (*loc && *loc != ':') {
6679                                 loc++;
6680                         }
6681                         if (*loc++ == ':') {
6682                                 len = ash_arith(loc);
6683                         }
6684                 }
6685 #  undef ash_arith
6686
6687                 if (pos < 0) {
6688                         /* ${VAR:$((-n)):l} starts n chars from the end */
6689                         pos = orig_len + pos;
6690                 }
6691                 if ((unsigned)pos >= orig_len) {
6692                         /* apart from obvious ${VAR:999999:l},
6693                          * covers ${VAR:$((-9999999)):l} - result is ""
6694                          * (bash compat)
6695                          */
6696                         pos = 0;
6697                         len = 0;
6698                 }
6699                 if (len < 0) {
6700                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6701                         len = (orig_len - pos) + len;
6702                 }
6703                 if ((unsigned)len > (orig_len - pos))
6704                         len = orig_len - pos;
6705
6706                 for (str = startp; pos; str++, pos--) {
6707                         if (quotes && (unsigned char)*str == CTLESC)
6708                                 str++;
6709                 }
6710                 for (loc = startp; len; len--) {
6711                         if (quotes && (unsigned char)*str == CTLESC)
6712                                 *loc++ = *str++;
6713                         *loc++ = *str++;
6714                 }
6715                 *loc = '\0';
6716                 amount = loc - expdest;
6717                 STADJUST(amount, expdest);
6718                 return loc;
6719         }
6720 #endif /* BASH_SUBSTR */
6721         }
6722
6723         resetloc = expdest - (char *)stackblock();
6724
6725 #if BASH_PATTERN_SUBST
6726         /* We'll comeback here if we grow the stack while handling
6727          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6728          * stack will need rebasing, and we'll need to remove our work
6729          * areas each time
6730          */
6731  restart:
6732 #endif
6733
6734         amount = expdest - ((char *)stackblock() + resetloc);
6735         STADJUST(-amount, expdest);
6736         startp = (char *)stackblock() + startloc;
6737
6738         rmesc = startp;
6739         rmescend = (char *)stackblock() + strloc;
6740         if (quotes) {
6741                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6742                 if (rmesc != startp) {
6743                         rmescend = expdest;
6744                         startp = (char *)stackblock() + startloc;
6745                 }
6746         }
6747         rmescend--;
6748         str = (char *)stackblock() + strloc;
6749         /*
6750          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6751          * The result is a_\_z_c (not a\_\_z_c)!
6752          *
6753          * The search pattern and replace string treat backslashes differently!
6754          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6755          * and string.  It's only used on the first call.
6756          */
6757         preglob(str, IF_BASH_PATTERN_SUBST(
6758                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6759                         RMESCAPE_SLASH : ) 0);
6760
6761 #if BASH_PATTERN_SUBST
6762         workloc = expdest - (char *)stackblock();
6763         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6764                 int len;
6765                 char *idx, *end;
6766
6767                 if (!repl) {
6768                         repl = strchr(str, CTLESC);
6769                         if (repl)
6770                                 *repl++ = '\0';
6771                         else
6772                                 repl = nullstr;
6773                 }
6774                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6775
6776                 /* If there's no pattern to match, return the expansion unmolested */
6777                 if (str[0] == '\0')
6778                         return NULL;
6779
6780                 len = 0;
6781                 idx = startp;
6782                 end = str - 1;
6783                 while (idx < end) {
6784  try_to_match:
6785                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6786                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6787                         if (!loc) {
6788                                 /* No match, advance */
6789                                 char *restart_detect = stackblock();
6790  skip_matching:
6791                                 STPUTC(*idx, expdest);
6792                                 if (quotes && (unsigned char)*idx == CTLESC) {
6793                                         idx++;
6794                                         len++;
6795                                         STPUTC(*idx, expdest);
6796                                 }
6797                                 if (stackblock() != restart_detect)
6798                                         goto restart;
6799                                 idx++;
6800                                 len++;
6801                                 rmesc++;
6802                                 /* continue; - prone to quadratic behavior, smarter code: */
6803                                 if (idx >= end)
6804                                         break;
6805                                 if (str[0] == '*') {
6806                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6807                                          * it would never match "ong_string" etc, no point in trying.
6808                                          */
6809                                         goto skip_matching;
6810                                 }
6811                                 goto try_to_match;
6812                         }
6813
6814                         if (subtype == VSREPLACEALL) {
6815                                 while (idx < loc) {
6816                                         if (quotes && (unsigned char)*idx == CTLESC)
6817                                                 idx++;
6818                                         idx++;
6819                                         rmesc++;
6820                                 }
6821                         } else {
6822                                 idx = loc;
6823                         }
6824
6825                         //bb_error_msg("repl:'%s'", repl);
6826                         for (loc = (char*)repl; *loc; loc++) {
6827                                 char *restart_detect = stackblock();
6828                                 if (quotes && *loc == '\\') {
6829                                         STPUTC(CTLESC, expdest);
6830                                         len++;
6831                                 }
6832                                 STPUTC(*loc, expdest);
6833                                 if (stackblock() != restart_detect)
6834                                         goto restart;
6835                                 len++;
6836                         }
6837
6838                         if (subtype == VSREPLACE) {
6839                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6840                                 while (*idx) {
6841                                         char *restart_detect = stackblock();
6842                                         STPUTC(*idx, expdest);
6843                                         if (stackblock() != restart_detect)
6844                                                 goto restart;
6845                                         len++;
6846                                         idx++;
6847                                 }
6848                                 break;
6849                         }
6850                 }
6851
6852                 /* We've put the replaced text into a buffer at workloc, now
6853                  * move it to the right place and adjust the stack.
6854                  */
6855                 STPUTC('\0', expdest);
6856                 startp = (char *)stackblock() + startloc;
6857                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6858                 //bb_error_msg("startp:'%s'", startp);
6859                 amount = expdest - (startp + len);
6860                 STADJUST(-amount, expdest);
6861                 return startp;
6862         }
6863 #endif /* BASH_PATTERN_SUBST */
6864
6865         subtype -= VSTRIMRIGHT;
6866 #if DEBUG
6867         if (subtype < 0 || subtype > 7)
6868                 abort();
6869 #endif
6870         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6871         zero = subtype >> 1;
6872         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6873         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6874
6875         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6876         if (loc) {
6877                 if (zero) {
6878                         memmove(startp, loc, str - loc);
6879                         loc = startp + (str - loc) - 1;
6880                 }
6881                 *loc = '\0';
6882                 amount = loc - expdest;
6883                 STADJUST(amount, expdest);
6884         }
6885         return loc;
6886 }
6887
6888 /*
6889  * Add the value of a specialized variable to the stack string.
6890  * name parameter (examples):
6891  * ash -c 'echo $1'      name:'1='
6892  * ash -c 'echo $qwe'    name:'qwe='
6893  * ash -c 'echo $$'      name:'$='
6894  * ash -c 'echo ${$}'    name:'$='
6895  * ash -c 'echo ${$##q}' name:'$=q'
6896  * ash -c 'echo ${#$}'   name:'$='
6897  * note: examples with bad shell syntax:
6898  * ash -c 'echo ${#$1}'  name:'$=1'
6899  * ash -c 'echo ${#1#}'  name:'1=#'
6900  */
6901 static NOINLINE ssize_t
6902 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6903 {
6904         const char *p;
6905         int num;
6906         int i;
6907         ssize_t len = 0;
6908         int sep;
6909         int quoted = *quotedp;
6910         int subtype = varflags & VSTYPE;
6911         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6912         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6913         int syntax;
6914
6915         sep = (flags & EXP_FULL) << CHAR_BIT;
6916         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6917
6918         switch (*name) {
6919         case '$':
6920                 num = rootpid;
6921                 goto numvar;
6922         case '?':
6923                 num = exitstatus;
6924                 goto numvar;
6925         case '#':
6926                 num = shellparam.nparam;
6927                 goto numvar;
6928         case '!':
6929                 num = backgndpid;
6930                 if (num == 0)
6931                         return -1;
6932  numvar:
6933                 len = cvtnum(num);
6934                 goto check_1char_name;
6935         case '-':
6936                 expdest = makestrspace(NOPTS, expdest);
6937                 for (i = NOPTS - 1; i >= 0; i--) {
6938                         if (optlist[i]) {
6939                                 USTPUTC(optletters(i), expdest);
6940                                 len++;
6941                         }
6942                 }
6943  check_1char_name:
6944 #if 0
6945                 /* handles cases similar to ${#$1} */
6946                 if (name[2] != '\0')
6947                         raise_error_syntax("bad substitution");
6948 #endif
6949                 break;
6950         case '@':
6951                 if (quoted && sep)
6952                         goto param;
6953                 /* fall through */
6954         case '*': {
6955                 char **ap;
6956                 char sepc;
6957
6958                 if (quoted)
6959                         sep = 0;
6960                 sep |= ifsset() ? ifsval()[0] : ' ';
6961  param:
6962                 sepc = sep;
6963                 *quotedp = !sepc;
6964                 ap = shellparam.p;
6965                 if (!ap)
6966                         return -1;
6967                 while ((p = *ap++) != NULL) {
6968                         len += strtodest(p, syntax, quotes);
6969
6970                         if (*ap && sep) {
6971                                 len++;
6972                                 memtodest(&sepc, 1, syntax, quotes);
6973                         }
6974                 }
6975                 break;
6976         } /* case '*' */
6977         case '0':
6978         case '1':
6979         case '2':
6980         case '3':
6981         case '4':
6982         case '5':
6983         case '6':
6984         case '7':
6985         case '8':
6986         case '9':
6987                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6988                 if (num < 0 || num > shellparam.nparam)
6989                         return -1;
6990                 p = num ? shellparam.p[num - 1] : arg0;
6991                 goto value;
6992         default:
6993                 /* NB: name has form "VAR=..." */
6994
6995                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6996                  * which should be considered before we check variables. */
6997                 if (var_str_list) {
6998                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6999                         p = NULL;
7000                         do {
7001                                 char *str, *eq;
7002                                 str = var_str_list->text;
7003                                 eq = strchr(str, '=');
7004                                 if (!eq) /* stop at first non-assignment */
7005                                         break;
7006                                 eq++;
7007                                 if (name_len == (unsigned)(eq - str)
7008                                  && strncmp(str, name, name_len) == 0
7009                                 ) {
7010                                         p = eq;
7011                                         /* goto value; - WRONG! */
7012                                         /* think "A=1 A=2 B=$A" */
7013                                 }
7014                                 var_str_list = var_str_list->next;
7015                         } while (var_str_list);
7016                         if (p)
7017                                 goto value;
7018                 }
7019                 p = lookupvar(name);
7020  value:
7021                 if (!p)
7022                         return -1;
7023
7024                 len = strtodest(p, syntax, quotes);
7025 #if ENABLE_UNICODE_SUPPORT
7026                 if (subtype == VSLENGTH && len > 0) {
7027                         reinit_unicode_for_ash();
7028                         if (unicode_status == UNICODE_ON) {
7029                                 STADJUST(-len, expdest);
7030                                 discard = 0;
7031                                 len = unicode_strlen(p);
7032                         }
7033                 }
7034 #endif
7035                 break;
7036         }
7037
7038         if (discard)
7039                 STADJUST(-len, expdest);
7040         return len;
7041 }
7042
7043 /*
7044  * Expand a variable, and return a pointer to the next character in the
7045  * input string.
7046  */
7047 static char *
7048 evalvar(char *p, int flag, struct strlist *var_str_list)
7049 {
7050         char varflags;
7051         char subtype;
7052         int quoted;
7053         char easy;
7054         char *var;
7055         int patloc;
7056         int startloc;
7057         ssize_t varlen;
7058
7059         varflags = (unsigned char) *p++;
7060         subtype = varflags & VSTYPE;
7061
7062         if (!subtype)
7063                 raise_error_syntax("bad substitution");
7064
7065         quoted = flag & EXP_QUOTED;
7066         var = p;
7067         easy = (!quoted || (*var == '@' && shellparam.nparam));
7068         startloc = expdest - (char *)stackblock();
7069         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7070
7071  again:
7072         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7073         if (varflags & VSNUL)
7074                 varlen--;
7075
7076         if (subtype == VSPLUS) {
7077                 varlen = -1 - varlen;
7078                 goto vsplus;
7079         }
7080
7081         if (subtype == VSMINUS) {
7082  vsplus:
7083                 if (varlen < 0) {
7084                         argstr(
7085                                 p,
7086                                 flag | EXP_TILDE | EXP_WORD,
7087                                 var_str_list
7088                         );
7089                         goto end;
7090                 }
7091                 goto record;
7092         }
7093
7094         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7095                 if (varlen >= 0)
7096                         goto record;
7097
7098                 subevalvar(p, var, 0, subtype, startloc, varflags,
7099                            flag & ~QUOTES_ESC, var_str_list);
7100                 varflags &= ~VSNUL;
7101                 /*
7102                  * Remove any recorded regions beyond
7103                  * start of variable
7104                  */
7105                 removerecordregions(startloc);
7106                 goto again;
7107         }
7108
7109         if (varlen < 0 && uflag)
7110                 varunset(p, var, 0, 0);
7111
7112         if (subtype == VSLENGTH) {
7113                 cvtnum(varlen > 0 ? varlen : 0);
7114                 goto record;
7115         }
7116
7117         if (subtype == VSNORMAL) {
7118  record:
7119                 if (!easy)
7120                         goto end;
7121                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7122                 goto end;
7123         }
7124
7125 #if DEBUG
7126         switch (subtype) {
7127         case VSTRIMLEFT:
7128         case VSTRIMLEFTMAX:
7129         case VSTRIMRIGHT:
7130         case VSTRIMRIGHTMAX:
7131 #if BASH_SUBSTR
7132         case VSSUBSTR:
7133 #endif
7134 #if BASH_PATTERN_SUBST
7135         case VSREPLACE:
7136         case VSREPLACEALL:
7137 #endif
7138                 break;
7139         default:
7140                 abort();
7141         }
7142 #endif
7143
7144         if (varlen >= 0) {
7145                 /*
7146                  * Terminate the string and start recording the pattern
7147                  * right after it
7148                  */
7149                 STPUTC('\0', expdest);
7150                 patloc = expdest - (char *)stackblock();
7151                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7152                                 startloc, varflags, flag, var_str_list)) {
7153                         int amount = expdest - (
7154                                 (char *)stackblock() + patloc - 1
7155                         );
7156                         STADJUST(-amount, expdest);
7157                 }
7158                 /* Remove any recorded regions beyond start of variable */
7159                 removerecordregions(startloc);
7160                 goto record;
7161         }
7162
7163  end:
7164         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7165                 int nesting = 1;
7166                 for (;;) {
7167                         unsigned char c = *p++;
7168                         if (c == CTLESC)
7169                                 p++;
7170                         else if (c == CTLBACKQ) {
7171                                 if (varlen >= 0)
7172                                         argbackq = argbackq->next;
7173                         } else if (c == CTLVAR) {
7174                                 if ((*p++ & VSTYPE) != VSNORMAL)
7175                                         nesting++;
7176                         } else if (c == CTLENDVAR) {
7177                                 if (--nesting == 0)
7178                                         break;
7179                         }
7180                 }
7181         }
7182         return p;
7183 }
7184
7185 /*
7186  * Add a file name to the list.
7187  */
7188 static void
7189 addfname(const char *name)
7190 {
7191         struct strlist *sp;
7192
7193         sp = stzalloc(sizeof(*sp));
7194         sp->text = sstrdup(name);
7195         *exparg.lastp = sp;
7196         exparg.lastp = &sp->next;
7197 }
7198
7199 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7200 static int
7201 hasmeta(const char *p)
7202 {
7203         static const char chars[] ALIGN1 = {
7204                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7205         };
7206
7207         for (;;) {
7208                 p = strpbrk(p, chars);
7209                 if (!p)
7210                         break;
7211                 switch ((unsigned char) *p) {
7212                 case CTLQUOTEMARK:
7213                         for (;;) {
7214                                 p++;
7215                                 if (*p == CTLQUOTEMARK)
7216                                         break;
7217                                 if (*p == CTLESC)
7218                                         p++;
7219                                 if (*p == '\0') /* huh? */
7220                                         return 0;
7221                         }
7222                         break;
7223                 case '\\':
7224                 case CTLESC:
7225                         p++;
7226                         if (*p == '\0')
7227                                 return 0;
7228                         break;
7229                 case '[':
7230                         if (!strchr(p + 1, ']')) {
7231                                 /* It's not a properly closed [] pattern,
7232                                  * but other metas may follow. Continue checking.
7233                                  * my[file* _is_ globbed by bash
7234                                  * and matches filenames like "my[file1".
7235                                  */
7236                                 break;
7237                         }
7238                         /* fallthrough */
7239                 default:
7240                 /* case '*': */
7241                 /* case '?': */
7242                         return 1;
7243                 }
7244                 p++;
7245         }
7246
7247         return 0;
7248 }
7249
7250 /* If we want to use glob() from libc... */
7251 #if !ENABLE_ASH_INTERNAL_GLOB
7252
7253 /* Add the result of glob() to the list */
7254 static void
7255 addglob(const glob_t *pglob)
7256 {
7257         char **p = pglob->gl_pathv;
7258
7259         do {
7260                 addfname(*p);
7261         } while (*++p);
7262 }
7263 static void
7264 expandmeta(struct strlist *str /*, int flag*/)
7265 {
7266         /* TODO - EXP_REDIR */
7267
7268         while (str) {
7269                 char *p;
7270                 glob_t pglob;
7271                 int i;
7272
7273                 if (fflag)
7274                         goto nometa;
7275
7276                 if (!hasmeta(str->text))
7277                         goto nometa;
7278
7279                 INT_OFF;
7280                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7281 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7282 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7283 //
7284 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7285 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7286 // Which means you need to unescape the string, right? Not so fast:
7287 // if there _is_ a file named "file\?" (with backslash), it is returned
7288 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7289 // You DON'T KNOW by looking at the result whether you need to unescape it.
7290 //
7291 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7292 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7293 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7294 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7295 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7296 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7297                 i = glob(p, 0, NULL, &pglob);
7298                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7299                 if (p != str->text)
7300                         free(p);
7301                 switch (i) {
7302                 case 0:
7303 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7304                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7305                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7306                                 goto nometa2;
7307 #endif
7308                         addglob(&pglob);
7309                         globfree(&pglob);
7310                         INT_ON;
7311                         break;
7312                 case GLOB_NOMATCH:
7313  //nometa2:
7314                         globfree(&pglob);
7315                         INT_ON;
7316  nometa:
7317                         *exparg.lastp = str;
7318                         rmescapes(str->text, 0);
7319                         exparg.lastp = &str->next;
7320                         break;
7321                 default:        /* GLOB_NOSPACE */
7322                         globfree(&pglob);
7323                         INT_ON;
7324                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7325                 }
7326                 str = str->next;
7327         }
7328 }
7329
7330 #else
7331 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7332
7333 /*
7334  * Do metacharacter (i.e. *, ?, [...]) expansion.
7335  */
7336 static void
7337 expmeta(char *expdir, char *enddir, char *name)
7338 {
7339         char *p;
7340         const char *cp;
7341         char *start;
7342         char *endname;
7343         int metaflag;
7344         struct stat statb;
7345         DIR *dirp;
7346         struct dirent *dp;
7347         int atend;
7348         int matchdot;
7349         int esc;
7350
7351         metaflag = 0;
7352         start = name;
7353         for (p = name; esc = 0, *p; p += esc + 1) {
7354                 if (*p == '*' || *p == '?')
7355                         metaflag = 1;
7356                 else if (*p == '[') {
7357                         char *q = p + 1;
7358                         if (*q == '!')
7359                                 q++;
7360                         for (;;) {
7361                                 if (*q == '\\')
7362                                         q++;
7363                                 if (*q == '/' || *q == '\0')
7364                                         break;
7365                                 if (*++q == ']') {
7366                                         metaflag = 1;
7367                                         break;
7368                                 }
7369                         }
7370                 } else {
7371                         if (*p == '\\')
7372                                 esc++;
7373                         if (p[esc] == '/') {
7374                                 if (metaflag)
7375                                         break;
7376                                 start = p + esc + 1;
7377                         }
7378                 }
7379         }
7380         if (metaflag == 0) {    /* we've reached the end of the file name */
7381                 if (enddir != expdir)
7382                         metaflag++;
7383                 p = name;
7384                 do {
7385                         if (*p == '\\')
7386                                 p++;
7387                         *enddir++ = *p;
7388                 } while (*p++);
7389                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7390                         addfname(expdir);
7391                 return;
7392         }
7393         endname = p;
7394         if (name < start) {
7395                 p = name;
7396                 do {
7397                         if (*p == '\\')
7398                                 p++;
7399                         *enddir++ = *p++;
7400                 } while (p < start);
7401         }
7402         if (enddir == expdir) {
7403                 cp = ".";
7404         } else if (enddir == expdir + 1 && *expdir == '/') {
7405                 cp = "/";
7406         } else {
7407                 cp = expdir;
7408                 enddir[-1] = '\0';
7409         }
7410         dirp = opendir(cp);
7411         if (dirp == NULL)
7412                 return;
7413         if (enddir != expdir)
7414                 enddir[-1] = '/';
7415         if (*endname == 0) {
7416                 atend = 1;
7417         } else {
7418                 atend = 0;
7419                 *endname = '\0';
7420                 endname += esc + 1;
7421         }
7422         matchdot = 0;
7423         p = start;
7424         if (*p == '\\')
7425                 p++;
7426         if (*p == '.')
7427                 matchdot++;
7428         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7429                 if (dp->d_name[0] == '.' && !matchdot)
7430                         continue;
7431                 if (pmatch(start, dp->d_name)) {
7432                         if (atend) {
7433                                 strcpy(enddir, dp->d_name);
7434                                 addfname(expdir);
7435                         } else {
7436                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7437                                         continue;
7438                                 p[-1] = '/';
7439                                 expmeta(expdir, p, endname);
7440                         }
7441                 }
7442         }
7443         closedir(dirp);
7444         if (!atend)
7445                 endname[-esc - 1] = esc ? '\\' : '/';
7446 }
7447
7448 static struct strlist *
7449 msort(struct strlist *list, int len)
7450 {
7451         struct strlist *p, *q = NULL;
7452         struct strlist **lpp;
7453         int half;
7454         int n;
7455
7456         if (len <= 1)
7457                 return list;
7458         half = len >> 1;
7459         p = list;
7460         for (n = half; --n >= 0;) {
7461                 q = p;
7462                 p = p->next;
7463         }
7464         q->next = NULL;                 /* terminate first half of list */
7465         q = msort(list, half);          /* sort first half of list */
7466         p = msort(p, len - half);               /* sort second half */
7467         lpp = &list;
7468         for (;;) {
7469 #if ENABLE_LOCALE_SUPPORT
7470                 if (strcoll(p->text, q->text) < 0)
7471 #else
7472                 if (strcmp(p->text, q->text) < 0)
7473 #endif
7474                                                 {
7475                         *lpp = p;
7476                         lpp = &p->next;
7477                         p = *lpp;
7478                         if (p == NULL) {
7479                                 *lpp = q;
7480                                 break;
7481                         }
7482                 } else {
7483                         *lpp = q;
7484                         lpp = &q->next;
7485                         q = *lpp;
7486                         if (q == NULL) {
7487                                 *lpp = p;
7488                                 break;
7489                         }
7490                 }
7491         }
7492         return list;
7493 }
7494
7495 /*
7496  * Sort the results of file name expansion.  It calculates the number of
7497  * strings to sort and then calls msort (short for merge sort) to do the
7498  * work.
7499  */
7500 static struct strlist *
7501 expsort(struct strlist *str)
7502 {
7503         int len;
7504         struct strlist *sp;
7505
7506         len = 0;
7507         for (sp = str; sp; sp = sp->next)
7508                 len++;
7509         return msort(str, len);
7510 }
7511
7512 static void
7513 expandmeta(struct strlist *str /*, int flag*/)
7514 {
7515         /* TODO - EXP_REDIR */
7516
7517         while (str) {
7518                 char *expdir;
7519                 struct strlist **savelastp;
7520                 struct strlist *sp;
7521                 char *p;
7522
7523                 if (fflag)
7524                         goto nometa;
7525                 if (!hasmeta(str->text))
7526                         goto nometa;
7527                 savelastp = exparg.lastp;
7528
7529                 INT_OFF;
7530                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7531                 {
7532                         int i = strlen(str->text);
7533 //BUGGY estimation of how long expanded name can be
7534                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7535                 }
7536                 expmeta(expdir, expdir, p);
7537                 free(expdir);
7538                 if (p != str->text)
7539                         free(p);
7540                 INT_ON;
7541                 if (exparg.lastp == savelastp) {
7542                         /*
7543                          * no matches
7544                          */
7545  nometa:
7546                         *exparg.lastp = str;
7547                         rmescapes(str->text, 0);
7548                         exparg.lastp = &str->next;
7549                 } else {
7550                         *exparg.lastp = NULL;
7551                         *savelastp = sp = expsort(*savelastp);
7552                         while (sp->next != NULL)
7553                                 sp = sp->next;
7554                         exparg.lastp = &sp->next;
7555                 }
7556                 str = str->next;
7557         }
7558 }
7559 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7560
7561 /*
7562  * Perform variable substitution and command substitution on an argument,
7563  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7564  * perform splitting and file name expansion.  When arglist is NULL, perform
7565  * here document expansion.
7566  */
7567 static void
7568 expandarg(union node *arg, struct arglist *arglist, int flag)
7569 {
7570         struct strlist *sp;
7571         char *p;
7572
7573         argbackq = arg->narg.backquote;
7574         STARTSTACKSTR(expdest);
7575         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7576         argstr(arg->narg.text, flag,
7577                         /* var_str_list: */ arglist ? arglist->list : NULL);
7578         p = _STPUTC('\0', expdest);
7579         expdest = p - 1;
7580         if (arglist == NULL) {
7581                 /* here document expanded */
7582                 goto out;
7583         }
7584         p = grabstackstr(p);
7585         TRACE(("expandarg: p:'%s'\n", p));
7586         exparg.lastp = &exparg.list;
7587         /*
7588          * TODO - EXP_REDIR
7589          */
7590         if (flag & EXP_FULL) {
7591                 ifsbreakup(p, &exparg);
7592                 *exparg.lastp = NULL;
7593                 exparg.lastp = &exparg.list;
7594                 expandmeta(exparg.list /*, flag*/);
7595         } else {
7596                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7597                         rmescapes(p, 0);
7598                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7599                 }
7600                 sp = stzalloc(sizeof(*sp));
7601                 sp->text = p;
7602                 *exparg.lastp = sp;
7603                 exparg.lastp = &sp->next;
7604         }
7605         *exparg.lastp = NULL;
7606         if (exparg.list) {
7607                 *arglist->lastp = exparg.list;
7608                 arglist->lastp = exparg.lastp;
7609         }
7610
7611  out:
7612         ifsfree();
7613 }
7614
7615 /*
7616  * Expand shell variables and backquotes inside a here document.
7617  */
7618 static void
7619 expandhere(union node *arg, int fd)
7620 {
7621         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7622         full_write(fd, stackblock(), expdest - (char *)stackblock());
7623 }
7624
7625 /*
7626  * Returns true if the pattern matches the string.
7627  */
7628 static int
7629 patmatch(char *pattern, const char *string)
7630 {
7631         char *p = preglob(pattern, 0);
7632         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7633         return pmatch(p, string);
7634 }
7635
7636 /*
7637  * See if a pattern matches in a case statement.
7638  */
7639 static int
7640 casematch(union node *pattern, char *val)
7641 {
7642         struct stackmark smark;
7643         int result;
7644
7645         setstackmark(&smark);
7646         argbackq = pattern->narg.backquote;
7647         STARTSTACKSTR(expdest);
7648         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7649                         /* var_str_list: */ NULL);
7650         STACKSTRNUL(expdest);
7651         ifsfree();
7652         result = patmatch(stackblock(), val);
7653         popstackmark(&smark);
7654         return result;
7655 }
7656
7657
7658 /* ============ find_command */
7659
7660 struct builtincmd {
7661         const char *name;
7662         int (*builtin)(int, char **) FAST_FUNC;
7663         /* unsigned flags; */
7664 };
7665 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7666 /* "regular" builtins always take precedence over commands,
7667  * regardless of PATH=....%builtin... position */
7668 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7669 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7670
7671 struct cmdentry {
7672         smallint cmdtype;       /* CMDxxx */
7673         union param {
7674                 int index;
7675                 /* index >= 0 for commands without path (slashes) */
7676                 /* (TODO: what exactly does the value mean? PATH position?) */
7677                 /* index == -1 for commands with slashes */
7678                 /* index == (-2 - applet_no) for NOFORK applets */
7679                 const struct builtincmd *cmd;
7680                 struct funcnode *func;
7681         } u;
7682 };
7683 /* values of cmdtype */
7684 #define CMDUNKNOWN      -1      /* no entry in table for command */
7685 #define CMDNORMAL       0       /* command is an executable program */
7686 #define CMDFUNCTION     1       /* command is a shell function */
7687 #define CMDBUILTIN      2       /* command is a shell builtin */
7688
7689 /* action to find_command() */
7690 #define DO_ERR          0x01    /* prints errors */
7691 #define DO_ABS          0x02    /* checks absolute paths */
7692 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7693 #define DO_ALTPATH      0x08    /* using alternate path */
7694 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7695
7696 static void find_command(char *, struct cmdentry *, int, const char *);
7697
7698
7699 /* ============ Hashing commands */
7700
7701 /*
7702  * When commands are first encountered, they are entered in a hash table.
7703  * This ensures that a full path search will not have to be done for them
7704  * on each invocation.
7705  *
7706  * We should investigate converting to a linear search, even though that
7707  * would make the command name "hash" a misnomer.
7708  */
7709
7710 struct tblentry {
7711         struct tblentry *next;  /* next entry in hash chain */
7712         union param param;      /* definition of builtin function */
7713         smallint cmdtype;       /* CMDxxx */
7714         char rehash;            /* if set, cd done since entry created */
7715         char cmdname[1];        /* name of command */
7716 };
7717
7718 static struct tblentry **cmdtable;
7719 #define INIT_G_cmdtable() do { \
7720         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7721 } while (0)
7722
7723 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7724
7725
7726 static void
7727 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7728 {
7729 #if ENABLE_FEATURE_SH_STANDALONE
7730         if (applet_no >= 0) {
7731                 if (APPLET_IS_NOEXEC(applet_no)) {
7732                         clearenv();
7733                         while (*envp)
7734                                 putenv(*envp++);
7735                         run_applet_no_and_exit(applet_no, cmd, argv);
7736                 }
7737                 /* re-exec ourselves with the new arguments */
7738                 execve(bb_busybox_exec_path, argv, envp);
7739                 /* If they called chroot or otherwise made the binary no longer
7740                  * executable, fall through */
7741         }
7742 #endif
7743
7744  repeat:
7745 #ifdef SYSV
7746         do {
7747                 execve(cmd, argv, envp);
7748         } while (errno == EINTR);
7749 #else
7750         execve(cmd, argv, envp);
7751 #endif
7752         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7753                 /* Run "cmd" as a shell script:
7754                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7755                  * "If the execve() function fails with ENOEXEC, the shell
7756                  * shall execute a command equivalent to having a shell invoked
7757                  * with the command name as its first operand,
7758                  * with any remaining arguments passed to the new shell"
7759                  *
7760                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7761                  * just call ourselves.
7762                  *
7763                  * Note that bash reads ~80 chars of the file, and if it sees
7764                  * a zero byte before it sees newline, it doesn't try to
7765                  * interpret it, but fails with "cannot execute binary file"
7766                  * message and exit code 126. For one, this prevents attempts
7767                  * to interpret foreign ELF binaries as shell scripts.
7768                  */
7769                 argv[0] = cmd;
7770                 cmd = (char*) bb_busybox_exec_path;
7771                 /* NB: this is only possible because all callers of shellexec()
7772                  * ensure that the argv[-1] slot exists!
7773                  */
7774                 argv--;
7775                 argv[0] = (char*) "ash";
7776                 goto repeat;
7777         }
7778 }
7779
7780 /*
7781  * Exec a program.  Never returns.  If you change this routine, you may
7782  * have to change the find_command routine as well.
7783  * argv[-1] must exist and be writable! See tryexec() for why.
7784  */
7785 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7786 static void shellexec(char *prog, char **argv, const char *path, int idx)
7787 {
7788         char *cmdname;
7789         int e;
7790         char **envp;
7791         int exerrno;
7792         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7793
7794         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7795         if (strchr(prog, '/') != NULL
7796 #if ENABLE_FEATURE_SH_STANDALONE
7797          || (applet_no = find_applet_by_name(prog)) >= 0
7798 #endif
7799         ) {
7800                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7801                 if (applet_no >= 0) {
7802                         /* We tried execing ourself, but it didn't work.
7803                          * Maybe /proc/self/exe doesn't exist?
7804                          * Try $PATH search.
7805                          */
7806                         goto try_PATH;
7807                 }
7808                 e = errno;
7809         } else {
7810  try_PATH:
7811                 e = ENOENT;
7812                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7813                         if (--idx < 0 && pathopt == NULL) {
7814                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7815                                 if (errno != ENOENT && errno != ENOTDIR)
7816                                         e = errno;
7817                         }
7818                         stunalloc(cmdname);
7819                 }
7820         }
7821
7822         /* Map to POSIX errors */
7823         switch (e) {
7824         case EACCES:
7825                 exerrno = 126;
7826                 break;
7827         case ENOENT:
7828                 exerrno = 127;
7829                 break;
7830         default:
7831                 exerrno = 2;
7832                 break;
7833         }
7834         exitstatus = exerrno;
7835         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7836                 prog, e, suppress_int));
7837         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7838         /* NOTREACHED */
7839 }
7840
7841 static void
7842 printentry(struct tblentry *cmdp)
7843 {
7844         int idx;
7845         const char *path;
7846         char *name;
7847
7848         idx = cmdp->param.index;
7849         path = pathval();
7850         do {
7851                 name = path_advance(&path, cmdp->cmdname);
7852                 stunalloc(name);
7853         } while (--idx >= 0);
7854         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7855 }
7856
7857 /*
7858  * Clear out command entries.  The argument specifies the first entry in
7859  * PATH which has changed.
7860  */
7861 static void
7862 clearcmdentry(int firstchange)
7863 {
7864         struct tblentry **tblp;
7865         struct tblentry **pp;
7866         struct tblentry *cmdp;
7867
7868         INT_OFF;
7869         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7870                 pp = tblp;
7871                 while ((cmdp = *pp) != NULL) {
7872                         if ((cmdp->cmdtype == CMDNORMAL &&
7873                              cmdp->param.index >= firstchange)
7874                          || (cmdp->cmdtype == CMDBUILTIN &&
7875                              builtinloc >= firstchange)
7876                         ) {
7877                                 *pp = cmdp->next;
7878                                 free(cmdp);
7879                         } else {
7880                                 pp = &cmdp->next;
7881                         }
7882                 }
7883         }
7884         INT_ON;
7885 }
7886
7887 /*
7888  * Locate a command in the command hash table.  If "add" is nonzero,
7889  * add the command to the table if it is not already present.  The
7890  * variable "lastcmdentry" is set to point to the address of the link
7891  * pointing to the entry, so that delete_cmd_entry can delete the
7892  * entry.
7893  *
7894  * Interrupts must be off if called with add != 0.
7895  */
7896 static struct tblentry **lastcmdentry;
7897
7898 static struct tblentry *
7899 cmdlookup(const char *name, int add)
7900 {
7901         unsigned int hashval;
7902         const char *p;
7903         struct tblentry *cmdp;
7904         struct tblentry **pp;
7905
7906         p = name;
7907         hashval = (unsigned char)*p << 4;
7908         while (*p)
7909                 hashval += (unsigned char)*p++;
7910         hashval &= 0x7FFF;
7911         pp = &cmdtable[hashval % CMDTABLESIZE];
7912         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7913                 if (strcmp(cmdp->cmdname, name) == 0)
7914                         break;
7915                 pp = &cmdp->next;
7916         }
7917         if (add && cmdp == NULL) {
7918                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7919                                 + strlen(name)
7920                                 /* + 1 - already done because
7921                                  * tblentry::cmdname is char[1] */);
7922                 /*cmdp->next = NULL; - ckzalloc did it */
7923                 cmdp->cmdtype = CMDUNKNOWN;
7924                 strcpy(cmdp->cmdname, name);
7925         }
7926         lastcmdentry = pp;
7927         return cmdp;
7928 }
7929
7930 /*
7931  * Delete the command entry returned on the last lookup.
7932  */
7933 static void
7934 delete_cmd_entry(void)
7935 {
7936         struct tblentry *cmdp;
7937
7938         INT_OFF;
7939         cmdp = *lastcmdentry;
7940         *lastcmdentry = cmdp->next;
7941         if (cmdp->cmdtype == CMDFUNCTION)
7942                 freefunc(cmdp->param.func);
7943         free(cmdp);
7944         INT_ON;
7945 }
7946
7947 /*
7948  * Add a new command entry, replacing any existing command entry for
7949  * the same name - except special builtins.
7950  */
7951 static void
7952 addcmdentry(char *name, struct cmdentry *entry)
7953 {
7954         struct tblentry *cmdp;
7955
7956         cmdp = cmdlookup(name, 1);
7957         if (cmdp->cmdtype == CMDFUNCTION) {
7958                 freefunc(cmdp->param.func);
7959         }
7960         cmdp->cmdtype = entry->cmdtype;
7961         cmdp->param = entry->u;
7962         cmdp->rehash = 0;
7963 }
7964
7965 static int FAST_FUNC
7966 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7967 {
7968         struct tblentry **pp;
7969         struct tblentry *cmdp;
7970         int c;
7971         struct cmdentry entry;
7972         char *name;
7973
7974         if (nextopt("r") != '\0') {
7975                 clearcmdentry(0);
7976                 return 0;
7977         }
7978
7979         if (*argptr == NULL) {
7980                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7981                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7982                                 if (cmdp->cmdtype == CMDNORMAL)
7983                                         printentry(cmdp);
7984                         }
7985                 }
7986                 return 0;
7987         }
7988
7989         c = 0;
7990         while ((name = *argptr) != NULL) {
7991                 cmdp = cmdlookup(name, 0);
7992                 if (cmdp != NULL
7993                  && (cmdp->cmdtype == CMDNORMAL
7994                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7995                 ) {
7996                         delete_cmd_entry();
7997                 }
7998                 find_command(name, &entry, DO_ERR, pathval());
7999                 if (entry.cmdtype == CMDUNKNOWN)
8000                         c = 1;
8001                 argptr++;
8002         }
8003         return c;
8004 }
8005
8006 /*
8007  * Called when a cd is done.  Marks all commands so the next time they
8008  * are executed they will be rehashed.
8009  */
8010 static void
8011 hashcd(void)
8012 {
8013         struct tblentry **pp;
8014         struct tblentry *cmdp;
8015
8016         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8017                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8018                         if (cmdp->cmdtype == CMDNORMAL
8019                          || (cmdp->cmdtype == CMDBUILTIN
8020                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8021                              && builtinloc > 0)
8022                         ) {
8023                                 cmdp->rehash = 1;
8024                         }
8025                 }
8026         }
8027 }
8028
8029 /*
8030  * Fix command hash table when PATH changed.
8031  * Called before PATH is changed.  The argument is the new value of PATH;
8032  * pathval() still returns the old value at this point.
8033  * Called with interrupts off.
8034  */
8035 static void FAST_FUNC
8036 changepath(const char *new)
8037 {
8038         const char *old;
8039         int firstchange;
8040         int idx;
8041         int idx_bltin;
8042
8043         old = pathval();
8044         firstchange = 9999;     /* assume no change */
8045         idx = 0;
8046         idx_bltin = -1;
8047         for (;;) {
8048                 if (*old != *new) {
8049                         firstchange = idx;
8050                         if ((*old == '\0' && *new == ':')
8051                          || (*old == ':' && *new == '\0')
8052                         ) {
8053                                 firstchange++;
8054                         }
8055                         old = new;      /* ignore subsequent differences */
8056                 }
8057                 if (*new == '\0')
8058                         break;
8059                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8060                         idx_bltin = idx;
8061                 if (*new == ':')
8062                         idx++;
8063                 new++;
8064                 old++;
8065         }
8066         if (builtinloc < 0 && idx_bltin >= 0)
8067                 builtinloc = idx_bltin;             /* zap builtins */
8068         if (builtinloc >= 0 && idx_bltin < 0)
8069                 firstchange = 0;
8070         clearcmdentry(firstchange);
8071         builtinloc = idx_bltin;
8072 }
8073 enum {
8074         TEOF,
8075         TNL,
8076         TREDIR,
8077         TWORD,
8078         TSEMI,
8079         TBACKGND,
8080         TAND,
8081         TOR,
8082         TPIPE,
8083         TLP,
8084         TRP,
8085         TENDCASE,
8086         TENDBQUOTE,
8087         TNOT,
8088         TCASE,
8089         TDO,
8090         TDONE,
8091         TELIF,
8092         TELSE,
8093         TESAC,
8094         TFI,
8095         TFOR,
8096 #if BASH_FUNCTION
8097         TFUNCTION,
8098 #endif
8099         TIF,
8100         TIN,
8101         TTHEN,
8102         TUNTIL,
8103         TWHILE,
8104         TBEGIN,
8105         TEND
8106 };
8107 typedef smallint token_id_t;
8108
8109 /* Nth bit indicates if token marks the end of a list */
8110 enum {
8111         tokendlist = 0
8112         /*  0 */ | (1u << TEOF)
8113         /*  1 */ | (0u << TNL)
8114         /*  2 */ | (0u << TREDIR)
8115         /*  3 */ | (0u << TWORD)
8116         /*  4 */ | (0u << TSEMI)
8117         /*  5 */ | (0u << TBACKGND)
8118         /*  6 */ | (0u << TAND)
8119         /*  7 */ | (0u << TOR)
8120         /*  8 */ | (0u << TPIPE)
8121         /*  9 */ | (0u << TLP)
8122         /* 10 */ | (1u << TRP)
8123         /* 11 */ | (1u << TENDCASE)
8124         /* 12 */ | (1u << TENDBQUOTE)
8125         /* 13 */ | (0u << TNOT)
8126         /* 14 */ | (0u << TCASE)
8127         /* 15 */ | (1u << TDO)
8128         /* 16 */ | (1u << TDONE)
8129         /* 17 */ | (1u << TELIF)
8130         /* 18 */ | (1u << TELSE)
8131         /* 19 */ | (1u << TESAC)
8132         /* 20 */ | (1u << TFI)
8133         /* 21 */ | (0u << TFOR)
8134 #if BASH_FUNCTION
8135         /* 22 */ | (0u << TFUNCTION)
8136 #endif
8137         /* 23 */ | (0u << TIF)
8138         /* 24 */ | (0u << TIN)
8139         /* 25 */ | (1u << TTHEN)
8140         /* 26 */ | (0u << TUNTIL)
8141         /* 27 */ | (0u << TWHILE)
8142         /* 28 */ | (0u << TBEGIN)
8143         /* 29 */ | (1u << TEND)
8144         , /* thus far 29 bits used */
8145 };
8146
8147 static const char *const tokname_array[] = {
8148         "end of file",
8149         "newline",
8150         "redirection",
8151         "word",
8152         ";",
8153         "&",
8154         "&&",
8155         "||",
8156         "|",
8157         "(",
8158         ")",
8159         ";;",
8160         "`",
8161 #define KWDOFFSET 13
8162         /* the following are keywords */
8163         "!",
8164         "case",
8165         "do",
8166         "done",
8167         "elif",
8168         "else",
8169         "esac",
8170         "fi",
8171         "for",
8172 #if BASH_FUNCTION
8173         "function",
8174 #endif
8175         "if",
8176         "in",
8177         "then",
8178         "until",
8179         "while",
8180         "{",
8181         "}",
8182 };
8183
8184 /* Wrapper around strcmp for qsort/bsearch/... */
8185 static int
8186 pstrcmp(const void *a, const void *b)
8187 {
8188         return strcmp((char*)a, *(char**)b);
8189 }
8190
8191 static const char *const *
8192 findkwd(const char *s)
8193 {
8194         return bsearch(s, tokname_array + KWDOFFSET,
8195                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8196                         sizeof(tokname_array[0]), pstrcmp);
8197 }
8198
8199 /*
8200  * Locate and print what a word is...
8201  */
8202 static int
8203 describe_command(char *command, const char *path, int describe_command_verbose)
8204 {
8205         struct cmdentry entry;
8206 #if ENABLE_ASH_ALIAS
8207         const struct alias *ap;
8208 #endif
8209
8210         path = path ? path : pathval();
8211
8212         if (describe_command_verbose) {
8213                 out1str(command);
8214         }
8215
8216         /* First look at the keywords */
8217         if (findkwd(command)) {
8218                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8219                 goto out;
8220         }
8221
8222 #if ENABLE_ASH_ALIAS
8223         /* Then look at the aliases */
8224         ap = lookupalias(command, 0);
8225         if (ap != NULL) {
8226                 if (!describe_command_verbose) {
8227                         out1str("alias ");
8228                         printalias(ap);
8229                         return 0;
8230                 }
8231                 out1fmt(" is an alias for %s", ap->val);
8232                 goto out;
8233         }
8234 #endif
8235         /* Brute force */
8236         find_command(command, &entry, DO_ABS, path);
8237
8238         switch (entry.cmdtype) {
8239         case CMDNORMAL: {
8240                 int j = entry.u.index;
8241                 char *p;
8242                 if (j < 0) {
8243                         p = command;
8244                 } else {
8245                         do {
8246                                 p = path_advance(&path, command);
8247                                 stunalloc(p);
8248                         } while (--j >= 0);
8249                 }
8250                 if (describe_command_verbose) {
8251                         out1fmt(" is %s", p);
8252                 } else {
8253                         out1str(p);
8254                 }
8255                 break;
8256         }
8257
8258         case CMDFUNCTION:
8259                 if (describe_command_verbose) {
8260                         out1str(" is a shell function");
8261                 } else {
8262                         out1str(command);
8263                 }
8264                 break;
8265
8266         case CMDBUILTIN:
8267                 if (describe_command_verbose) {
8268                         out1fmt(" is a %sshell builtin",
8269                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8270                                         "special " : nullstr
8271                         );
8272                 } else {
8273                         out1str(command);
8274                 }
8275                 break;
8276
8277         default:
8278                 if (describe_command_verbose) {
8279                         out1str(": not found\n");
8280                 }
8281                 return 127;
8282         }
8283  out:
8284         out1str("\n");
8285         return 0;
8286 }
8287
8288 static int FAST_FUNC
8289 typecmd(int argc UNUSED_PARAM, char **argv)
8290 {
8291         int i = 1;
8292         int err = 0;
8293         int verbose = 1;
8294
8295         /* type -p ... ? (we don't bother checking for 'p') */
8296         if (argv[1] && argv[1][0] == '-') {
8297                 i++;
8298                 verbose = 0;
8299         }
8300         while (argv[i]) {
8301                 err |= describe_command(argv[i++], NULL, verbose);
8302         }
8303         return err;
8304 }
8305
8306 #if ENABLE_ASH_CMDCMD
8307 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8308 static char **
8309 parse_command_args(char **argv, const char **path)
8310 {
8311         char *cp, c;
8312
8313         for (;;) {
8314                 cp = *++argv;
8315                 if (!cp)
8316                         return NULL;
8317                 if (*cp++ != '-')
8318                         break;
8319                 c = *cp++;
8320                 if (!c)
8321                         break;
8322                 if (c == '-' && !*cp) {
8323                         if (!*++argv)
8324                                 return NULL;
8325                         break;
8326                 }
8327                 do {
8328                         switch (c) {
8329                         case 'p':
8330                                 *path = bb_default_path;
8331                                 break;
8332                         default:
8333                                 /* run 'typecmd' for other options */
8334                                 return NULL;
8335                         }
8336                         c = *cp++;
8337                 } while (c);
8338         }
8339         return argv;
8340 }
8341
8342 static int FAST_FUNC
8343 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8344 {
8345         char *cmd;
8346         int c;
8347         enum {
8348                 VERIFY_BRIEF = 1,
8349                 VERIFY_VERBOSE = 2,
8350         } verify = 0;
8351         const char *path = NULL;
8352
8353         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8354          * never reaches this function.
8355          */
8356
8357         while ((c = nextopt("pvV")) != '\0')
8358                 if (c == 'V')
8359                         verify |= VERIFY_VERBOSE;
8360                 else if (c == 'v')
8361                         /*verify |= VERIFY_BRIEF*/;
8362 #if DEBUG
8363                 else if (c != 'p')
8364                         abort();
8365 #endif
8366                 else
8367                         path = bb_default_path;
8368
8369         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8370         cmd = *argptr;
8371         if (/*verify && */ cmd)
8372                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8373
8374         return 0;
8375 }
8376 #endif
8377
8378
8379 /*static int funcblocksize;     // size of structures in function */
8380 /*static int funcstringsize;    // size of strings in node */
8381 static void *funcblock;         /* block to allocate function from */
8382 static char *funcstring_end;    /* end of block to allocate strings from */
8383
8384 /* flags in argument to evaltree */
8385 #define EV_EXIT    01           /* exit after evaluating tree */
8386 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8387
8388 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8389         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8390         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8391         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8392         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8393         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8394         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8395         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8396         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8397         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8398         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8399         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8400         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8401         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8402         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8403         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8404         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8405         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8406 #if BASH_REDIR_OUTPUT
8407         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8408 #endif
8409         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8410         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8411         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8412         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8413         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8414         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8415         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8416         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8417         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8418 };
8419
8420 static int calcsize(int funcblocksize, union node *n);
8421
8422 static int
8423 sizenodelist(int funcblocksize, struct nodelist *lp)
8424 {
8425         while (lp) {
8426                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8427                 funcblocksize = calcsize(funcblocksize, lp->n);
8428                 lp = lp->next;
8429         }
8430         return funcblocksize;
8431 }
8432
8433 static int
8434 calcsize(int funcblocksize, union node *n)
8435 {
8436         if (n == NULL)
8437                 return funcblocksize;
8438         funcblocksize += nodesize[n->type];
8439         switch (n->type) {
8440         case NCMD:
8441                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8442                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8443                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8444                 break;
8445         case NPIPE:
8446                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8447                 break;
8448         case NREDIR:
8449         case NBACKGND:
8450         case NSUBSHELL:
8451                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8452                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8453                 break;
8454         case NAND:
8455         case NOR:
8456         case NSEMI:
8457         case NWHILE:
8458         case NUNTIL:
8459                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8460                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8461                 break;
8462         case NIF:
8463                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8464                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8465                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8466                 break;
8467         case NFOR:
8468                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8469                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8470                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8471                 break;
8472         case NCASE:
8473                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8474                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8475                 break;
8476         case NCLIST:
8477                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8478                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8479                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8480                 break;
8481         case NDEFUN:
8482         case NARG:
8483                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8484                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8485                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8486                 break;
8487         case NTO:
8488 #if BASH_REDIR_OUTPUT
8489         case NTO2:
8490 #endif
8491         case NCLOBBER:
8492         case NFROM:
8493         case NFROMTO:
8494         case NAPPEND:
8495                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8496                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8497                 break;
8498         case NTOFD:
8499         case NFROMFD:
8500                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8501                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8502         break;
8503         case NHERE:
8504         case NXHERE:
8505                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8506                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8507                 break;
8508         case NNOT:
8509                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8510                 break;
8511         };
8512         return funcblocksize;
8513 }
8514
8515 static char *
8516 nodeckstrdup(char *s)
8517 {
8518         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8519         return strcpy(funcstring_end, s);
8520 }
8521
8522 static union node *copynode(union node *);
8523
8524 static struct nodelist *
8525 copynodelist(struct nodelist *lp)
8526 {
8527         struct nodelist *start;
8528         struct nodelist **lpp;
8529
8530         lpp = &start;
8531         while (lp) {
8532                 *lpp = funcblock;
8533                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8534                 (*lpp)->n = copynode(lp->n);
8535                 lp = lp->next;
8536                 lpp = &(*lpp)->next;
8537         }
8538         *lpp = NULL;
8539         return start;
8540 }
8541
8542 static union node *
8543 copynode(union node *n)
8544 {
8545         union node *new;
8546
8547         if (n == NULL)
8548                 return NULL;
8549         new = funcblock;
8550         funcblock = (char *) funcblock + nodesize[n->type];
8551
8552         switch (n->type) {
8553         case NCMD:
8554                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8555                 new->ncmd.args = copynode(n->ncmd.args);
8556                 new->ncmd.assign = copynode(n->ncmd.assign);
8557                 break;
8558         case NPIPE:
8559                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8560                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8561                 break;
8562         case NREDIR:
8563         case NBACKGND:
8564         case NSUBSHELL:
8565                 new->nredir.redirect = copynode(n->nredir.redirect);
8566                 new->nredir.n = copynode(n->nredir.n);
8567                 break;
8568         case NAND:
8569         case NOR:
8570         case NSEMI:
8571         case NWHILE:
8572         case NUNTIL:
8573                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8574                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8575                 break;
8576         case NIF:
8577                 new->nif.elsepart = copynode(n->nif.elsepart);
8578                 new->nif.ifpart = copynode(n->nif.ifpart);
8579                 new->nif.test = copynode(n->nif.test);
8580                 break;
8581         case NFOR:
8582                 new->nfor.var = nodeckstrdup(n->nfor.var);
8583                 new->nfor.body = copynode(n->nfor.body);
8584                 new->nfor.args = copynode(n->nfor.args);
8585                 break;
8586         case NCASE:
8587                 new->ncase.cases = copynode(n->ncase.cases);
8588                 new->ncase.expr = copynode(n->ncase.expr);
8589                 break;
8590         case NCLIST:
8591                 new->nclist.body = copynode(n->nclist.body);
8592                 new->nclist.pattern = copynode(n->nclist.pattern);
8593                 new->nclist.next = copynode(n->nclist.next);
8594                 break;
8595         case NDEFUN:
8596         case NARG:
8597                 new->narg.backquote = copynodelist(n->narg.backquote);
8598                 new->narg.text = nodeckstrdup(n->narg.text);
8599                 new->narg.next = copynode(n->narg.next);
8600                 break;
8601         case NTO:
8602 #if BASH_REDIR_OUTPUT
8603         case NTO2:
8604 #endif
8605         case NCLOBBER:
8606         case NFROM:
8607         case NFROMTO:
8608         case NAPPEND:
8609                 new->nfile.fname = copynode(n->nfile.fname);
8610                 new->nfile.fd = n->nfile.fd;
8611                 new->nfile.next = copynode(n->nfile.next);
8612                 break;
8613         case NTOFD:
8614         case NFROMFD:
8615                 new->ndup.vname = copynode(n->ndup.vname);
8616                 new->ndup.dupfd = n->ndup.dupfd;
8617                 new->ndup.fd = n->ndup.fd;
8618                 new->ndup.next = copynode(n->ndup.next);
8619                 break;
8620         case NHERE:
8621         case NXHERE:
8622                 new->nhere.doc = copynode(n->nhere.doc);
8623                 new->nhere.fd = n->nhere.fd;
8624                 new->nhere.next = copynode(n->nhere.next);
8625                 break;
8626         case NNOT:
8627                 new->nnot.com = copynode(n->nnot.com);
8628                 break;
8629         };
8630         new->type = n->type;
8631         return new;
8632 }
8633
8634 /*
8635  * Make a copy of a parse tree.
8636  */
8637 static struct funcnode *
8638 copyfunc(union node *n)
8639 {
8640         struct funcnode *f;
8641         size_t blocksize;
8642
8643         /*funcstringsize = 0;*/
8644         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8645         f = ckzalloc(blocksize /* + funcstringsize */);
8646         funcblock = (char *) f + offsetof(struct funcnode, n);
8647         funcstring_end = (char *) f + blocksize;
8648         copynode(n);
8649         /* f->count = 0; - ckzalloc did it */
8650         return f;
8651 }
8652
8653 /*
8654  * Define a shell function.
8655  */
8656 static void
8657 defun(union node *func)
8658 {
8659         struct cmdentry entry;
8660
8661         INT_OFF;
8662         entry.cmdtype = CMDFUNCTION;
8663         entry.u.func = copyfunc(func);
8664         addcmdentry(func->narg.text, &entry);
8665         INT_ON;
8666 }
8667
8668 /* Reasons for skipping commands (see comment on breakcmd routine) */
8669 #define SKIPBREAK      (1 << 0)
8670 #define SKIPCONT       (1 << 1)
8671 #define SKIPFUNC       (1 << 2)
8672 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8673 static int skipcount;           /* number of levels to skip */
8674 static int funcnest;            /* depth of function calls */
8675 static int loopnest;            /* current loop nesting level */
8676
8677 /* Forward decl way out to parsing code - dotrap needs it */
8678 static int evalstring(char *s, int flags);
8679
8680 /* Called to execute a trap.
8681  * Single callsite - at the end of evaltree().
8682  * If we return non-zero, evaltree raises EXEXIT exception.
8683  *
8684  * Perhaps we should avoid entering new trap handlers
8685  * while we are executing a trap handler. [is it a TODO?]
8686  */
8687 static void
8688 dotrap(void)
8689 {
8690         uint8_t *g;
8691         int sig;
8692         uint8_t last_status;
8693
8694         if (!pending_sig)
8695                 return;
8696
8697         last_status = exitstatus;
8698         pending_sig = 0;
8699         barrier();
8700
8701         TRACE(("dotrap entered\n"));
8702         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8703                 char *p;
8704
8705                 if (!*g)
8706                         continue;
8707
8708                 if (evalskip) {
8709                         pending_sig = sig;
8710                         break;
8711                 }
8712
8713                 p = trap[sig];
8714                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8715                  * don't upset it by resetting gotsig[SIGINT-1] */
8716                 if (sig == SIGINT && !p)
8717                         continue;
8718
8719                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8720                 *g = 0;
8721                 if (!p)
8722                         continue;
8723                 evalstring(p, 0);
8724         }
8725         exitstatus = last_status;
8726         TRACE(("dotrap returns\n"));
8727 }
8728
8729 /* forward declarations - evaluation is fairly recursive business... */
8730 static int evalloop(union node *, int);
8731 static int evalfor(union node *, int);
8732 static int evalcase(union node *, int);
8733 static int evalsubshell(union node *, int);
8734 static void expredir(union node *);
8735 static int evalpipe(union node *, int);
8736 static int evalcommand(union node *, int);
8737 static int evalbltin(const struct builtincmd *, int, char **, int);
8738 static void prehash(union node *);
8739
8740 /*
8741  * Evaluate a parse tree.  The value is left in the global variable
8742  * exitstatus.
8743  */
8744 static int
8745 evaltree(union node *n, int flags)
8746 {
8747         int checkexit = 0;
8748         int (*evalfn)(union node *, int);
8749         int status = 0;
8750
8751         if (n == NULL) {
8752                 TRACE(("evaltree(NULL) called\n"));
8753                 goto out;
8754         }
8755         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8756
8757         dotrap();
8758
8759         switch (n->type) {
8760         default:
8761 #if DEBUG
8762                 out1fmt("Node type = %d\n", n->type);
8763                 fflush_all();
8764                 break;
8765 #endif
8766         case NNOT:
8767                 status = !evaltree(n->nnot.com, EV_TESTED);
8768                 goto setstatus;
8769         case NREDIR:
8770                 expredir(n->nredir.redirect);
8771                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8772                 if (!status) {
8773                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8774                 }
8775                 if (n->nredir.redirect)
8776                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8777                 goto setstatus;
8778         case NCMD:
8779                 evalfn = evalcommand;
8780  checkexit:
8781                 if (eflag && !(flags & EV_TESTED))
8782                         checkexit = ~0;
8783                 goto calleval;
8784         case NFOR:
8785                 evalfn = evalfor;
8786                 goto calleval;
8787         case NWHILE:
8788         case NUNTIL:
8789                 evalfn = evalloop;
8790                 goto calleval;
8791         case NSUBSHELL:
8792         case NBACKGND:
8793                 evalfn = evalsubshell;
8794                 goto checkexit;
8795         case NPIPE:
8796                 evalfn = evalpipe;
8797                 goto checkexit;
8798         case NCASE:
8799                 evalfn = evalcase;
8800                 goto calleval;
8801         case NAND:
8802         case NOR:
8803         case NSEMI: {
8804
8805 #if NAND + 1 != NOR
8806 #error NAND + 1 != NOR
8807 #endif
8808 #if NOR + 1 != NSEMI
8809 #error NOR + 1 != NSEMI
8810 #endif
8811                 unsigned is_or = n->type - NAND;
8812                 status = evaltree(
8813                         n->nbinary.ch1,
8814                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8815                 );
8816                 if ((!status) == is_or || evalskip)
8817                         break;
8818                 n = n->nbinary.ch2;
8819  evaln:
8820                 evalfn = evaltree;
8821  calleval:
8822                 status = evalfn(n, flags);
8823                 goto setstatus;
8824         }
8825         case NIF:
8826                 status = evaltree(n->nif.test, EV_TESTED);
8827                 if (evalskip)
8828                         break;
8829                 if (!status) {
8830                         n = n->nif.ifpart;
8831                         goto evaln;
8832                 }
8833                 if (n->nif.elsepart) {
8834                         n = n->nif.elsepart;
8835                         goto evaln;
8836                 }
8837                 status = 0;
8838                 goto setstatus;
8839         case NDEFUN:
8840                 defun(n);
8841                 /* Not necessary. To test it:
8842                  * "false; f() { qwerty; }; echo $?" should print 0.
8843                  */
8844                 /* status = 0; */
8845  setstatus:
8846                 exitstatus = status;
8847                 break;
8848         }
8849  out:
8850         /* Order of checks below is important:
8851          * signal handlers trigger before exit caused by "set -e".
8852          */
8853         dotrap();
8854
8855         if (checkexit & status)
8856                 raise_exception(EXEXIT);
8857         if (flags & EV_EXIT)
8858                 raise_exception(EXEXIT);
8859
8860         TRACE(("leaving evaltree (no interrupts)\n"));
8861         return exitstatus;
8862 }
8863
8864 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8865 static
8866 #endif
8867 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8868
8869 static int
8870 skiploop(void)
8871 {
8872         int skip = evalskip;
8873
8874         switch (skip) {
8875         case 0:
8876                 break;
8877         case SKIPBREAK:
8878         case SKIPCONT:
8879                 if (--skipcount <= 0) {
8880                         evalskip = 0;
8881                         break;
8882                 }
8883                 skip = SKIPBREAK;
8884                 break;
8885         }
8886         return skip;
8887 }
8888
8889 static int
8890 evalloop(union node *n, int flags)
8891 {
8892         int skip;
8893         int status;
8894
8895         loopnest++;
8896         status = 0;
8897         flags &= EV_TESTED;
8898         do {
8899                 int i;
8900
8901                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8902                 skip = skiploop();
8903                 if (skip == SKIPFUNC)
8904                         status = i;
8905                 if (skip)
8906                         continue;
8907                 if (n->type != NWHILE)
8908                         i = !i;
8909                 if (i != 0)
8910                         break;
8911                 status = evaltree(n->nbinary.ch2, flags);
8912                 skip = skiploop();
8913         } while (!(skip & ~SKIPCONT));
8914         loopnest--;
8915
8916         return status;
8917 }
8918
8919 static int
8920 evalfor(union node *n, int flags)
8921 {
8922         struct arglist arglist;
8923         union node *argp;
8924         struct strlist *sp;
8925         struct stackmark smark;
8926         int status = 0;
8927
8928         setstackmark(&smark);
8929         arglist.list = NULL;
8930         arglist.lastp = &arglist.list;
8931         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8932                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8933         }
8934         *arglist.lastp = NULL;
8935
8936         loopnest++;
8937         flags &= EV_TESTED;
8938         for (sp = arglist.list; sp; sp = sp->next) {
8939                 setvar0(n->nfor.var, sp->text);
8940                 status = evaltree(n->nfor.body, flags);
8941                 if (skiploop() & ~SKIPCONT)
8942                         break;
8943         }
8944         loopnest--;
8945         popstackmark(&smark);
8946
8947         return status;
8948 }
8949
8950 static int
8951 evalcase(union node *n, int flags)
8952 {
8953         union node *cp;
8954         union node *patp;
8955         struct arglist arglist;
8956         struct stackmark smark;
8957         int status = 0;
8958
8959         setstackmark(&smark);
8960         arglist.list = NULL;
8961         arglist.lastp = &arglist.list;
8962         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8963         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8964                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8965                         if (casematch(patp, arglist.list->text)) {
8966                                 /* Ensure body is non-empty as otherwise
8967                                  * EV_EXIT may prevent us from setting the
8968                                  * exit status.
8969                                  */
8970                                 if (evalskip == 0 && cp->nclist.body) {
8971                                         status = evaltree(cp->nclist.body, flags);
8972                                 }
8973                                 goto out;
8974                         }
8975                 }
8976         }
8977  out:
8978         popstackmark(&smark);
8979
8980         return status;
8981 }
8982
8983 /*
8984  * Kick off a subshell to evaluate a tree.
8985  */
8986 static int
8987 evalsubshell(union node *n, int flags)
8988 {
8989         struct job *jp;
8990         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8991         int status;
8992
8993         expredir(n->nredir.redirect);
8994         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8995                 goto nofork;
8996         INT_OFF;
8997         if (backgnd == FORK_FG)
8998                 get_tty_state();
8999         jp = makejob(/*n,*/ 1);
9000         if (forkshell(jp, n, backgnd) == 0) {
9001                 /* child */
9002                 INT_ON;
9003                 flags |= EV_EXIT;
9004                 if (backgnd)
9005                         flags &= ~EV_TESTED;
9006  nofork:
9007                 redirect(n->nredir.redirect, 0);
9008                 evaltreenr(n->nredir.n, flags);
9009                 /* never returns */
9010         }
9011         /* parent */
9012         status = 0;
9013         if (backgnd == FORK_FG)
9014                 status = waitforjob(jp);
9015         INT_ON;
9016         return status;
9017 }
9018
9019 /*
9020  * Compute the names of the files in a redirection list.
9021  */
9022 static void fixredir(union node *, const char *, int);
9023 static void
9024 expredir(union node *n)
9025 {
9026         union node *redir;
9027
9028         for (redir = n; redir; redir = redir->nfile.next) {
9029                 struct arglist fn;
9030
9031                 fn.list = NULL;
9032                 fn.lastp = &fn.list;
9033                 switch (redir->type) {
9034                 case NFROMTO:
9035                 case NFROM:
9036                 case NTO:
9037 #if BASH_REDIR_OUTPUT
9038                 case NTO2:
9039 #endif
9040                 case NCLOBBER:
9041                 case NAPPEND:
9042                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9043                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9044 #if BASH_REDIR_OUTPUT
9045  store_expfname:
9046 #endif
9047 #if 0
9048 // By the design of stack allocator, the loop of this kind:
9049 //      while true; do while true; do break; done </dev/null; done
9050 // will look like a memory leak: ash plans to free expfname's
9051 // of "/dev/null" as soon as it finishes running the loop
9052 // (in this case, never).
9053 // This "fix" is wrong:
9054                         if (redir->nfile.expfname)
9055                                 stunalloc(redir->nfile.expfname);
9056 // It results in corrupted state of stacked allocations.
9057 #endif
9058                         redir->nfile.expfname = fn.list->text;
9059                         break;
9060                 case NFROMFD:
9061                 case NTOFD: /* >& */
9062                         if (redir->ndup.vname) {
9063                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9064                                 if (fn.list == NULL)
9065                                         ash_msg_and_raise_error("redir error");
9066 #if BASH_REDIR_OUTPUT
9067 //FIXME: we used expandarg with different args!
9068                                 if (!isdigit_str9(fn.list->text)) {
9069                                         /* >&file, not >&fd */
9070                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9071                                                 ash_msg_and_raise_error("redir error");
9072                                         redir->type = NTO2;
9073                                         goto store_expfname;
9074                                 }
9075 #endif
9076                                 fixredir(redir, fn.list->text, 1);
9077                         }
9078                         break;
9079                 }
9080         }
9081 }
9082
9083 /*
9084  * Evaluate a pipeline.  All the processes in the pipeline are children
9085  * of the process creating the pipeline.  (This differs from some versions
9086  * of the shell, which make the last process in a pipeline the parent
9087  * of all the rest.)
9088  */
9089 static int
9090 evalpipe(union node *n, int flags)
9091 {
9092         struct job *jp;
9093         struct nodelist *lp;
9094         int pipelen;
9095         int prevfd;
9096         int pip[2];
9097         int status = 0;
9098
9099         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9100         pipelen = 0;
9101         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9102                 pipelen++;
9103         flags |= EV_EXIT;
9104         INT_OFF;
9105         if (n->npipe.pipe_backgnd == 0)
9106                 get_tty_state();
9107         jp = makejob(/*n,*/ pipelen);
9108         prevfd = -1;
9109         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9110                 prehash(lp->n);
9111                 pip[1] = -1;
9112                 if (lp->next) {
9113                         if (pipe(pip) < 0) {
9114                                 close(prevfd);
9115                                 ash_msg_and_raise_error("pipe call failed");
9116                         }
9117                 }
9118                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9119                         /* child */
9120                         INT_ON;
9121                         if (pip[1] >= 0) {
9122                                 close(pip[0]);
9123                         }
9124                         if (prevfd > 0) {
9125                                 dup2(prevfd, 0);
9126                                 close(prevfd);
9127                         }
9128                         if (pip[1] > 1) {
9129                                 dup2(pip[1], 1);
9130                                 close(pip[1]);
9131                         }
9132                         evaltreenr(lp->n, flags);
9133                         /* never returns */
9134                 }
9135                 /* parent */
9136                 if (prevfd >= 0)
9137                         close(prevfd);
9138                 prevfd = pip[0];
9139                 /* Don't want to trigger debugging */
9140                 if (pip[1] != -1)
9141                         close(pip[1]);
9142         }
9143         if (n->npipe.pipe_backgnd == 0) {
9144                 status = waitforjob(jp);
9145                 TRACE(("evalpipe:  job done exit status %d\n", status));
9146         }
9147         INT_ON;
9148
9149         return status;
9150 }
9151
9152 /*
9153  * Controls whether the shell is interactive or not.
9154  */
9155 static void
9156 setinteractive(int on)
9157 {
9158         static smallint is_interactive;
9159
9160         if (++on == is_interactive)
9161                 return;
9162         is_interactive = on;
9163         setsignal(SIGINT);
9164         setsignal(SIGQUIT);
9165         setsignal(SIGTERM);
9166 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9167         if (is_interactive > 1) {
9168                 /* Looks like they want an interactive shell */
9169                 static smallint did_banner;
9170
9171                 if (!did_banner) {
9172                         /* note: ash and hush share this string */
9173                         out1fmt("\n\n%s %s\n"
9174                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9175                                 "\n",
9176                                 bb_banner,
9177                                 "built-in shell (ash)"
9178                         );
9179                         did_banner = 1;
9180                 }
9181         }
9182 #endif
9183 }
9184
9185 static void
9186 optschanged(void)
9187 {
9188 #if DEBUG
9189         opentrace();
9190 #endif
9191         setinteractive(iflag);
9192         setjobctl(mflag);
9193 #if ENABLE_FEATURE_EDITING_VI
9194         if (viflag)
9195                 line_input_state->flags |= VI_MODE;
9196         else
9197                 line_input_state->flags &= ~VI_MODE;
9198 #else
9199         viflag = 0; /* forcibly keep the option off */
9200 #endif
9201 }
9202
9203 static struct localvar *localvars;
9204
9205 /*
9206  * Called after a function returns.
9207  * Interrupts must be off.
9208  */
9209 static void
9210 poplocalvars(void)
9211 {
9212         struct localvar *lvp;
9213         struct var *vp;
9214
9215         while ((lvp = localvars) != NULL) {
9216                 localvars = lvp->next;
9217                 vp = lvp->vp;
9218                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9219                 if (vp == NULL) {       /* $- saved */
9220                         memcpy(optlist, lvp->text, sizeof(optlist));
9221                         free((char*)lvp->text);
9222                         optschanged();
9223                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9224                         unsetvar(vp->var_text);
9225                 } else {
9226                         if (vp->var_func)
9227                                 vp->var_func(var_end(lvp->text));
9228                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9229                                 free((char*)vp->var_text);
9230                         vp->flags = lvp->flags;
9231                         vp->var_text = lvp->text;
9232                 }
9233                 free(lvp);
9234         }
9235 }
9236
9237 static int
9238 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9239 {
9240         volatile struct shparam saveparam;
9241         struct localvar *volatile savelocalvars;
9242         struct jmploc *volatile savehandler;
9243         struct jmploc jmploc;
9244         int e;
9245
9246         saveparam = shellparam;
9247         savelocalvars = localvars;
9248         savehandler = exception_handler;
9249         e = setjmp(jmploc.loc);
9250         if (e) {
9251                 goto funcdone;
9252         }
9253         INT_OFF;
9254         exception_handler = &jmploc;
9255         localvars = NULL;
9256         shellparam.malloced = 0;
9257         func->count++;
9258         funcnest++;
9259         INT_ON;
9260         shellparam.nparam = argc - 1;
9261         shellparam.p = argv + 1;
9262 #if ENABLE_ASH_GETOPTS
9263         shellparam.optind = 1;
9264         shellparam.optoff = -1;
9265 #endif
9266         evaltree(func->n.narg.next, flags & EV_TESTED);
9267  funcdone:
9268         INT_OFF;
9269         funcnest--;
9270         freefunc(func);
9271         poplocalvars();
9272         localvars = savelocalvars;
9273         freeparam(&shellparam);
9274         shellparam = saveparam;
9275         exception_handler = savehandler;
9276         INT_ON;
9277         evalskip &= ~SKIPFUNC;
9278         return e;
9279 }
9280
9281 /*
9282  * Make a variable a local variable.  When a variable is made local, it's
9283  * value and flags are saved in a localvar structure.  The saved values
9284  * will be restored when the shell function returns.  We handle the name
9285  * "-" as a special case: it makes changes to "set +-options" local
9286  * (options will be restored on return from the function).
9287  */
9288 static void
9289 mklocal(char *name)
9290 {
9291         struct localvar *lvp;
9292         struct var **vpp;
9293         struct var *vp;
9294         char *eq = strchr(name, '=');
9295
9296         INT_OFF;
9297         /* Cater for duplicate "local". Examples:
9298          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9299          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9300          */
9301         lvp = localvars;
9302         while (lvp) {
9303                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9304                         if (eq)
9305                                 setvareq(name, 0);
9306                         /* else:
9307                          * it's a duplicate "local VAR" declaration, do nothing
9308                          */
9309                         goto ret;
9310                 }
9311                 lvp = lvp->next;
9312         }
9313
9314         lvp = ckzalloc(sizeof(*lvp));
9315         if (LONE_DASH(name)) {
9316                 char *p;
9317                 p = ckmalloc(sizeof(optlist));
9318                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9319                 vp = NULL;
9320         } else {
9321                 vpp = hashvar(name);
9322                 vp = *findvar(vpp, name);
9323                 if (vp == NULL) {
9324                         /* variable did not exist yet */
9325                         if (eq)
9326                                 setvareq(name, VSTRFIXED);
9327                         else
9328                                 setvar(name, NULL, VSTRFIXED);
9329                         vp = *vpp;      /* the new variable */
9330                         lvp->flags = VUNSET;
9331                 } else {
9332                         lvp->text = vp->var_text;
9333                         lvp->flags = vp->flags;
9334                         /* make sure neither "struct var" nor string gets freed
9335                          * during (un)setting:
9336                          */
9337                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9338                         if (eq)
9339                                 setvareq(name, 0);
9340                         else
9341                                 /* "local VAR" unsets VAR: */
9342                                 setvar0(name, NULL);
9343                 }
9344         }
9345         lvp->vp = vp;
9346         lvp->next = localvars;
9347         localvars = lvp;
9348  ret:
9349         INT_ON;
9350 }
9351
9352 /*
9353  * The "local" command.
9354  */
9355 static int FAST_FUNC
9356 localcmd(int argc UNUSED_PARAM, char **argv)
9357 {
9358         char *name;
9359
9360         if (!funcnest)
9361                 ash_msg_and_raise_error("not in a function");
9362
9363         argv = argptr;
9364         while ((name = *argv++) != NULL) {
9365                 mklocal(name);
9366         }
9367         return 0;
9368 }
9369
9370 static int FAST_FUNC
9371 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9372 {
9373         return 1;
9374 }
9375
9376 static int FAST_FUNC
9377 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9378 {
9379         return 0;
9380 }
9381
9382 static int FAST_FUNC
9383 execcmd(int argc UNUSED_PARAM, char **argv)
9384 {
9385         optionarg = NULL;
9386         while (nextopt("a:") != '\0')
9387                 /* nextopt() sets optionarg to "-a ARGV0" */;
9388
9389         argv = argptr;
9390         if (argv[0]) {
9391                 char *prog;
9392
9393                 iflag = 0;              /* exit on error */
9394                 mflag = 0;
9395                 optschanged();
9396                 /* We should set up signals for "exec CMD"
9397                  * the same way as for "CMD" without "exec".
9398                  * But optschanged->setinteractive->setsignal
9399                  * still thought we are a root shell. Therefore, for example,
9400                  * SIGQUIT is still set to IGN. Fix it:
9401                  */
9402                 shlvl++;
9403                 setsignal(SIGQUIT);
9404                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9405                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9406                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9407
9408                 prog = argv[0];
9409                 if (optionarg)
9410                         argv[0] = optionarg;
9411                 shellexec(prog, argv, pathval(), 0);
9412                 /* NOTREACHED */
9413         }
9414         return 0;
9415 }
9416
9417 /*
9418  * The return command.
9419  */
9420 static int FAST_FUNC
9421 returncmd(int argc UNUSED_PARAM, char **argv)
9422 {
9423         /*
9424          * If called outside a function, do what ksh does;
9425          * skip the rest of the file.
9426          */
9427         evalskip = SKIPFUNC;
9428         return argv[1] ? number(argv[1]) : exitstatus;
9429 }
9430
9431 /* Forward declarations for builtintab[] */
9432 static int breakcmd(int, char **) FAST_FUNC;
9433 static int dotcmd(int, char **) FAST_FUNC;
9434 static int evalcmd(int, char **, int) FAST_FUNC;
9435 static int exitcmd(int, char **) FAST_FUNC;
9436 static int exportcmd(int, char **) FAST_FUNC;
9437 #if ENABLE_ASH_GETOPTS
9438 static int getoptscmd(int, char **) FAST_FUNC;
9439 #endif
9440 #if ENABLE_ASH_HELP
9441 static int helpcmd(int, char **) FAST_FUNC;
9442 #endif
9443 #if MAX_HISTORY
9444 static int historycmd(int, char **) FAST_FUNC;
9445 #endif
9446 #if ENABLE_FEATURE_SH_MATH
9447 static int letcmd(int, char **) FAST_FUNC;
9448 #endif
9449 static int readcmd(int, char **) FAST_FUNC;
9450 static int setcmd(int, char **) FAST_FUNC;
9451 static int shiftcmd(int, char **) FAST_FUNC;
9452 static int timescmd(int, char **) FAST_FUNC;
9453 static int trapcmd(int, char **) FAST_FUNC;
9454 static int umaskcmd(int, char **) FAST_FUNC;
9455 static int unsetcmd(int, char **) FAST_FUNC;
9456 static int ulimitcmd(int, char **) FAST_FUNC;
9457
9458 #define BUILTIN_NOSPEC          "0"
9459 #define BUILTIN_SPECIAL         "1"
9460 #define BUILTIN_REGULAR         "2"
9461 #define BUILTIN_SPEC_REG        "3"
9462 #define BUILTIN_ASSIGN          "4"
9463 #define BUILTIN_SPEC_ASSG       "5"
9464 #define BUILTIN_REG_ASSG        "6"
9465 #define BUILTIN_SPEC_REG_ASSG   "7"
9466
9467 /* Stubs for calling non-FAST_FUNC's */
9468 #if ENABLE_ASH_ECHO
9469 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9470 #endif
9471 #if ENABLE_ASH_PRINTF
9472 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9473 #endif
9474 #if ENABLE_ASH_TEST || BASH_TEST2
9475 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9476 #endif
9477
9478 /* Keep these in proper order since it is searched via bsearch() */
9479 static const struct builtincmd builtintab[] = {
9480         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9481         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9482 #if ENABLE_ASH_TEST
9483         { BUILTIN_REGULAR       "["       , testcmd    },
9484 #endif
9485 #if BASH_TEST2
9486         { BUILTIN_REGULAR       "[["      , testcmd    },
9487 #endif
9488 #if ENABLE_ASH_ALIAS
9489         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9490 #endif
9491 #if JOBS
9492         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9493 #endif
9494         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9495         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9496         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9497 #if ENABLE_ASH_CMDCMD
9498         { BUILTIN_REGULAR       "command" , commandcmd },
9499 #endif
9500         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9501 #if ENABLE_ASH_ECHO
9502         { BUILTIN_REGULAR       "echo"    , echocmd    },
9503 #endif
9504         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9505         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9506         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9507         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9508         { BUILTIN_REGULAR       "false"   , falsecmd   },
9509 #if JOBS
9510         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9511 #endif
9512 #if ENABLE_ASH_GETOPTS
9513         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9514 #endif
9515         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9516 #if ENABLE_ASH_HELP
9517         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9518 #endif
9519 #if MAX_HISTORY
9520         { BUILTIN_NOSPEC        "history" , historycmd },
9521 #endif
9522 #if JOBS
9523         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9524         { BUILTIN_REGULAR       "kill"    , killcmd    },
9525 #endif
9526 #if ENABLE_FEATURE_SH_MATH
9527         { BUILTIN_NOSPEC        "let"     , letcmd     },
9528 #endif
9529         { BUILTIN_ASSIGN        "local"   , localcmd   },
9530 #if ENABLE_ASH_PRINTF
9531         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9532 #endif
9533         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9534         { BUILTIN_REGULAR       "read"    , readcmd    },
9535         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9536         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9537         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9538         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9539 #if BASH_SOURCE
9540         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9541 #endif
9542 #if ENABLE_ASH_TEST
9543         { BUILTIN_REGULAR       "test"    , testcmd    },
9544 #endif
9545         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9546         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9547         { BUILTIN_REGULAR       "true"    , truecmd    },
9548         { BUILTIN_NOSPEC        "type"    , typecmd    },
9549         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9550         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9551 #if ENABLE_ASH_ALIAS
9552         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9553 #endif
9554         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9555         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9556 };
9557
9558 /* Should match the above table! */
9559 #define COMMANDCMD (builtintab + \
9560         /* . : */       2 + \
9561         /* [ */         1 * ENABLE_ASH_TEST + \
9562         /* [[ */        1 * BASH_TEST2 + \
9563         /* alias */     1 * ENABLE_ASH_ALIAS + \
9564         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9565         /* break cd cddir  */   3)
9566 #define EVALCMD (COMMANDCMD + \
9567         /* command */   1 * ENABLE_ASH_CMDCMD + \
9568         /* continue */  1 + \
9569         /* echo */      1 * ENABLE_ASH_ECHO + \
9570         0)
9571 #define EXECCMD (EVALCMD + \
9572         /* eval */      1)
9573
9574 /*
9575  * Search the table of builtin commands.
9576  */
9577 static int
9578 pstrcmp1(const void *a, const void *b)
9579 {
9580         return strcmp((char*)a, *(char**)b + 1);
9581 }
9582 static struct builtincmd *
9583 find_builtin(const char *name)
9584 {
9585         struct builtincmd *bp;
9586
9587         bp = bsearch(
9588                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9589                 pstrcmp1
9590         );
9591         return bp;
9592 }
9593
9594 /*
9595  * Execute a simple command.
9596  */
9597 static int
9598 isassignment(const char *p)
9599 {
9600         const char *q = endofname(p);
9601         if (p == q)
9602                 return 0;
9603         return *q == '=';
9604 }
9605 static int FAST_FUNC
9606 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9607 {
9608         /* Preserve exitstatus of a previous possible redirection
9609          * as POSIX mandates */
9610         return back_exitstatus;
9611 }
9612 static int
9613 evalcommand(union node *cmd, int flags)
9614 {
9615         static const struct builtincmd null_bltin = {
9616                 "\0\0", bltincmd /* why three NULs? */
9617         };
9618         struct stackmark smark;
9619         union node *argp;
9620         struct arglist arglist;
9621         struct arglist varlist;
9622         char **argv;
9623         int argc;
9624         const struct strlist *sp;
9625         struct cmdentry cmdentry;
9626         struct job *jp;
9627         char *lastarg;
9628         const char *path;
9629         int spclbltin;
9630         int status;
9631         char **nargv;
9632         struct builtincmd *bcmd;
9633         smallint cmd_is_exec;
9634         smallint pseudovarflag = 0;
9635
9636         /* First expand the arguments. */
9637         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9638         setstackmark(&smark);
9639         back_exitstatus = 0;
9640
9641         cmdentry.cmdtype = CMDBUILTIN;
9642         cmdentry.u.cmd = &null_bltin;
9643         varlist.lastp = &varlist.list;
9644         *varlist.lastp = NULL;
9645         arglist.lastp = &arglist.list;
9646         *arglist.lastp = NULL;
9647
9648         argc = 0;
9649         if (cmd->ncmd.args) {
9650                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9651                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9652         }
9653
9654         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9655                 struct strlist **spp;
9656
9657                 spp = arglist.lastp;
9658                 if (pseudovarflag && isassignment(argp->narg.text))
9659                         expandarg(argp, &arglist, EXP_VARTILDE);
9660                 else
9661                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9662
9663                 for (sp = *spp; sp; sp = sp->next)
9664                         argc++;
9665         }
9666
9667         /* Reserve one extra spot at the front for shellexec. */
9668         nargv = stalloc(sizeof(char *) * (argc + 2));
9669         argv = ++nargv;
9670         for (sp = arglist.list; sp; sp = sp->next) {
9671                 TRACE(("evalcommand arg: %s\n", sp->text));
9672                 *nargv++ = sp->text;
9673         }
9674         *nargv = NULL;
9675
9676         lastarg = NULL;
9677         if (iflag && funcnest == 0 && argc > 0)
9678                 lastarg = nargv[-1];
9679
9680         preverrout_fd = 2;
9681         expredir(cmd->ncmd.redirect);
9682         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9683
9684         path = vpath.var_text;
9685         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9686                 struct strlist **spp;
9687                 char *p;
9688
9689                 spp = varlist.lastp;
9690                 expandarg(argp, &varlist, EXP_VARTILDE);
9691
9692                 /*
9693                  * Modify the command lookup path, if a PATH= assignment
9694                  * is present
9695                  */
9696                 p = (*spp)->text;
9697                 if (varcmp(p, path) == 0)
9698                         path = p;
9699         }
9700
9701         /* Print the command if xflag is set. */
9702         if (xflag) {
9703                 int n;
9704                 const char *p = " %s" + 1;
9705
9706                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9707                 sp = varlist.list;
9708                 for (n = 0; n < 2; n++) {
9709                         while (sp) {
9710                                 fdprintf(preverrout_fd, p, sp->text);
9711                                 sp = sp->next;
9712                                 p = " %s";
9713                         }
9714                         sp = arglist.list;
9715                 }
9716                 safe_write(preverrout_fd, "\n", 1);
9717         }
9718
9719         cmd_is_exec = 0;
9720         spclbltin = -1;
9721
9722         /* Now locate the command. */
9723         if (argc) {
9724                 int cmd_flag = DO_ERR;
9725 #if ENABLE_ASH_CMDCMD
9726                 const char *oldpath = path + 5;
9727 #endif
9728                 path += 5;
9729                 for (;;) {
9730                         find_command(argv[0], &cmdentry, cmd_flag, path);
9731                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9732                                 flush_stdout_stderr();
9733                                 status = 127;
9734                                 goto bail;
9735                         }
9736
9737                         /* implement bltin and command here */
9738                         if (cmdentry.cmdtype != CMDBUILTIN)
9739                                 break;
9740                         if (spclbltin < 0)
9741                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9742                         if (cmdentry.u.cmd == EXECCMD)
9743                                 cmd_is_exec = 1;
9744 #if ENABLE_ASH_CMDCMD
9745                         if (cmdentry.u.cmd == COMMANDCMD) {
9746                                 path = oldpath;
9747                                 nargv = parse_command_args(argv, &path);
9748                                 if (!nargv)
9749                                         break;
9750                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9751                                  * nargv => "PROG". path is updated if -p.
9752                                  */
9753                                 argc -= nargv - argv;
9754                                 argv = nargv;
9755                                 cmd_flag |= DO_NOFUNC;
9756                         } else
9757 #endif
9758                                 break;
9759                 }
9760         }
9761
9762         if (status) {
9763  bail:
9764                 exitstatus = status;
9765
9766                 /* We have a redirection error. */
9767                 if (spclbltin > 0)
9768                         raise_exception(EXERROR);
9769
9770                 goto out;
9771         }
9772
9773         /* Execute the command. */
9774         switch (cmdentry.cmdtype) {
9775         default: {
9776
9777 #if ENABLE_FEATURE_SH_NOFORK
9778 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9779  *     around run_nofork_applet() call.
9780  * (2) Should this check also be done in forkshell()?
9781  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9782  */
9783                 /* find_command() encodes applet_no as (-2 - applet_no) */
9784                 int applet_no = (- cmdentry.u.index - 2);
9785                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9786                         listsetvar(varlist.list, VEXPORT|VSTACK);
9787                         /* run <applet>_main() */
9788                         status = run_nofork_applet(applet_no, argv);
9789                         break;
9790                 }
9791 #endif
9792                 /* Can we avoid forking off? For example, very last command
9793                  * in a script or a subshell does not need forking,
9794                  * we can just exec it.
9795                  */
9796                 if (!(flags & EV_EXIT) || may_have_traps) {
9797                         /* No, forking off a child is necessary */
9798                         INT_OFF;
9799                         get_tty_state();
9800                         jp = makejob(/*cmd,*/ 1);
9801                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9802                                 /* parent */
9803                                 status = waitforjob(jp);
9804                                 INT_ON;
9805                                 TRACE(("forked child exited with %d\n", status));
9806                                 break;
9807                         }
9808                         /* child */
9809                         FORCE_INT_ON;
9810                         /* fall through to exec'ing external program */
9811                 }
9812                 listsetvar(varlist.list, VEXPORT|VSTACK);
9813                 shellexec(argv[0], argv, path, cmdentry.u.index);
9814                 /* NOTREACHED */
9815         } /* default */
9816         case CMDBUILTIN:
9817                 cmdenviron = varlist.list;
9818                 if (cmdenviron) {
9819                         struct strlist *list = cmdenviron;
9820                         int i = VNOSET;
9821                         if (spclbltin > 0 || argc == 0) {
9822                                 i = 0;
9823                                 if (cmd_is_exec && argc > 1)
9824                                         i = VEXPORT;
9825                         }
9826                         listsetvar(list, i);
9827                 }
9828                 /* Tight loop with builtins only:
9829                  * "while kill -0 $child; do true; done"
9830                  * will never exit even if $child died, unless we do this
9831                  * to reap the zombie and make kill detect that it's gone: */
9832                 dowait(DOWAIT_NONBLOCK, NULL);
9833
9834                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9835                         if (exception_type == EXERROR && spclbltin <= 0) {
9836                                 FORCE_INT_ON;
9837                                 goto readstatus;
9838                         }
9839  raise:
9840                         longjmp(exception_handler->loc, 1);
9841                 }
9842                 goto readstatus;
9843
9844         case CMDFUNCTION:
9845                 listsetvar(varlist.list, 0);
9846                 /* See above for the rationale */
9847                 dowait(DOWAIT_NONBLOCK, NULL);
9848                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9849                         goto raise;
9850  readstatus:
9851                 status = exitstatus;
9852                 break;
9853         } /* switch */
9854
9855  out:
9856         if (cmd->ncmd.redirect)
9857                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9858         if (lastarg) {
9859                 /* dsl: I think this is intended to be used to support
9860                  * '_' in 'vi' command mode during line editing...
9861                  * However I implemented that within libedit itself.
9862                  */
9863                 setvar0("_", lastarg);
9864         }
9865         popstackmark(&smark);
9866
9867         return status;
9868 }
9869
9870 static int
9871 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9872 {
9873         char *volatile savecmdname;
9874         struct jmploc *volatile savehandler;
9875         struct jmploc jmploc;
9876         int status;
9877         int i;
9878
9879         savecmdname = commandname;
9880         savehandler = exception_handler;
9881         i = setjmp(jmploc.loc);
9882         if (i)
9883                 goto cmddone;
9884         exception_handler = &jmploc;
9885         commandname = argv[0];
9886         argptr = argv + 1;
9887         optptr = NULL;                  /* initialize nextopt */
9888         if (cmd == EVALCMD)
9889                 status = evalcmd(argc, argv, flags);
9890         else
9891                 status = (*cmd->builtin)(argc, argv);
9892         flush_stdout_stderr();
9893         status |= ferror(stdout);
9894         exitstatus = status;
9895  cmddone:
9896         clearerr(stdout);
9897         commandname = savecmdname;
9898         exception_handler = savehandler;
9899
9900         return i;
9901 }
9902
9903 static int
9904 goodname(const char *p)
9905 {
9906         return endofname(p)[0] == '\0';
9907 }
9908
9909
9910 /*
9911  * Search for a command.  This is called before we fork so that the
9912  * location of the command will be available in the parent as well as
9913  * the child.  The check for "goodname" is an overly conservative
9914  * check that the name will not be subject to expansion.
9915  */
9916 static void
9917 prehash(union node *n)
9918 {
9919         struct cmdentry entry;
9920
9921         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9922                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9923 }
9924
9925
9926 /* ============ Builtin commands
9927  *
9928  * Builtin commands whose functions are closely tied to evaluation
9929  * are implemented here.
9930  */
9931
9932 /*
9933  * Handle break and continue commands.  Break, continue, and return are
9934  * all handled by setting the evalskip flag.  The evaluation routines
9935  * above all check this flag, and if it is set they start skipping
9936  * commands rather than executing them.  The variable skipcount is
9937  * the number of loops to break/continue, or the number of function
9938  * levels to return.  (The latter is always 1.)  It should probably
9939  * be an error to break out of more loops than exist, but it isn't
9940  * in the standard shell so we don't make it one here.
9941  */
9942 static int FAST_FUNC
9943 breakcmd(int argc UNUSED_PARAM, char **argv)
9944 {
9945         int n = argv[1] ? number(argv[1]) : 1;
9946
9947         if (n <= 0)
9948                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9949         if (n > loopnest)
9950                 n = loopnest;
9951         if (n > 0) {
9952                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9953                 skipcount = n;
9954         }
9955         return 0;
9956 }
9957
9958
9959 /*
9960  * This implements the input routines used by the parser.
9961  */
9962
9963 enum {
9964         INPUT_PUSH_FILE = 1,
9965         INPUT_NOFILE_OK = 2,
9966 };
9967
9968 static smallint checkkwd;
9969 /* values of checkkwd variable */
9970 #define CHKALIAS        0x1
9971 #define CHKKWD          0x2
9972 #define CHKNL           0x4
9973
9974 /*
9975  * Push a string back onto the input at this current parsefile level.
9976  * We handle aliases this way.
9977  */
9978 #if !ENABLE_ASH_ALIAS
9979 #define pushstring(s, ap) pushstring(s)
9980 #endif
9981 static void
9982 pushstring(char *s, struct alias *ap)
9983 {
9984         struct strpush *sp;
9985         int len;
9986
9987         len = strlen(s);
9988         INT_OFF;
9989         if (g_parsefile->strpush) {
9990                 sp = ckzalloc(sizeof(*sp));
9991                 sp->prev = g_parsefile->strpush;
9992         } else {
9993                 sp = &(g_parsefile->basestrpush);
9994         }
9995         g_parsefile->strpush = sp;
9996         sp->prev_string = g_parsefile->next_to_pgetc;
9997         sp->prev_left_in_line = g_parsefile->left_in_line;
9998         sp->unget = g_parsefile->unget;
9999         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10000 #if ENABLE_ASH_ALIAS
10001         sp->ap = ap;
10002         if (ap) {
10003                 ap->flag |= ALIASINUSE;
10004                 sp->string = s;
10005         }
10006 #endif
10007         g_parsefile->next_to_pgetc = s;
10008         g_parsefile->left_in_line = len;
10009         g_parsefile->unget = 0;
10010         INT_ON;
10011 }
10012
10013 static void
10014 popstring(void)
10015 {
10016         struct strpush *sp = g_parsefile->strpush;
10017
10018         INT_OFF;
10019 #if ENABLE_ASH_ALIAS
10020         if (sp->ap) {
10021                 if (g_parsefile->next_to_pgetc[-1] == ' '
10022                  || g_parsefile->next_to_pgetc[-1] == '\t'
10023                 ) {
10024                         checkkwd |= CHKALIAS;
10025                 }
10026                 if (sp->string != sp->ap->val) {
10027                         free(sp->string);
10028                 }
10029                 sp->ap->flag &= ~ALIASINUSE;
10030                 if (sp->ap->flag & ALIASDEAD) {
10031                         unalias(sp->ap->name);
10032                 }
10033         }
10034 #endif
10035         g_parsefile->next_to_pgetc = sp->prev_string;
10036         g_parsefile->left_in_line = sp->prev_left_in_line;
10037         g_parsefile->unget = sp->unget;
10038         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10039         g_parsefile->strpush = sp->prev;
10040         if (sp != &(g_parsefile->basestrpush))
10041                 free(sp);
10042         INT_ON;
10043 }
10044
10045 static int
10046 preadfd(void)
10047 {
10048         int nr;
10049         char *buf = g_parsefile->buf;
10050
10051         g_parsefile->next_to_pgetc = buf;
10052 #if ENABLE_FEATURE_EDITING
10053  retry:
10054         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10055                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10056         else {
10057                 int timeout = -1;
10058 # if ENABLE_ASH_IDLE_TIMEOUT
10059                 if (iflag) {
10060                         const char *tmout_var = lookupvar("TMOUT");
10061                         if (tmout_var) {
10062                                 timeout = atoi(tmout_var) * 1000;
10063                                 if (timeout <= 0)
10064                                         timeout = -1;
10065                         }
10066                 }
10067 # endif
10068 # if ENABLE_FEATURE_TAB_COMPLETION
10069                 line_input_state->path_lookup = pathval();
10070 # endif
10071                 reinit_unicode_for_ash();
10072                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10073                 if (nr == 0) {
10074                         /* ^C pressed, "convert" to SIGINT */
10075                         write(STDOUT_FILENO, "^C", 2);
10076                         if (trap[SIGINT]) {
10077                                 buf[0] = '\n';
10078                                 buf[1] = '\0';
10079                                 raise(SIGINT);
10080                                 return 1;
10081                         }
10082                         exitstatus = 128 + SIGINT;
10083                         bb_putchar('\n');
10084                         goto retry;
10085                 }
10086                 if (nr < 0) {
10087                         if (errno == 0) {
10088                                 /* Ctrl+D pressed */
10089                                 nr = 0;
10090                         }
10091 # if ENABLE_ASH_IDLE_TIMEOUT
10092                         else if (errno == EAGAIN && timeout > 0) {
10093                                 puts("\007timed out waiting for input: auto-logout");
10094                                 exitshell();
10095                         }
10096 # endif
10097                 }
10098         }
10099 #else
10100         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10101 #endif
10102
10103 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10104         if (nr < 0) {
10105                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10106                         int flags = fcntl(0, F_GETFL);
10107                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10108                                 flags &= ~O_NONBLOCK;
10109                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10110                                         out2str("sh: turning off NDELAY mode\n");
10111                                         goto retry;
10112                                 }
10113                         }
10114                 }
10115         }
10116 #endif
10117         return nr;
10118 }
10119
10120 /*
10121  * Refill the input buffer and return the next input character:
10122  *
10123  * 1) If a string was pushed back on the input, pop it;
10124  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10125  *    or we are reading from a string so we can't refill the buffer,
10126  *    return EOF.
10127  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10128  * 4) Process input up to the next newline, deleting nul characters.
10129  */
10130 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10131 #define pgetc_debug(...) ((void)0)
10132 static int pgetc(void);
10133 static int
10134 preadbuffer(void)
10135 {
10136         char *q;
10137         int more;
10138
10139         if (g_parsefile->strpush) {
10140 #if ENABLE_ASH_ALIAS
10141                 if (g_parsefile->left_in_line == -1
10142                  && g_parsefile->strpush->ap
10143                  && g_parsefile->next_to_pgetc[-1] != ' '
10144                  && g_parsefile->next_to_pgetc[-1] != '\t'
10145                 ) {
10146                         pgetc_debug("preadbuffer PEOA");
10147                         return PEOA;
10148                 }
10149 #endif
10150                 popstring();
10151                 return pgetc();
10152         }
10153         /* on both branches above g_parsefile->left_in_line < 0.
10154          * "pgetc" needs refilling.
10155          */
10156
10157         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10158          * pungetc() may increment it a few times.
10159          * Assuming it won't increment it to less than -90.
10160          */
10161         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10162                 pgetc_debug("preadbuffer PEOF1");
10163                 /* even in failure keep left_in_line and next_to_pgetc
10164                  * in lock step, for correct multi-layer pungetc.
10165                  * left_in_line was decremented before preadbuffer(),
10166                  * must inc next_to_pgetc: */
10167                 g_parsefile->next_to_pgetc++;
10168                 return PEOF;
10169         }
10170
10171         more = g_parsefile->left_in_buffer;
10172         if (more <= 0) {
10173                 flush_stdout_stderr();
10174  again:
10175                 more = preadfd();
10176                 if (more <= 0) {
10177                         /* don't try reading again */
10178                         g_parsefile->left_in_line = -99;
10179                         pgetc_debug("preadbuffer PEOF2");
10180                         g_parsefile->next_to_pgetc++;
10181                         return PEOF;
10182                 }
10183         }
10184
10185         /* Find out where's the end of line.
10186          * Set g_parsefile->left_in_line
10187          * and g_parsefile->left_in_buffer acordingly.
10188          * NUL chars are deleted.
10189          */
10190         q = g_parsefile->next_to_pgetc;
10191         for (;;) {
10192                 char c;
10193
10194                 more--;
10195
10196                 c = *q;
10197                 if (c == '\0') {
10198                         memmove(q, q + 1, more);
10199                 } else {
10200                         q++;
10201                         if (c == '\n') {
10202                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10203                                 break;
10204                         }
10205                 }
10206
10207                 if (more <= 0) {
10208                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10209                         if (g_parsefile->left_in_line < 0)
10210                                 goto again;
10211                         break;
10212                 }
10213         }
10214         g_parsefile->left_in_buffer = more;
10215
10216         if (vflag) {
10217                 char save = *q;
10218                 *q = '\0';
10219                 out2str(g_parsefile->next_to_pgetc);
10220                 *q = save;
10221         }
10222
10223         pgetc_debug("preadbuffer at %d:%p'%s'",
10224                         g_parsefile->left_in_line,
10225                         g_parsefile->next_to_pgetc,
10226                         g_parsefile->next_to_pgetc);
10227         return (unsigned char)*g_parsefile->next_to_pgetc++;
10228 }
10229
10230 static void
10231 nlprompt(void)
10232 {
10233         g_parsefile->linno++;
10234         setprompt_if(doprompt, 2);
10235 }
10236 static void
10237 nlnoprompt(void)
10238 {
10239         g_parsefile->linno++;
10240         needprompt = doprompt;
10241 }
10242
10243 static int
10244 pgetc(void)
10245 {
10246         int c;
10247
10248         pgetc_debug("pgetc at %d:%p'%s'",
10249                         g_parsefile->left_in_line,
10250                         g_parsefile->next_to_pgetc,
10251                         g_parsefile->next_to_pgetc);
10252         if (g_parsefile->unget)
10253                 return g_parsefile->lastc[--g_parsefile->unget];
10254
10255         if (--g_parsefile->left_in_line >= 0)
10256                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10257         else
10258                 c = preadbuffer();
10259
10260         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10261         g_parsefile->lastc[0] = c;
10262
10263         return c;
10264 }
10265
10266 #if ENABLE_ASH_ALIAS
10267 static int
10268 pgetc_without_PEOA(void)
10269 {
10270         int c;
10271         do {
10272                 pgetc_debug("pgetc at %d:%p'%s'",
10273                                 g_parsefile->left_in_line,
10274                                 g_parsefile->next_to_pgetc,
10275                                 g_parsefile->next_to_pgetc);
10276                 c = pgetc();
10277         } while (c == PEOA);
10278         return c;
10279 }
10280 #else
10281 # define pgetc_without_PEOA() pgetc()
10282 #endif
10283
10284 /*
10285  * Read a line from the script.
10286  */
10287 static char *
10288 pfgets(char *line, int len)
10289 {
10290         char *p = line;
10291         int nleft = len;
10292         int c;
10293
10294         while (--nleft > 0) {
10295                 c = pgetc_without_PEOA();
10296                 if (c == PEOF) {
10297                         if (p == line)
10298                                 return NULL;
10299                         break;
10300                 }
10301                 *p++ = c;
10302                 if (c == '\n')
10303                         break;
10304         }
10305         *p = '\0';
10306         return line;
10307 }
10308
10309 /*
10310  * Undo a call to pgetc.  Only two characters may be pushed back.
10311  * PEOF may be pushed back.
10312  */
10313 static void
10314 pungetc(void)
10315 {
10316         g_parsefile->unget++;
10317 }
10318
10319 /* This one eats backslash+newline */
10320 static int
10321 pgetc_eatbnl(void)
10322 {
10323         int c;
10324
10325         while ((c = pgetc()) == '\\') {
10326                 if (pgetc() != '\n') {
10327                         pungetc();
10328                         break;
10329                 }
10330
10331                 nlprompt();
10332         }
10333
10334         return c;
10335 }
10336
10337 /*
10338  * To handle the "." command, a stack of input files is used.  Pushfile
10339  * adds a new entry to the stack and popfile restores the previous level.
10340  */
10341 static void
10342 pushfile(void)
10343 {
10344         struct parsefile *pf;
10345
10346         pf = ckzalloc(sizeof(*pf));
10347         pf->prev = g_parsefile;
10348         pf->pf_fd = -1;
10349         /*pf->strpush = NULL; - ckzalloc did it */
10350         /*pf->basestrpush.prev = NULL;*/
10351         /*pf->unget = 0;*/
10352         g_parsefile = pf;
10353 }
10354
10355 static void
10356 popfile(void)
10357 {
10358         struct parsefile *pf = g_parsefile;
10359
10360         if (pf == &basepf)
10361                 return;
10362
10363         INT_OFF;
10364         if (pf->pf_fd >= 0)
10365                 close(pf->pf_fd);
10366         free(pf->buf);
10367         while (pf->strpush)
10368                 popstring();
10369         g_parsefile = pf->prev;
10370         free(pf);
10371         INT_ON;
10372 }
10373
10374 /*
10375  * Return to top level.
10376  */
10377 static void
10378 popallfiles(void)
10379 {
10380         while (g_parsefile != &basepf)
10381                 popfile();
10382 }
10383
10384 /*
10385  * Close the file(s) that the shell is reading commands from.  Called
10386  * after a fork is done.
10387  */
10388 static void
10389 closescript(void)
10390 {
10391         popallfiles();
10392         if (g_parsefile->pf_fd > 0) {
10393                 close(g_parsefile->pf_fd);
10394                 g_parsefile->pf_fd = 0;
10395         }
10396 }
10397
10398 /*
10399  * Like setinputfile, but takes an open file descriptor.  Call this with
10400  * interrupts off.
10401  */
10402 static void
10403 setinputfd(int fd, int push)
10404 {
10405         if (push) {
10406                 pushfile();
10407                 g_parsefile->buf = NULL;
10408         }
10409         g_parsefile->pf_fd = fd;
10410         if (g_parsefile->buf == NULL)
10411                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10412         g_parsefile->left_in_buffer = 0;
10413         g_parsefile->left_in_line = 0;
10414         g_parsefile->linno = 1;
10415 }
10416
10417 /*
10418  * Set the input to take input from a file.  If push is set, push the
10419  * old input onto the stack first.
10420  */
10421 static int
10422 setinputfile(const char *fname, int flags)
10423 {
10424         int fd;
10425
10426         INT_OFF;
10427         fd = open(fname, O_RDONLY);
10428         if (fd < 0) {
10429                 if (flags & INPUT_NOFILE_OK)
10430                         goto out;
10431                 exitstatus = 127;
10432                 ash_msg_and_raise_error("can't open '%s'", fname);
10433         }
10434         if (fd < 10)
10435                 fd = savefd(fd);
10436         else
10437                 close_on_exec_on(fd);
10438         setinputfd(fd, flags & INPUT_PUSH_FILE);
10439  out:
10440         INT_ON;
10441         return fd;
10442 }
10443
10444 /*
10445  * Like setinputfile, but takes input from a string.
10446  */
10447 static void
10448 setinputstring(char *string)
10449 {
10450         INT_OFF;
10451         pushfile();
10452         g_parsefile->next_to_pgetc = string;
10453         g_parsefile->left_in_line = strlen(string);
10454         g_parsefile->buf = NULL;
10455         g_parsefile->linno = 1;
10456         INT_ON;
10457 }
10458
10459
10460 /*
10461  * Routines to check for mail.
10462  */
10463
10464 #if ENABLE_ASH_MAIL
10465
10466 /* Hash of mtimes of mailboxes */
10467 static unsigned mailtime_hash;
10468 /* Set if MAIL or MAILPATH is changed. */
10469 static smallint mail_var_path_changed;
10470
10471 /*
10472  * Print appropriate message(s) if mail has arrived.
10473  * If mail_var_path_changed is set,
10474  * then the value of MAIL has mail_var_path_changed,
10475  * so we just update the values.
10476  */
10477 static void
10478 chkmail(void)
10479 {
10480         const char *mpath;
10481         char *p;
10482         char *q;
10483         unsigned new_hash;
10484         struct stackmark smark;
10485         struct stat statb;
10486
10487         setstackmark(&smark);
10488         mpath = mpathset() ? mpathval() : mailval();
10489         new_hash = 0;
10490         for (;;) {
10491                 p = path_advance(&mpath, nullstr);
10492                 if (p == NULL)
10493                         break;
10494                 if (*p == '\0')
10495                         continue;
10496                 for (q = p; *q; q++)
10497                         continue;
10498 #if DEBUG
10499                 if (q[-1] != '/')
10500                         abort();
10501 #endif
10502                 q[-1] = '\0';                   /* delete trailing '/' */
10503                 if (stat(p, &statb) < 0) {
10504                         continue;
10505                 }
10506                 /* Very simplistic "hash": just a sum of all mtimes */
10507                 new_hash += (unsigned)statb.st_mtime;
10508         }
10509         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10510                 if (mailtime_hash != 0)
10511                         out2str("you have mail\n");
10512                 mailtime_hash = new_hash;
10513         }
10514         mail_var_path_changed = 0;
10515         popstackmark(&smark);
10516 }
10517
10518 static void FAST_FUNC
10519 changemail(const char *val UNUSED_PARAM)
10520 {
10521         mail_var_path_changed = 1;
10522 }
10523
10524 #endif /* ASH_MAIL */
10525
10526
10527 /* ============ ??? */
10528
10529 /*
10530  * Set the shell parameters.
10531  */
10532 static void
10533 setparam(char **argv)
10534 {
10535         char **newparam;
10536         char **ap;
10537         int nparam;
10538
10539         for (nparam = 0; argv[nparam]; nparam++)
10540                 continue;
10541         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10542         while (*argv) {
10543                 *ap++ = ckstrdup(*argv++);
10544         }
10545         *ap = NULL;
10546         freeparam(&shellparam);
10547         shellparam.malloced = 1;
10548         shellparam.nparam = nparam;
10549         shellparam.p = newparam;
10550 #if ENABLE_ASH_GETOPTS
10551         shellparam.optind = 1;
10552         shellparam.optoff = -1;
10553 #endif
10554 }
10555
10556 /*
10557  * Process shell options.  The global variable argptr contains a pointer
10558  * to the argument list; we advance it past the options.
10559  *
10560  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10561  * For a non-interactive shell, an error condition encountered
10562  * by a special built-in ... shall cause the shell to write a diagnostic message
10563  * to standard error and exit as shown in the following table:
10564  * Error                                           Special Built-In
10565  * ...
10566  * Utility syntax error (option or operand error)  Shall exit
10567  * ...
10568  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10569  * we see that bash does not do that (set "finishes" with error code 1 instead,
10570  * and shell continues), and people rely on this behavior!
10571  * Testcase:
10572  * set -o barfoo 2>/dev/null
10573  * echo $?
10574  *
10575  * Oh well. Let's mimic that.
10576  */
10577 static int
10578 plus_minus_o(char *name, int val)
10579 {
10580         int i;
10581
10582         if (name) {
10583                 for (i = 0; i < NOPTS; i++) {
10584                         if (strcmp(name, optnames(i)) == 0) {
10585                                 optlist[i] = val;
10586                                 return 0;
10587                         }
10588                 }
10589                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10590                 return 1;
10591         }
10592         for (i = 0; i < NOPTS; i++) {
10593                 if (val) {
10594                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10595                 } else {
10596                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10597                 }
10598         }
10599         return 0;
10600 }
10601 static void
10602 setoption(int flag, int val)
10603 {
10604         int i;
10605
10606         for (i = 0; i < NOPTS; i++) {
10607                 if (optletters(i) == flag) {
10608                         optlist[i] = val;
10609                         return;
10610                 }
10611         }
10612         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10613         /* NOTREACHED */
10614 }
10615 static int
10616 options(int cmdline)
10617 {
10618         char *p;
10619         int val;
10620         int c;
10621
10622         if (cmdline)
10623                 minusc = NULL;
10624         while ((p = *argptr) != NULL) {
10625                 c = *p++;
10626                 if (c != '-' && c != '+')
10627                         break;
10628                 argptr++;
10629                 val = 0; /* val = 0 if c == '+' */
10630                 if (c == '-') {
10631                         val = 1;
10632                         if (p[0] == '\0' || LONE_DASH(p)) {
10633                                 if (!cmdline) {
10634                                         /* "-" means turn off -x and -v */
10635                                         if (p[0] == '\0')
10636                                                 xflag = vflag = 0;
10637                                         /* "--" means reset params */
10638                                         else if (*argptr == NULL)
10639                                                 setparam(argptr);
10640                                 }
10641                                 break;    /* "-" or "--" terminates options */
10642                         }
10643                 }
10644                 /* first char was + or - */
10645                 while ((c = *p++) != '\0') {
10646                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10647                         if (c == 'c' && cmdline) {
10648                                 minusc = p;     /* command is after shell args */
10649                         } else if (c == 'o') {
10650                                 if (plus_minus_o(*argptr, val)) {
10651                                         /* it already printed err message */
10652                                         return 1; /* error */
10653                                 }
10654                                 if (*argptr)
10655                                         argptr++;
10656                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10657                                 isloginsh = 1;
10658                         /* bash does not accept +-login, we also won't */
10659                         } else if (cmdline && val && (c == '-')) { /* long options */
10660                                 if (strcmp(p, "login") == 0)
10661                                         isloginsh = 1;
10662                                 break;
10663                         } else {
10664                                 setoption(c, val);
10665                         }
10666                 }
10667         }
10668         return 0;
10669 }
10670
10671 /*
10672  * The shift builtin command.
10673  */
10674 static int FAST_FUNC
10675 shiftcmd(int argc UNUSED_PARAM, char **argv)
10676 {
10677         int n;
10678         char **ap1, **ap2;
10679
10680         n = 1;
10681         if (argv[1])
10682                 n = number(argv[1]);
10683         if (n > shellparam.nparam)
10684                 n = 0; /* bash compat, was = shellparam.nparam; */
10685         INT_OFF;
10686         shellparam.nparam -= n;
10687         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10688                 if (shellparam.malloced)
10689                         free(*ap1);
10690         }
10691         ap2 = shellparam.p;
10692         while ((*ap2++ = *ap1++) != NULL)
10693                 continue;
10694 #if ENABLE_ASH_GETOPTS
10695         shellparam.optind = 1;
10696         shellparam.optoff = -1;
10697 #endif
10698         INT_ON;
10699         return 0;
10700 }
10701
10702 /*
10703  * POSIX requires that 'set' (but not export or readonly) output the
10704  * variables in lexicographic order - by the locale's collating order (sigh).
10705  * Maybe we could keep them in an ordered balanced binary tree
10706  * instead of hashed lists.
10707  * For now just roll 'em through qsort for printing...
10708  */
10709 static int
10710 showvars(const char *sep_prefix, int on, int off)
10711 {
10712         const char *sep;
10713         char **ep, **epend;
10714
10715         ep = listvars(on, off, &epend);
10716         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10717
10718         sep = *sep_prefix ? " " : sep_prefix;
10719
10720         for (; ep < epend; ep++) {
10721                 const char *p;
10722                 const char *q;
10723
10724                 p = strchrnul(*ep, '=');
10725                 q = nullstr;
10726                 if (*p)
10727                         q = single_quote(++p);
10728                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10729         }
10730         return 0;
10731 }
10732
10733 /*
10734  * The set command builtin.
10735  */
10736 static int FAST_FUNC
10737 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10738 {
10739         int retval;
10740
10741         if (!argv[1])
10742                 return showvars(nullstr, 0, VUNSET);
10743
10744         INT_OFF;
10745         retval = options(/*cmdline:*/ 0);
10746         if (retval == 0) { /* if no parse error... */
10747                 optschanged();
10748                 if (*argptr != NULL) {
10749                         setparam(argptr);
10750                 }
10751         }
10752         INT_ON;
10753         return retval;
10754 }
10755
10756 #if ENABLE_ASH_RANDOM_SUPPORT
10757 static void FAST_FUNC
10758 change_random(const char *value)
10759 {
10760         uint32_t t;
10761
10762         if (value == NULL) {
10763                 /* "get", generate */
10764                 t = next_random(&random_gen);
10765                 /* set without recursion */
10766                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10767                 vrandom.flags &= ~VNOFUNC;
10768         } else {
10769                 /* set/reset */
10770                 t = strtoul(value, NULL, 10);
10771                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10772         }
10773 }
10774 #endif
10775
10776 #if ENABLE_ASH_GETOPTS
10777 static int
10778 getopts(char *optstr, char *optvar, char **optfirst)
10779 {
10780         char *p, *q;
10781         char c = '?';
10782         int done = 0;
10783         char sbuf[2];
10784         char **optnext;
10785         int ind = shellparam.optind;
10786         int off = shellparam.optoff;
10787
10788         sbuf[1] = '\0';
10789
10790         shellparam.optind = -1;
10791         optnext = optfirst + ind - 1;
10792
10793         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10794                 p = NULL;
10795         else
10796                 p = optnext[-1] + off;
10797         if (p == NULL || *p == '\0') {
10798                 /* Current word is done, advance */
10799                 p = *optnext;
10800                 if (p == NULL || *p != '-' || *++p == '\0') {
10801  atend:
10802                         p = NULL;
10803                         done = 1;
10804                         goto out;
10805                 }
10806                 optnext++;
10807                 if (LONE_DASH(p))        /* check for "--" */
10808                         goto atend;
10809         }
10810
10811         c = *p++;
10812         for (q = optstr; *q != c;) {
10813                 if (*q == '\0') {
10814                         if (optstr[0] == ':') {
10815                                 sbuf[0] = c;
10816                                 /*sbuf[1] = '\0'; - already is */
10817                                 setvar0("OPTARG", sbuf);
10818                         } else {
10819                                 fprintf(stderr, "Illegal option -%c\n", c);
10820                                 unsetvar("OPTARG");
10821                         }
10822                         c = '?';
10823                         goto out;
10824                 }
10825                 if (*++q == ':')
10826                         q++;
10827         }
10828
10829         if (*++q == ':') {
10830                 if (*p == '\0' && (p = *optnext) == NULL) {
10831                         if (optstr[0] == ':') {
10832                                 sbuf[0] = c;
10833                                 /*sbuf[1] = '\0'; - already is */
10834                                 setvar0("OPTARG", sbuf);
10835                                 c = ':';
10836                         } else {
10837                                 fprintf(stderr, "No arg for -%c option\n", c);
10838                                 unsetvar("OPTARG");
10839                                 c = '?';
10840                         }
10841                         goto out;
10842                 }
10843
10844                 if (p == *optnext)
10845                         optnext++;
10846                 setvar0("OPTARG", p);
10847                 p = NULL;
10848         } else
10849                 setvar0("OPTARG", nullstr);
10850  out:
10851         ind = optnext - optfirst + 1;
10852         setvar("OPTIND", itoa(ind), VNOFUNC);
10853         sbuf[0] = c;
10854         /*sbuf[1] = '\0'; - already is */
10855         setvar0(optvar, sbuf);
10856
10857         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10858         shellparam.optind = ind;
10859
10860         return done;
10861 }
10862
10863 /*
10864  * The getopts builtin.  Shellparam.optnext points to the next argument
10865  * to be processed.  Shellparam.optptr points to the next character to
10866  * be processed in the current argument.  If shellparam.optnext is NULL,
10867  * then it's the first time getopts has been called.
10868  */
10869 static int FAST_FUNC
10870 getoptscmd(int argc, char **argv)
10871 {
10872         char **optbase;
10873
10874         if (argc < 3)
10875                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10876         if (argc == 3) {
10877                 optbase = shellparam.p;
10878                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10879                         shellparam.optind = 1;
10880                         shellparam.optoff = -1;
10881                 }
10882         } else {
10883                 optbase = &argv[3];
10884                 if ((unsigned)shellparam.optind > argc - 2) {
10885                         shellparam.optind = 1;
10886                         shellparam.optoff = -1;
10887                 }
10888         }
10889
10890         return getopts(argv[1], argv[2], optbase);
10891 }
10892 #endif /* ASH_GETOPTS */
10893
10894
10895 /* ============ Shell parser */
10896
10897 struct heredoc {
10898         struct heredoc *next;   /* next here document in list */
10899         union node *here;       /* redirection node */
10900         char *eofmark;          /* string indicating end of input */
10901         smallint striptabs;     /* if set, strip leading tabs */
10902 };
10903
10904 static smallint tokpushback;           /* last token pushed back */
10905 static smallint quoteflag;             /* set if (part of) last token was quoted */
10906 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10907 static struct heredoc *heredoclist;    /* list of here documents to read */
10908 static char *wordtext;                 /* text of last word returned by readtoken */
10909 static struct nodelist *backquotelist;
10910 static union node *redirnode;
10911 static struct heredoc *heredoc;
10912
10913 static const char *
10914 tokname(char *buf, int tok)
10915 {
10916         if (tok < TSEMI)
10917                 return tokname_array[tok];
10918         sprintf(buf, "\"%s\"", tokname_array[tok]);
10919         return buf;
10920 }
10921
10922 /* raise_error_unexpected_syntax:
10923  * Called when an unexpected token is read during the parse.  The argument
10924  * is the token that is expected, or -1 if more than one type of token can
10925  * occur at this point.
10926  */
10927 static void raise_error_unexpected_syntax(int) NORETURN;
10928 static void
10929 raise_error_unexpected_syntax(int token)
10930 {
10931         char msg[64];
10932         char buf[16];
10933         int l;
10934
10935         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10936         if (token >= 0)
10937                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10938         raise_error_syntax(msg);
10939         /* NOTREACHED */
10940 }
10941
10942 #define EOFMARKLEN 79
10943
10944 /* parsing is heavily cross-recursive, need these forward decls */
10945 static union node *andor(void);
10946 static union node *pipeline(void);
10947 static union node *parse_command(void);
10948 static void parseheredoc(void);
10949 static int peektoken(void);
10950 static int readtoken(void);
10951
10952 static union node *
10953 list(int nlflag)
10954 {
10955         union node *n1, *n2, *n3;
10956         int tok;
10957
10958         n1 = NULL;
10959         for (;;) {
10960                 switch (peektoken()) {
10961                 case TNL:
10962                         if (!(nlflag & 1))
10963                                 break;
10964                         parseheredoc();
10965                         return n1;
10966
10967                 case TEOF:
10968                         if (!n1 && (nlflag & 1))
10969                                 n1 = NODE_EOF;
10970                         parseheredoc();
10971                         return n1;
10972                 }
10973
10974                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10975                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10976                         return n1;
10977                 nlflag |= 2;
10978
10979                 n2 = andor();
10980                 tok = readtoken();
10981                 if (tok == TBACKGND) {
10982                         if (n2->type == NPIPE) {
10983                                 n2->npipe.pipe_backgnd = 1;
10984                         } else {
10985                                 if (n2->type != NREDIR) {
10986                                         n3 = stzalloc(sizeof(struct nredir));
10987                                         n3->nredir.n = n2;
10988                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10989                                         n2 = n3;
10990                                 }
10991                                 n2->type = NBACKGND;
10992                         }
10993                 }
10994                 if (n1 == NULL) {
10995                         n1 = n2;
10996                 } else {
10997                         n3 = stzalloc(sizeof(struct nbinary));
10998                         n3->type = NSEMI;
10999                         n3->nbinary.ch1 = n1;
11000                         n3->nbinary.ch2 = n2;
11001                         n1 = n3;
11002                 }
11003                 switch (tok) {
11004                 case TNL:
11005                 case TEOF:
11006                         tokpushback = 1;
11007                         /* fall through */
11008                 case TBACKGND:
11009                 case TSEMI:
11010                         break;
11011                 default:
11012                         if ((nlflag & 1))
11013                                 raise_error_unexpected_syntax(-1);
11014                         tokpushback = 1;
11015                         return n1;
11016                 }
11017         }
11018 }
11019
11020 static union node *
11021 andor(void)
11022 {
11023         union node *n1, *n2, *n3;
11024         int t;
11025
11026         n1 = pipeline();
11027         for (;;) {
11028                 t = readtoken();
11029                 if (t == TAND) {
11030                         t = NAND;
11031                 } else if (t == TOR) {
11032                         t = NOR;
11033                 } else {
11034                         tokpushback = 1;
11035                         return n1;
11036                 }
11037                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11038                 n2 = pipeline();
11039                 n3 = stzalloc(sizeof(struct nbinary));
11040                 n3->type = t;
11041                 n3->nbinary.ch1 = n1;
11042                 n3->nbinary.ch2 = n2;
11043                 n1 = n3;
11044         }
11045 }
11046
11047 static union node *
11048 pipeline(void)
11049 {
11050         union node *n1, *n2, *pipenode;
11051         struct nodelist *lp, *prev;
11052         int negate;
11053
11054         negate = 0;
11055         TRACE(("pipeline: entered\n"));
11056         if (readtoken() == TNOT) {
11057                 negate = !negate;
11058                 checkkwd = CHKKWD | CHKALIAS;
11059         } else
11060                 tokpushback = 1;
11061         n1 = parse_command();
11062         if (readtoken() == TPIPE) {
11063                 pipenode = stzalloc(sizeof(struct npipe));
11064                 pipenode->type = NPIPE;
11065                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11066                 lp = stzalloc(sizeof(struct nodelist));
11067                 pipenode->npipe.cmdlist = lp;
11068                 lp->n = n1;
11069                 do {
11070                         prev = lp;
11071                         lp = stzalloc(sizeof(struct nodelist));
11072                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11073                         lp->n = parse_command();
11074                         prev->next = lp;
11075                 } while (readtoken() == TPIPE);
11076                 lp->next = NULL;
11077                 n1 = pipenode;
11078         }
11079         tokpushback = 1;
11080         if (negate) {
11081                 n2 = stzalloc(sizeof(struct nnot));
11082                 n2->type = NNOT;
11083                 n2->nnot.com = n1;
11084                 return n2;
11085         }
11086         return n1;
11087 }
11088
11089 static union node *
11090 makename(void)
11091 {
11092         union node *n;
11093
11094         n = stzalloc(sizeof(struct narg));
11095         n->type = NARG;
11096         /*n->narg.next = NULL; - stzalloc did it */
11097         n->narg.text = wordtext;
11098         n->narg.backquote = backquotelist;
11099         return n;
11100 }
11101
11102 static void
11103 fixredir(union node *n, const char *text, int err)
11104 {
11105         int fd;
11106
11107         TRACE(("Fix redir %s %d\n", text, err));
11108         if (!err)
11109                 n->ndup.vname = NULL;
11110
11111         fd = bb_strtou(text, NULL, 10);
11112         if (!errno && fd >= 0)
11113                 n->ndup.dupfd = fd;
11114         else if (LONE_DASH(text))
11115                 n->ndup.dupfd = -1;
11116         else {
11117                 if (err)
11118                         raise_error_syntax("bad fd number");
11119                 n->ndup.vname = makename();
11120         }
11121 }
11122
11123 /*
11124  * Returns true if the text contains nothing to expand (no dollar signs
11125  * or backquotes).
11126  */
11127 static int
11128 noexpand(const char *text)
11129 {
11130         unsigned char c;
11131
11132         while ((c = *text++) != '\0') {
11133                 if (c == CTLQUOTEMARK)
11134                         continue;
11135                 if (c == CTLESC)
11136                         text++;
11137                 else if (SIT(c, BASESYNTAX) == CCTL)
11138                         return 0;
11139         }
11140         return 1;
11141 }
11142
11143 static void
11144 parsefname(void)
11145 {
11146         union node *n = redirnode;
11147
11148         if (readtoken() != TWORD)
11149                 raise_error_unexpected_syntax(-1);
11150         if (n->type == NHERE) {
11151                 struct heredoc *here = heredoc;
11152                 struct heredoc *p;
11153                 int i;
11154
11155                 if (quoteflag == 0)
11156                         n->type = NXHERE;
11157                 TRACE(("Here document %d\n", n->type));
11158                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11159                         raise_error_syntax("illegal eof marker for << redirection");
11160                 rmescapes(wordtext, 0);
11161                 here->eofmark = wordtext;
11162                 here->next = NULL;
11163                 if (heredoclist == NULL)
11164                         heredoclist = here;
11165                 else {
11166                         for (p = heredoclist; p->next; p = p->next)
11167                                 continue;
11168                         p->next = here;
11169                 }
11170         } else if (n->type == NTOFD || n->type == NFROMFD) {
11171                 fixredir(n, wordtext, 0);
11172         } else {
11173                 n->nfile.fname = makename();
11174         }
11175 }
11176
11177 static union node *
11178 simplecmd(void)
11179 {
11180         union node *args, **app;
11181         union node *n = NULL;
11182         union node *vars, **vpp;
11183         union node **rpp, *redir;
11184         int savecheckkwd;
11185 #if BASH_TEST2
11186         smallint double_brackets_flag = 0;
11187 #endif
11188         IF_BASH_FUNCTION(smallint function_flag = 0;)
11189
11190         args = NULL;
11191         app = &args;
11192         vars = NULL;
11193         vpp = &vars;
11194         redir = NULL;
11195         rpp = &redir;
11196
11197         savecheckkwd = CHKALIAS;
11198         for (;;) {
11199                 int t;
11200                 checkkwd = savecheckkwd;
11201                 t = readtoken();
11202                 switch (t) {
11203 #if BASH_FUNCTION
11204                 case TFUNCTION:
11205                         if (peektoken() != TWORD)
11206                                 raise_error_unexpected_syntax(TWORD);
11207                         function_flag = 1;
11208                         break;
11209 #endif
11210 #if BASH_TEST2
11211                 case TAND: /* "&&" */
11212                 case TOR: /* "||" */
11213                         if (!double_brackets_flag) {
11214                                 tokpushback = 1;
11215                                 goto out;
11216                         }
11217                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11218 #endif
11219                 case TWORD:
11220                         n = stzalloc(sizeof(struct narg));
11221                         n->type = NARG;
11222                         /*n->narg.next = NULL; - stzalloc did it */
11223                         n->narg.text = wordtext;
11224 #if BASH_TEST2
11225                         if (strcmp("[[", wordtext) == 0)
11226                                 double_brackets_flag = 1;
11227                         else if (strcmp("]]", wordtext) == 0)
11228                                 double_brackets_flag = 0;
11229 #endif
11230                         n->narg.backquote = backquotelist;
11231                         if (savecheckkwd && isassignment(wordtext)) {
11232                                 *vpp = n;
11233                                 vpp = &n->narg.next;
11234                         } else {
11235                                 *app = n;
11236                                 app = &n->narg.next;
11237                                 savecheckkwd = 0;
11238                         }
11239 #if BASH_FUNCTION
11240                         if (function_flag) {
11241                                 checkkwd = CHKNL | CHKKWD;
11242                                 switch (peektoken()) {
11243                                 case TBEGIN:
11244                                 case TIF:
11245                                 case TCASE:
11246                                 case TUNTIL:
11247                                 case TWHILE:
11248                                 case TFOR:
11249                                         goto do_func;
11250                                 case TLP:
11251                                         function_flag = 0;
11252                                         break;
11253                                 case TWORD:
11254                                         if (strcmp("[[", wordtext) == 0)
11255                                                 goto do_func;
11256                                         /* fall through */
11257                                 default:
11258                                         raise_error_unexpected_syntax(-1);
11259                                 }
11260                         }
11261 #endif
11262                         break;
11263                 case TREDIR:
11264                         *rpp = n = redirnode;
11265                         rpp = &n->nfile.next;
11266                         parsefname();   /* read name of redirection file */
11267                         break;
11268                 case TLP:
11269  IF_BASH_FUNCTION(do_func:)
11270                         if (args && app == &args->narg.next
11271                          && !vars && !redir
11272                         ) {
11273                                 struct builtincmd *bcmd;
11274                                 const char *name;
11275
11276                                 /* We have a function */
11277                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11278                                         raise_error_unexpected_syntax(TRP);
11279                                 name = n->narg.text;
11280                                 if (!goodname(name)
11281                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11282                                 ) {
11283                                         raise_error_syntax("bad function name");
11284                                 }
11285                                 n->type = NDEFUN;
11286                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11287                                 n->narg.next = parse_command();
11288                                 return n;
11289                         }
11290                         IF_BASH_FUNCTION(function_flag = 0;)
11291                         /* fall through */
11292                 default:
11293                         tokpushback = 1;
11294                         goto out;
11295                 }
11296         }
11297  out:
11298         *app = NULL;
11299         *vpp = NULL;
11300         *rpp = NULL;
11301         n = stzalloc(sizeof(struct ncmd));
11302         n->type = NCMD;
11303         n->ncmd.args = args;
11304         n->ncmd.assign = vars;
11305         n->ncmd.redirect = redir;
11306         return n;
11307 }
11308
11309 static union node *
11310 parse_command(void)
11311 {
11312         union node *n1, *n2;
11313         union node *ap, **app;
11314         union node *cp, **cpp;
11315         union node *redir, **rpp;
11316         union node **rpp2;
11317         int t;
11318
11319         redir = NULL;
11320         rpp2 = &redir;
11321
11322         switch (readtoken()) {
11323         default:
11324                 raise_error_unexpected_syntax(-1);
11325                 /* NOTREACHED */
11326         case TIF:
11327                 n1 = stzalloc(sizeof(struct nif));
11328                 n1->type = NIF;
11329                 n1->nif.test = list(0);
11330                 if (readtoken() != TTHEN)
11331                         raise_error_unexpected_syntax(TTHEN);
11332                 n1->nif.ifpart = list(0);
11333                 n2 = n1;
11334                 while (readtoken() == TELIF) {
11335                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11336                         n2 = n2->nif.elsepart;
11337                         n2->type = NIF;
11338                         n2->nif.test = list(0);
11339                         if (readtoken() != TTHEN)
11340                                 raise_error_unexpected_syntax(TTHEN);
11341                         n2->nif.ifpart = list(0);
11342                 }
11343                 if (lasttoken == TELSE)
11344                         n2->nif.elsepart = list(0);
11345                 else {
11346                         n2->nif.elsepart = NULL;
11347                         tokpushback = 1;
11348                 }
11349                 t = TFI;
11350                 break;
11351         case TWHILE:
11352         case TUNTIL: {
11353                 int got;
11354                 n1 = stzalloc(sizeof(struct nbinary));
11355                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11356                 n1->nbinary.ch1 = list(0);
11357                 got = readtoken();
11358                 if (got != TDO) {
11359                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11360                                         got == TWORD ? wordtext : ""));
11361                         raise_error_unexpected_syntax(TDO);
11362                 }
11363                 n1->nbinary.ch2 = list(0);
11364                 t = TDONE;
11365                 break;
11366         }
11367         case TFOR:
11368                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11369                         raise_error_syntax("bad for loop variable");
11370                 n1 = stzalloc(sizeof(struct nfor));
11371                 n1->type = NFOR;
11372                 n1->nfor.var = wordtext;
11373                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11374                 if (readtoken() == TIN) {
11375                         app = &ap;
11376                         while (readtoken() == TWORD) {
11377                                 n2 = stzalloc(sizeof(struct narg));
11378                                 n2->type = NARG;
11379                                 /*n2->narg.next = NULL; - stzalloc did it */
11380                                 n2->narg.text = wordtext;
11381                                 n2->narg.backquote = backquotelist;
11382                                 *app = n2;
11383                                 app = &n2->narg.next;
11384                         }
11385                         *app = NULL;
11386                         n1->nfor.args = ap;
11387                         if (lasttoken != TNL && lasttoken != TSEMI)
11388                                 raise_error_unexpected_syntax(-1);
11389                 } else {
11390                         n2 = stzalloc(sizeof(struct narg));
11391                         n2->type = NARG;
11392                         /*n2->narg.next = NULL; - stzalloc did it */
11393                         n2->narg.text = (char *)dolatstr;
11394                         /*n2->narg.backquote = NULL;*/
11395                         n1->nfor.args = n2;
11396                         /*
11397                          * Newline or semicolon here is optional (but note
11398                          * that the original Bourne shell only allowed NL).
11399                          */
11400                         if (lasttoken != TSEMI)
11401                                 tokpushback = 1;
11402                 }
11403                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11404                 if (readtoken() != TDO)
11405                         raise_error_unexpected_syntax(TDO);
11406                 n1->nfor.body = list(0);
11407                 t = TDONE;
11408                 break;
11409         case TCASE:
11410                 n1 = stzalloc(sizeof(struct ncase));
11411                 n1->type = NCASE;
11412                 if (readtoken() != TWORD)
11413                         raise_error_unexpected_syntax(TWORD);
11414                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11415                 n2->type = NARG;
11416                 /*n2->narg.next = NULL; - stzalloc did it */
11417                 n2->narg.text = wordtext;
11418                 n2->narg.backquote = backquotelist;
11419                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11420                 if (readtoken() != TIN)
11421                         raise_error_unexpected_syntax(TIN);
11422                 cpp = &n1->ncase.cases;
11423  next_case:
11424                 checkkwd = CHKNL | CHKKWD;
11425                 t = readtoken();
11426                 while (t != TESAC) {
11427                         if (lasttoken == TLP)
11428                                 readtoken();
11429                         *cpp = cp = stzalloc(sizeof(struct nclist));
11430                         cp->type = NCLIST;
11431                         app = &cp->nclist.pattern;
11432                         for (;;) {
11433                                 *app = ap = stzalloc(sizeof(struct narg));
11434                                 ap->type = NARG;
11435                                 /*ap->narg.next = NULL; - stzalloc did it */
11436                                 ap->narg.text = wordtext;
11437                                 ap->narg.backquote = backquotelist;
11438                                 if (readtoken() != TPIPE)
11439                                         break;
11440                                 app = &ap->narg.next;
11441                                 readtoken();
11442                         }
11443                         //ap->narg.next = NULL;
11444                         if (lasttoken != TRP)
11445                                 raise_error_unexpected_syntax(TRP);
11446                         cp->nclist.body = list(2);
11447
11448                         cpp = &cp->nclist.next;
11449
11450                         checkkwd = CHKNL | CHKKWD;
11451                         t = readtoken();
11452                         if (t != TESAC) {
11453                                 if (t != TENDCASE)
11454                                         raise_error_unexpected_syntax(TENDCASE);
11455                                 goto next_case;
11456                         }
11457                 }
11458                 *cpp = NULL;
11459                 goto redir;
11460         case TLP:
11461                 n1 = stzalloc(sizeof(struct nredir));
11462                 n1->type = NSUBSHELL;
11463                 n1->nredir.n = list(0);
11464                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11465                 t = TRP;
11466                 break;
11467         case TBEGIN:
11468                 n1 = list(0);
11469                 t = TEND;
11470                 break;
11471         IF_BASH_FUNCTION(case TFUNCTION:)
11472         case TWORD:
11473         case TREDIR:
11474                 tokpushback = 1;
11475                 return simplecmd();
11476         }
11477
11478         if (readtoken() != t)
11479                 raise_error_unexpected_syntax(t);
11480
11481  redir:
11482         /* Now check for redirection which may follow command */
11483         checkkwd = CHKKWD | CHKALIAS;
11484         rpp = rpp2;
11485         while (readtoken() == TREDIR) {
11486                 *rpp = n2 = redirnode;
11487                 rpp = &n2->nfile.next;
11488                 parsefname();
11489         }
11490         tokpushback = 1;
11491         *rpp = NULL;
11492         if (redir) {
11493                 if (n1->type != NSUBSHELL) {
11494                         n2 = stzalloc(sizeof(struct nredir));
11495                         n2->type = NREDIR;
11496                         n2->nredir.n = n1;
11497                         n1 = n2;
11498                 }
11499                 n1->nredir.redirect = redir;
11500         }
11501         return n1;
11502 }
11503
11504 #if BASH_DOLLAR_SQUOTE
11505 static int
11506 decode_dollar_squote(void)
11507 {
11508         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11509         int c, cnt;
11510         char *p;
11511         char buf[4];
11512
11513         c = pgetc();
11514         p = strchr(C_escapes, c);
11515         if (p) {
11516                 buf[0] = c;
11517                 p = buf;
11518                 cnt = 3;
11519                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11520                         do {
11521                                 c = pgetc();
11522                                 *++p = c;
11523                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11524                         pungetc();
11525                 } else if (c == 'x') { /* \xHH */
11526                         do {
11527                                 c = pgetc();
11528                                 *++p = c;
11529                         } while (isxdigit(c) && --cnt);
11530                         pungetc();
11531                         if (cnt == 3) { /* \x but next char is "bad" */
11532                                 c = 'x';
11533                                 goto unrecognized;
11534                         }
11535                 } else { /* simple seq like \\ or \t */
11536                         p++;
11537                 }
11538                 *p = '\0';
11539                 p = buf;
11540                 c = bb_process_escape_sequence((void*)&p);
11541         } else { /* unrecognized "\z": print both chars unless ' or " */
11542                 if (c != '\'' && c != '"') {
11543  unrecognized:
11544                         c |= 0x100; /* "please encode \, then me" */
11545                 }
11546         }
11547         return c;
11548 }
11549 #endif
11550
11551 /*
11552  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11553  * is not NULL, read a here document.  In the latter case, eofmark is the
11554  * word which marks the end of the document and striptabs is true if
11555  * leading tabs should be stripped from the document.  The argument c
11556  * is the first character of the input token or document.
11557  *
11558  * Because C does not have internal subroutines, I have simulated them
11559  * using goto's to implement the subroutine linkage.  The following macros
11560  * will run code that appears at the end of readtoken1.
11561  */
11562 #define CHECKEND()      {goto checkend; checkend_return:;}
11563 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11564 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11565 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11566 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11567 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11568 static int
11569 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11570 {
11571         /* NB: syntax parameter fits into smallint */
11572         /* c parameter is an unsigned char or PEOF or PEOA */
11573         char *out;
11574         size_t len;
11575         char line[EOFMARKLEN + 1];
11576         struct nodelist *bqlist;
11577         smallint quotef;
11578         smallint dblquote;
11579         smallint oldstyle;
11580         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11581         smallint pssyntax;   /* we are expanding a prompt string */
11582         int varnest;         /* levels of variables expansion */
11583         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11584         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11585         int dqvarnest;       /* levels of variables expansion within double quotes */
11586
11587         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11588
11589         startlinno = g_parsefile->linno;
11590         bqlist = NULL;
11591         quotef = 0;
11592         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11593         pssyntax = (syntax == PSSYNTAX);
11594         if (pssyntax)
11595                 syntax = DQSYNTAX;
11596         dblquote = (syntax == DQSYNTAX);
11597         varnest = 0;
11598         IF_FEATURE_SH_MATH(arinest = 0;)
11599         IF_FEATURE_SH_MATH(parenlevel = 0;)
11600         dqvarnest = 0;
11601
11602         STARTSTACKSTR(out);
11603  loop:
11604         /* For each line, until end of word */
11605         CHECKEND();     /* set c to PEOF if at end of here document */
11606         for (;;) {      /* until end of line or end of word */
11607                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11608                 switch (SIT(c, syntax)) {
11609                 case CNL:       /* '\n' */
11610                         if (syntax == BASESYNTAX)
11611                                 goto endword;   /* exit outer loop */
11612                         USTPUTC(c, out);
11613                         nlprompt();
11614                         c = pgetc();
11615                         goto loop;              /* continue outer loop */
11616                 case CWORD:
11617                         USTPUTC(c, out);
11618                         break;
11619                 case CCTL:
11620 #if BASH_DOLLAR_SQUOTE
11621                         if (c == '\\' && bash_dollar_squote) {
11622                                 c = decode_dollar_squote();
11623                                 if (c == '\0') {
11624                                         /* skip $'\000', $'\x00' (like bash) */
11625                                         break;
11626                                 }
11627                                 if (c & 0x100) {
11628                                         /* Unknown escape. Encode as '\z' */
11629                                         c = (unsigned char)c;
11630                                         if (eofmark == NULL || dblquote)
11631                                                 USTPUTC(CTLESC, out);
11632                                         USTPUTC('\\', out);
11633                                 }
11634                         }
11635 #endif
11636                         if (eofmark == NULL || dblquote)
11637                                 USTPUTC(CTLESC, out);
11638                         USTPUTC(c, out);
11639                         break;
11640                 case CBACK:     /* backslash */
11641                         c = pgetc_without_PEOA();
11642                         if (c == PEOF) {
11643                                 USTPUTC(CTLESC, out);
11644                                 USTPUTC('\\', out);
11645                                 pungetc();
11646                         } else if (c == '\n') {
11647                                 nlprompt();
11648                         } else {
11649                                 if (c == '$' && pssyntax) {
11650                                         USTPUTC(CTLESC, out);
11651                                         USTPUTC('\\', out);
11652                                 }
11653                                 /* Backslash is retained if we are in "str" and next char isn't special */
11654                                 if (dblquote
11655                                  && c != '\\'
11656                                  && c != '`'
11657                                  && c != '$'
11658                                  && (c != '"' || eofmark != NULL)
11659                                 ) {
11660                                         USTPUTC('\\', out);
11661                                 }
11662                                 USTPUTC(CTLESC, out);
11663                                 USTPUTC(c, out);
11664                                 quotef = 1;
11665                         }
11666                         break;
11667                 case CSQUOTE:
11668                         syntax = SQSYNTAX;
11669  quotemark:
11670                         if (eofmark == NULL) {
11671                                 USTPUTC(CTLQUOTEMARK, out);
11672                         }
11673                         break;
11674                 case CDQUOTE:
11675                         syntax = DQSYNTAX;
11676                         dblquote = 1;
11677                         goto quotemark;
11678                 case CENDQUOTE:
11679                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11680                         if (eofmark != NULL && varnest == 0) {
11681                                 USTPUTC(c, out);
11682                         } else {
11683                                 if (dqvarnest == 0) {
11684                                         syntax = BASESYNTAX;
11685                                         dblquote = 0;
11686                                 }
11687                                 quotef = 1;
11688                                 goto quotemark;
11689                         }
11690                         break;
11691                 case CVAR:      /* '$' */
11692                         PARSESUB();             /* parse substitution */
11693                         break;
11694                 case CENDVAR:   /* '}' */
11695                         if (varnest > 0) {
11696                                 varnest--;
11697                                 if (dqvarnest > 0) {
11698                                         dqvarnest--;
11699                                 }
11700                                 c = CTLENDVAR;
11701                         }
11702                         USTPUTC(c, out);
11703                         break;
11704 #if ENABLE_FEATURE_SH_MATH
11705                 case CLP:       /* '(' in arithmetic */
11706                         parenlevel++;
11707                         USTPUTC(c, out);
11708                         break;
11709                 case CRP:       /* ')' in arithmetic */
11710                         if (parenlevel > 0) {
11711                                 parenlevel--;
11712                         } else {
11713                                 if (pgetc_eatbnl() == ')') {
11714                                         c = CTLENDARI;
11715                                         if (--arinest == 0) {
11716                                                 syntax = prevsyntax;
11717                                         }
11718                                 } else {
11719                                         /*
11720                                          * unbalanced parens
11721                                          * (don't 2nd guess - no error)
11722                                          */
11723                                         pungetc();
11724                                 }
11725                         }
11726                         USTPUTC(c, out);
11727                         break;
11728 #endif
11729                 case CBQUOTE:   /* '`' */
11730                         PARSEBACKQOLD();
11731                         break;
11732                 case CENDFILE:
11733                         goto endword;           /* exit outer loop */
11734                 case CIGN:
11735                         break;
11736                 default:
11737                         if (varnest == 0) {
11738 #if BASH_REDIR_OUTPUT
11739                                 if (c == '&') {
11740 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11741                                         if (pgetc() == '>')
11742                                                 c = 0x100 + '>'; /* flag &> */
11743                                         pungetc();
11744                                 }
11745 #endif
11746                                 goto endword;   /* exit outer loop */
11747                         }
11748                         IF_ASH_ALIAS(if (c != PEOA))
11749                                 USTPUTC(c, out);
11750                 }
11751                 c = pgetc();
11752         } /* for (;;) */
11753  endword:
11754
11755 #if ENABLE_FEATURE_SH_MATH
11756         if (syntax == ARISYNTAX)
11757                 raise_error_syntax("missing '))'");
11758 #endif
11759         if (syntax != BASESYNTAX && eofmark == NULL)
11760                 raise_error_syntax("unterminated quoted string");
11761         if (varnest != 0) {
11762                 startlinno = g_parsefile->linno;
11763                 /* { */
11764                 raise_error_syntax("missing '}'");
11765         }
11766         USTPUTC('\0', out);
11767         len = out - (char *)stackblock();
11768         out = stackblock();
11769         if (eofmark == NULL) {
11770                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11771                  && quotef == 0
11772                 ) {
11773                         if (isdigit_str9(out)) {
11774                                 PARSEREDIR(); /* passed as params: out, c */
11775                                 lasttoken = TREDIR;
11776                                 return lasttoken;
11777                         }
11778                         /* else: non-number X seen, interpret it
11779                          * as "NNNX>file" = "NNNX >file" */
11780                 }
11781                 pungetc();
11782         }
11783         quoteflag = quotef;
11784         backquotelist = bqlist;
11785         grabstackblock(len);
11786         wordtext = out;
11787         lasttoken = TWORD;
11788         return lasttoken;
11789 /* end of readtoken routine */
11790
11791 /*
11792  * Check to see whether we are at the end of the here document.  When this
11793  * is called, c is set to the first character of the next input line.  If
11794  * we are at the end of the here document, this routine sets the c to PEOF.
11795  */
11796 checkend: {
11797         if (eofmark) {
11798 #if ENABLE_ASH_ALIAS
11799                 if (c == PEOA)
11800                         c = pgetc_without_PEOA();
11801 #endif
11802                 if (striptabs) {
11803                         while (c == '\t') {
11804                                 c = pgetc_without_PEOA();
11805                         }
11806                 }
11807                 if (c == *eofmark) {
11808                         if (pfgets(line, sizeof(line)) != NULL) {
11809                                 char *p, *q;
11810                                 int cc;
11811
11812                                 p = line;
11813                                 for (q = eofmark + 1;; p++, q++) {
11814                                         cc = *p;
11815                                         if (cc == '\n')
11816                                                 cc = 0;
11817                                         if (!*q || cc != *q)
11818                                                 break;
11819                                 }
11820                                 if (cc == *q) {
11821                                         c = PEOF;
11822                                         nlnoprompt();
11823                                 } else {
11824                                         pushstring(line, NULL);
11825                                 }
11826                         }
11827                 }
11828         }
11829         goto checkend_return;
11830 }
11831
11832 /*
11833  * Parse a redirection operator.  The variable "out" points to a string
11834  * specifying the fd to be redirected.  The variable "c" contains the
11835  * first character of the redirection operator.
11836  */
11837 parseredir: {
11838         /* out is already checked to be a valid number or "" */
11839         int fd = (*out == '\0' ? -1 : atoi(out));
11840         union node *np;
11841
11842         np = stzalloc(sizeof(struct nfile));
11843         if (c == '>') {
11844                 np->nfile.fd = 1;
11845                 c = pgetc();
11846                 if (c == '>')
11847                         np->type = NAPPEND;
11848                 else if (c == '|')
11849                         np->type = NCLOBBER;
11850                 else if (c == '&')
11851                         np->type = NTOFD;
11852                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11853                 else {
11854                         np->type = NTO;
11855                         pungetc();
11856                 }
11857         }
11858 #if BASH_REDIR_OUTPUT
11859         else if (c == 0x100 + '>') { /* this flags &> redirection */
11860                 np->nfile.fd = 1;
11861                 pgetc(); /* this is '>', no need to check */
11862                 np->type = NTO2;
11863         }
11864 #endif
11865         else { /* c == '<' */
11866                 /*np->nfile.fd = 0; - stzalloc did it */
11867                 c = pgetc();
11868                 switch (c) {
11869                 case '<':
11870                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11871                                 np = stzalloc(sizeof(struct nhere));
11872                                 /*np->nfile.fd = 0; - stzalloc did it */
11873                         }
11874                         np->type = NHERE;
11875                         heredoc = stzalloc(sizeof(struct heredoc));
11876                         heredoc->here = np;
11877                         c = pgetc();
11878                         if (c == '-') {
11879                                 heredoc->striptabs = 1;
11880                         } else {
11881                                 /*heredoc->striptabs = 0; - stzalloc did it */
11882                                 pungetc();
11883                         }
11884                         break;
11885
11886                 case '&':
11887                         np->type = NFROMFD;
11888                         break;
11889
11890                 case '>':
11891                         np->type = NFROMTO;
11892                         break;
11893
11894                 default:
11895                         np->type = NFROM;
11896                         pungetc();
11897                         break;
11898                 }
11899         }
11900         if (fd >= 0)
11901                 np->nfile.fd = fd;
11902         redirnode = np;
11903         goto parseredir_return;
11904 }
11905
11906 /*
11907  * Parse a substitution.  At this point, we have read the dollar sign
11908  * and nothing else.
11909  */
11910
11911 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11912  * (assuming ascii char codes, as the original implementation did) */
11913 #define is_special(c) \
11914         (((unsigned)(c) - 33 < 32) \
11915                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11916 parsesub: {
11917         unsigned char subtype;
11918         int typeloc;
11919
11920         c = pgetc_eatbnl();
11921         if (c > 255 /* PEOA or PEOF */
11922          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11923         ) {
11924 #if BASH_DOLLAR_SQUOTE
11925                 if (syntax != DQSYNTAX && c == '\'')
11926                         bash_dollar_squote = 1;
11927                 else
11928 #endif
11929                         USTPUTC('$', out);
11930                 pungetc();
11931         } else if (c == '(') {
11932                 /* $(command) or $((arith)) */
11933                 if (pgetc_eatbnl() == '(') {
11934 #if ENABLE_FEATURE_SH_MATH
11935                         PARSEARITH();
11936 #else
11937                         raise_error_syntax("support for $((arith)) is disabled");
11938 #endif
11939                 } else {
11940                         pungetc();
11941                         PARSEBACKQNEW();
11942                 }
11943         } else {
11944                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11945                 USTPUTC(CTLVAR, out);
11946                 typeloc = out - (char *)stackblock();
11947                 STADJUST(1, out);
11948                 subtype = VSNORMAL;
11949                 if (c == '{') {
11950                         c = pgetc_eatbnl();
11951                         subtype = 0;
11952                 }
11953  varname:
11954                 if (is_name(c)) {
11955                         /* $[{[#]]NAME[}] */
11956                         do {
11957                                 STPUTC(c, out);
11958                                 c = pgetc_eatbnl();
11959                         } while (is_in_name(c));
11960                 } else if (isdigit(c)) {
11961                         /* $[{[#]]NUM[}] */
11962                         do {
11963                                 STPUTC(c, out);
11964                                 c = pgetc_eatbnl();
11965                         } while (isdigit(c));
11966                 } else if (is_special(c)) {
11967                         /* $[{[#]]<specialchar>[}] */
11968                         int cc = c;
11969
11970                         c = pgetc_eatbnl();
11971                         if (!subtype && cc == '#') {
11972                                 subtype = VSLENGTH;
11973                                 if (c == '_' || isalnum(c))
11974                                         goto varname;
11975                                 cc = c;
11976                                 c = pgetc_eatbnl();
11977                                 if (cc == '}' || c != '}') {
11978                                         pungetc();
11979                                         subtype = 0;
11980                                         c = cc;
11981                                         cc = '#';
11982                                 }
11983                         }
11984                         USTPUTC(cc, out);
11985                 } else {
11986                         goto badsub;
11987                 }
11988                 if (c != '}' && subtype == VSLENGTH) {
11989                         /* ${#VAR didn't end with } */
11990                         goto badsub;
11991                 }
11992
11993                 if (subtype == 0) {
11994                         static const char types[] ALIGN1 = "}-+?=";
11995                         /* ${VAR...} but not $VAR or ${#VAR} */
11996                         /* c == first char after VAR */
11997                         switch (c) {
11998                         case ':':
11999                                 c = pgetc_eatbnl();
12000 #if BASH_SUBSTR
12001                                 /* This check is only needed to not misinterpret
12002                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12003                                  * constructs.
12004                                  */
12005                                 if (!strchr(types, c)) {
12006                                         subtype = VSSUBSTR;
12007                                         pungetc();
12008                                         break; /* "goto badsub" is bigger (!) */
12009                                 }
12010 #endif
12011                                 subtype = VSNUL;
12012                                 /*FALLTHROUGH*/
12013                         default: {
12014                                 const char *p = strchr(types, c);
12015                                 if (p == NULL)
12016                                         break;
12017                                 subtype |= p - types + VSNORMAL;
12018                                 break;
12019                         }
12020                         case '%':
12021                         case '#': {
12022                                 int cc = c;
12023                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12024                                 c = pgetc_eatbnl();
12025                                 if (c != cc)
12026                                         goto badsub;
12027                                 subtype++;
12028                                 break;
12029                         }
12030 #if BASH_PATTERN_SUBST
12031                         case '/':
12032                                 /* ${v/[/]pattern/repl} */
12033 //TODO: encode pattern and repl separately.
12034 // Currently ${v/$var_with_slash/repl} is horribly broken
12035                                 subtype = VSREPLACE;
12036                                 c = pgetc_eatbnl();
12037                                 if (c != '/')
12038                                         goto badsub;
12039                                 subtype++; /* VSREPLACEALL */
12040                                 break;
12041 #endif
12042                         }
12043                 } else {
12044  badsub:
12045                         pungetc();
12046                 }
12047                 ((unsigned char *)stackblock())[typeloc] = subtype;
12048                 if (subtype != VSNORMAL) {
12049                         varnest++;
12050                         if (dblquote)
12051                                 dqvarnest++;
12052                 }
12053                 STPUTC('=', out);
12054         }
12055         goto parsesub_return;
12056 }
12057
12058 /*
12059  * Called to parse command substitutions.  Newstyle is set if the command
12060  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12061  * list of commands (passed by reference), and savelen is the number of
12062  * characters on the top of the stack which must be preserved.
12063  */
12064 parsebackq: {
12065         struct nodelist **nlpp;
12066         union node *n;
12067         char *str;
12068         size_t savelen;
12069         smallint saveprompt = 0;
12070
12071         str = NULL;
12072         savelen = out - (char *)stackblock();
12073         if (savelen > 0) {
12074                 /*
12075                  * FIXME: this can allocate very large block on stack and SEGV.
12076                  * Example:
12077                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12078                  * allocates 100kb for every command subst. With about
12079                  * a hundred command substitutions stack overflows.
12080                  * With larger prepended string, SEGV happens sooner.
12081                  */
12082                 str = alloca(savelen);
12083                 memcpy(str, stackblock(), savelen);
12084         }
12085
12086         if (oldstyle) {
12087                 /* We must read until the closing backquote, giving special
12088                  * treatment to some slashes, and then push the string and
12089                  * reread it as input, interpreting it normally.
12090                  */
12091                 char *pout;
12092                 size_t psavelen;
12093                 char *pstr;
12094
12095                 STARTSTACKSTR(pout);
12096                 for (;;) {
12097                         int pc;
12098
12099                         setprompt_if(needprompt, 2);
12100                         pc = pgetc();
12101                         switch (pc) {
12102                         case '`':
12103                                 goto done;
12104
12105                         case '\\':
12106                                 pc = pgetc();
12107                                 if (pc == '\n') {
12108                                         nlprompt();
12109                                         /*
12110                                          * If eating a newline, avoid putting
12111                                          * the newline into the new character
12112                                          * stream (via the STPUTC after the
12113                                          * switch).
12114                                          */
12115                                         continue;
12116                                 }
12117                                 if (pc != '\\' && pc != '`' && pc != '$'
12118                                  && (!dblquote || pc != '"')
12119                                 ) {
12120                                         STPUTC('\\', pout);
12121                                 }
12122                                 if (pc <= 255 /* not PEOA or PEOF */) {
12123                                         break;
12124                                 }
12125                                 /* fall through */
12126
12127                         case PEOF:
12128                         IF_ASH_ALIAS(case PEOA:)
12129                                 startlinno = g_parsefile->linno;
12130                                 raise_error_syntax("EOF in backquote substitution");
12131
12132                         case '\n':
12133                                 nlnoprompt();
12134                                 break;
12135
12136                         default:
12137                                 break;
12138                         }
12139                         STPUTC(pc, pout);
12140                 }
12141  done:
12142                 STPUTC('\0', pout);
12143                 psavelen = pout - (char *)stackblock();
12144                 if (psavelen > 0) {
12145                         pstr = grabstackstr(pout);
12146                         setinputstring(pstr);
12147                 }
12148         }
12149         nlpp = &bqlist;
12150         while (*nlpp)
12151                 nlpp = &(*nlpp)->next;
12152         *nlpp = stzalloc(sizeof(**nlpp));
12153         /* (*nlpp)->next = NULL; - stzalloc did it */
12154
12155         if (oldstyle) {
12156                 saveprompt = doprompt;
12157                 doprompt = 0;
12158         }
12159
12160         n = list(2);
12161
12162         if (oldstyle)
12163                 doprompt = saveprompt;
12164         else if (readtoken() != TRP)
12165                 raise_error_unexpected_syntax(TRP);
12166
12167         (*nlpp)->n = n;
12168         if (oldstyle) {
12169                 /*
12170                  * Start reading from old file again, ignoring any pushed back
12171                  * tokens left from the backquote parsing
12172                  */
12173                 popfile();
12174                 tokpushback = 0;
12175         }
12176         while (stackblocksize() <= savelen)
12177                 growstackblock();
12178         STARTSTACKSTR(out);
12179         if (str) {
12180                 memcpy(out, str, savelen);
12181                 STADJUST(savelen, out);
12182         }
12183         USTPUTC(CTLBACKQ, out);
12184         if (oldstyle)
12185                 goto parsebackq_oldreturn;
12186         goto parsebackq_newreturn;
12187 }
12188
12189 #if ENABLE_FEATURE_SH_MATH
12190 /*
12191  * Parse an arithmetic expansion (indicate start of one and set state)
12192  */
12193 parsearith: {
12194         if (++arinest == 1) {
12195                 prevsyntax = syntax;
12196                 syntax = ARISYNTAX;
12197         }
12198         USTPUTC(CTLARI, out);
12199         goto parsearith_return;
12200 }
12201 #endif
12202 } /* end of readtoken */
12203
12204 /*
12205  * Read the next input token.
12206  * If the token is a word, we set backquotelist to the list of cmds in
12207  *      backquotes.  We set quoteflag to true if any part of the word was
12208  *      quoted.
12209  * If the token is TREDIR, then we set redirnode to a structure containing
12210  *      the redirection.
12211  * In all cases, the variable startlinno is set to the number of the line
12212  *      on which the token starts.
12213  *
12214  * [Change comment:  here documents and internal procedures]
12215  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12216  *  word parsing code into a separate routine.  In this case, readtoken
12217  *  doesn't need to have any internal procedures, but parseword does.
12218  *  We could also make parseoperator in essence the main routine, and
12219  *  have parseword (readtoken1?) handle both words and redirection.]
12220  */
12221 #define NEW_xxreadtoken
12222 #ifdef NEW_xxreadtoken
12223 /* singles must be first! */
12224 static const char xxreadtoken_chars[7] ALIGN1 = {
12225         '\n', '(', ')', /* singles */
12226         '&', '|', ';',  /* doubles */
12227         0
12228 };
12229
12230 #define xxreadtoken_singles 3
12231 #define xxreadtoken_doubles 3
12232
12233 static const char xxreadtoken_tokens[] ALIGN1 = {
12234         TNL, TLP, TRP,          /* only single occurrence allowed */
12235         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12236         TEOF,                   /* corresponds to trailing nul */
12237         TAND, TOR, TENDCASE     /* if double occurrence */
12238 };
12239
12240 static int
12241 xxreadtoken(void)
12242 {
12243         int c;
12244
12245         if (tokpushback) {
12246                 tokpushback = 0;
12247                 return lasttoken;
12248         }
12249         setprompt_if(needprompt, 2);
12250         startlinno = g_parsefile->linno;
12251         for (;;) {                      /* until token or start of word found */
12252                 c = pgetc();
12253                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12254                         continue;
12255
12256                 if (c == '#') {
12257                         while ((c = pgetc()) != '\n' && c != PEOF)
12258                                 continue;
12259                         pungetc();
12260                 } else if (c == '\\') {
12261                         if (pgetc() != '\n') {
12262                                 pungetc();
12263                                 break; /* return readtoken1(...) */
12264                         }
12265                         nlprompt();
12266                 } else {
12267                         const char *p;
12268
12269                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12270                         if (c != PEOF) {
12271                                 if (c == '\n') {
12272                                         nlnoprompt();
12273                                 }
12274
12275                                 p = strchr(xxreadtoken_chars, c);
12276                                 if (p == NULL)
12277                                         break; /* return readtoken1(...) */
12278
12279                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12280                                         int cc = pgetc();
12281                                         if (cc == c) {    /* double occurrence? */
12282                                                 p += xxreadtoken_doubles + 1;
12283                                         } else {
12284                                                 pungetc();
12285 #if BASH_REDIR_OUTPUT
12286                                                 if (c == '&' && cc == '>') /* &> */
12287                                                         break; /* return readtoken1(...) */
12288 #endif
12289                                         }
12290                                 }
12291                         }
12292                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12293                         return lasttoken;
12294                 }
12295         } /* for (;;) */
12296
12297         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12298 }
12299 #else /* old xxreadtoken */
12300 #define RETURN(token)   return lasttoken = token
12301 static int
12302 xxreadtoken(void)
12303 {
12304         int c;
12305
12306         if (tokpushback) {
12307                 tokpushback = 0;
12308                 return lasttoken;
12309         }
12310         setprompt_if(needprompt, 2);
12311         startlinno = g_parsefile->linno;
12312         for (;;) {      /* until token or start of word found */
12313                 c = pgetc();
12314                 switch (c) {
12315                 case ' ': case '\t':
12316                 IF_ASH_ALIAS(case PEOA:)
12317                         continue;
12318                 case '#':
12319                         while ((c = pgetc()) != '\n' && c != PEOF)
12320                                 continue;
12321                         pungetc();
12322                         continue;
12323                 case '\\':
12324                         if (pgetc() == '\n') {
12325                                 nlprompt();
12326                                 continue;
12327                         }
12328                         pungetc();
12329                         goto breakloop;
12330                 case '\n':
12331                         nlnoprompt();
12332                         RETURN(TNL);
12333                 case PEOF:
12334                         RETURN(TEOF);
12335                 case '&':
12336                         if (pgetc() == '&')
12337                                 RETURN(TAND);
12338                         pungetc();
12339                         RETURN(TBACKGND);
12340                 case '|':
12341                         if (pgetc() == '|')
12342                                 RETURN(TOR);
12343                         pungetc();
12344                         RETURN(TPIPE);
12345                 case ';':
12346                         if (pgetc() == ';')
12347                                 RETURN(TENDCASE);
12348                         pungetc();
12349                         RETURN(TSEMI);
12350                 case '(':
12351                         RETURN(TLP);
12352                 case ')':
12353                         RETURN(TRP);
12354                 default:
12355                         goto breakloop;
12356                 }
12357         }
12358  breakloop:
12359         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12360 #undef RETURN
12361 }
12362 #endif /* old xxreadtoken */
12363
12364 static int
12365 readtoken(void)
12366 {
12367         int t;
12368         int kwd = checkkwd;
12369 #if DEBUG
12370         smallint alreadyseen = tokpushback;
12371 #endif
12372
12373 #if ENABLE_ASH_ALIAS
12374  top:
12375 #endif
12376
12377         t = xxreadtoken();
12378
12379         /*
12380          * eat newlines
12381          */
12382         if (kwd & CHKNL) {
12383                 while (t == TNL) {
12384                         parseheredoc();
12385                         t = xxreadtoken();
12386                 }
12387         }
12388
12389         if (t != TWORD || quoteflag) {
12390                 goto out;
12391         }
12392
12393         /*
12394          * check for keywords
12395          */
12396         if (kwd & CHKKWD) {
12397                 const char *const *pp;
12398
12399                 pp = findkwd(wordtext);
12400                 if (pp) {
12401                         lasttoken = t = pp - tokname_array;
12402                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12403                         goto out;
12404                 }
12405         }
12406
12407         if (checkkwd & CHKALIAS) {
12408 #if ENABLE_ASH_ALIAS
12409                 struct alias *ap;
12410                 ap = lookupalias(wordtext, 1);
12411                 if (ap != NULL) {
12412                         if (*ap->val) {
12413                                 pushstring(ap->val, ap);
12414                         }
12415                         goto top;
12416                 }
12417 #endif
12418         }
12419  out:
12420         checkkwd = 0;
12421 #if DEBUG
12422         if (!alreadyseen)
12423                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12424         else
12425                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12426 #endif
12427         return t;
12428 }
12429
12430 static int
12431 peektoken(void)
12432 {
12433         int t;
12434
12435         t = readtoken();
12436         tokpushback = 1;
12437         return t;
12438 }
12439
12440 /*
12441  * Read and parse a command.  Returns NODE_EOF on end of file.
12442  * (NULL is a valid parse tree indicating a blank line.)
12443  */
12444 static union node *
12445 parsecmd(int interact)
12446 {
12447         tokpushback = 0;
12448         checkkwd = 0;
12449         heredoclist = 0;
12450         doprompt = interact;
12451         setprompt_if(doprompt, doprompt);
12452         needprompt = 0;
12453         return list(1);
12454 }
12455
12456 /*
12457  * Input any here documents.
12458  */
12459 static void
12460 parseheredoc(void)
12461 {
12462         struct heredoc *here;
12463         union node *n;
12464
12465         here = heredoclist;
12466         heredoclist = NULL;
12467
12468         while (here) {
12469                 setprompt_if(needprompt, 2);
12470                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12471                                 here->eofmark, here->striptabs);
12472                 n = stzalloc(sizeof(struct narg));
12473                 n->narg.type = NARG;
12474                 /*n->narg.next = NULL; - stzalloc did it */
12475                 n->narg.text = wordtext;
12476                 n->narg.backquote = backquotelist;
12477                 here->here->nhere.doc = n;
12478                 here = here->next;
12479         }
12480 }
12481
12482
12483 /*
12484  * called by editline -- any expansions to the prompt should be added here.
12485  */
12486 static const char *
12487 expandstr(const char *ps)
12488 {
12489         union node n;
12490         int saveprompt;
12491
12492         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12493          * and token processing _can_ alter it (delete NULs etc). */
12494         setinputstring((char *)ps);
12495
12496         saveprompt = doprompt;
12497         doprompt = 0;
12498         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12499         doprompt = saveprompt;
12500
12501         popfile();
12502
12503         n.narg.type = NARG;
12504         n.narg.next = NULL;
12505         n.narg.text = wordtext;
12506         n.narg.backquote = backquotelist;
12507
12508         expandarg(&n, NULL, EXP_QUOTED);
12509         return stackblock();
12510 }
12511
12512 /*
12513  * Execute a command or commands contained in a string.
12514  */
12515 static int
12516 evalstring(char *s, int flags)
12517 {
12518         struct jmploc *volatile savehandler;
12519         struct jmploc jmploc;
12520         int ex;
12521
12522         union node *n;
12523         struct stackmark smark;
12524         int status;
12525
12526         s = sstrdup(s);
12527         setinputstring(s);
12528         setstackmark(&smark);
12529
12530         status = 0;
12531         /* On exception inside execution loop, we must popfile().
12532          * Try interactively:
12533          *      readonly a=a
12534          *      command eval "a=b"  # throws "is read only" error
12535          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12536          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12537          */
12538         savehandler = exception_handler;
12539         ex = setjmp(jmploc.loc);
12540         if (ex)
12541                 goto out;
12542         exception_handler = &jmploc;
12543
12544         while ((n = parsecmd(0)) != NODE_EOF) {
12545                 int i;
12546
12547                 i = evaltree(n, flags);
12548                 if (n)
12549                         status = i;
12550                 popstackmark(&smark);
12551                 if (evalskip)
12552                         break;
12553         }
12554  out:
12555         popstackmark(&smark);
12556         popfile();
12557         stunalloc(s);
12558
12559         exception_handler = savehandler;
12560         if (ex)
12561                 longjmp(exception_handler->loc, ex);
12562
12563         return status;
12564 }
12565
12566 /*
12567  * The eval command.
12568  */
12569 static int FAST_FUNC
12570 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12571 {
12572         char *p;
12573         char *concat;
12574
12575         if (argv[1]) {
12576                 p = argv[1];
12577                 argv += 2;
12578                 if (argv[0]) {
12579                         STARTSTACKSTR(concat);
12580                         for (;;) {
12581                                 concat = stack_putstr(p, concat);
12582                                 p = *argv++;
12583                                 if (p == NULL)
12584                                         break;
12585                                 STPUTC(' ', concat);
12586                         }
12587                         STPUTC('\0', concat);
12588                         p = grabstackstr(concat);
12589                 }
12590                 return evalstring(p, flags & EV_TESTED);
12591         }
12592         return 0;
12593 }
12594
12595 /*
12596  * Read and execute commands.
12597  * "Top" is nonzero for the top level command loop;
12598  * it turns on prompting if the shell is interactive.
12599  */
12600 static int
12601 cmdloop(int top)
12602 {
12603         union node *n;
12604         struct stackmark smark;
12605         int inter;
12606         int status = 0;
12607         int numeof = 0;
12608
12609         TRACE(("cmdloop(%d) called\n", top));
12610         for (;;) {
12611                 int skip;
12612
12613                 setstackmark(&smark);
12614 #if JOBS
12615                 if (doing_jobctl)
12616                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12617 #endif
12618                 inter = 0;
12619                 if (iflag && top) {
12620                         inter++;
12621                         chkmail();
12622                 }
12623                 n = parsecmd(inter);
12624 #if DEBUG
12625                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12626                         showtree(n);
12627 #endif
12628                 if (n == NODE_EOF) {
12629                         if (!top || numeof >= 50)
12630                                 break;
12631                         if (!stoppedjobs()) {
12632                                 if (!Iflag)
12633                                         break;
12634                                 out2str("\nUse \"exit\" to leave shell.\n");
12635                         }
12636                         numeof++;
12637                 } else if (nflag == 0) {
12638                         int i;
12639
12640                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12641                         job_warning >>= 1;
12642                         numeof = 0;
12643                         i = evaltree(n, 0);
12644                         if (n)
12645                                 status = i;
12646                 }
12647                 popstackmark(&smark);
12648                 skip = evalskip;
12649
12650                 if (skip) {
12651                         evalskip &= ~SKIPFUNC;
12652                         break;
12653                 }
12654         }
12655         return status;
12656 }
12657
12658 /*
12659  * Take commands from a file.  To be compatible we should do a path
12660  * search for the file, which is necessary to find sub-commands.
12661  */
12662 static char *
12663 find_dot_file(char *name)
12664 {
12665         char *fullname;
12666         const char *path = pathval();
12667         struct stat statb;
12668
12669         /* don't try this for absolute or relative paths */
12670         if (strchr(name, '/'))
12671                 return name;
12672
12673         while ((fullname = path_advance(&path, name)) != NULL) {
12674                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12675                         /*
12676                          * Don't bother freeing here, since it will
12677                          * be freed by the caller.
12678                          */
12679                         return fullname;
12680                 }
12681                 if (fullname != name)
12682                         stunalloc(fullname);
12683         }
12684
12685         /* not found in the PATH */
12686         ash_msg_and_raise_error("%s: not found", name);
12687         /* NOTREACHED */
12688 }
12689
12690 static int FAST_FUNC
12691 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12692 {
12693         /* "false; . empty_file; echo $?" should print 0, not 1: */
12694         int status = 0;
12695         char *fullname;
12696         char **argv;
12697         char *args_need_save;
12698         struct strlist *sp;
12699         volatile struct shparam saveparam;
12700
12701         for (sp = cmdenviron; sp; sp = sp->next)
12702                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12703
12704         nextopt(nullstr); /* handle possible "--" */
12705         argv = argptr;
12706
12707         if (!argv[0]) {
12708                 /* bash says: "bash: .: filename argument required" */
12709                 return 2; /* bash compat */
12710         }
12711
12712         /* This aborts if file isn't found, which is POSIXly correct.
12713          * bash returns exitcode 1 instead.
12714          */
12715         fullname = find_dot_file(argv[0]);
12716         argv++;
12717         args_need_save = argv[0];
12718         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12719                 int argc;
12720                 saveparam = shellparam;
12721                 shellparam.malloced = 0;
12722                 argc = 1;
12723                 while (argv[argc])
12724                         argc++;
12725                 shellparam.nparam = argc;
12726                 shellparam.p = argv;
12727         };
12728
12729         /* This aborts if file can't be opened, which is POSIXly correct.
12730          * bash returns exitcode 1 instead.
12731          */
12732         setinputfile(fullname, INPUT_PUSH_FILE);
12733         commandname = fullname;
12734         status = cmdloop(0);
12735         popfile();
12736
12737         if (args_need_save) {
12738                 freeparam(&shellparam);
12739                 shellparam = saveparam;
12740         };
12741
12742         return status;
12743 }
12744
12745 static int FAST_FUNC
12746 exitcmd(int argc UNUSED_PARAM, char **argv)
12747 {
12748         if (stoppedjobs())
12749                 return 0;
12750         if (argv[1])
12751                 exitstatus = number(argv[1]);
12752         raise_exception(EXEXIT);
12753         /* NOTREACHED */
12754 }
12755
12756 /*
12757  * Read a file containing shell functions.
12758  */
12759 static void
12760 readcmdfile(char *name)
12761 {
12762         setinputfile(name, INPUT_PUSH_FILE);
12763         cmdloop(0);
12764         popfile();
12765 }
12766
12767
12768 /* ============ find_command inplementation */
12769
12770 /*
12771  * Resolve a command name.  If you change this routine, you may have to
12772  * change the shellexec routine as well.
12773  */
12774 static void
12775 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12776 {
12777         struct tblentry *cmdp;
12778         int idx;
12779         int prev;
12780         char *fullname;
12781         struct stat statb;
12782         int e;
12783         int updatetbl;
12784         struct builtincmd *bcmd;
12785
12786         /* If name contains a slash, don't use PATH or hash table */
12787         if (strchr(name, '/') != NULL) {
12788                 entry->u.index = -1;
12789                 if (act & DO_ABS) {
12790                         while (stat(name, &statb) < 0) {
12791 #ifdef SYSV
12792                                 if (errno == EINTR)
12793                                         continue;
12794 #endif
12795                                 entry->cmdtype = CMDUNKNOWN;
12796                                 return;
12797                         }
12798                 }
12799                 entry->cmdtype = CMDNORMAL;
12800                 return;
12801         }
12802
12803 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12804
12805         updatetbl = (path == pathval());
12806         if (!updatetbl) {
12807                 act |= DO_ALTPATH;
12808                 if (strstr(path, "%builtin") != NULL)
12809                         act |= DO_ALTBLTIN;
12810         }
12811
12812         /* If name is in the table, check answer will be ok */
12813         cmdp = cmdlookup(name, 0);
12814         if (cmdp != NULL) {
12815                 int bit;
12816
12817                 switch (cmdp->cmdtype) {
12818                 default:
12819 #if DEBUG
12820                         abort();
12821 #endif
12822                 case CMDNORMAL:
12823                         bit = DO_ALTPATH;
12824                         break;
12825                 case CMDFUNCTION:
12826                         bit = DO_NOFUNC;
12827                         break;
12828                 case CMDBUILTIN:
12829                         bit = DO_ALTBLTIN;
12830                         break;
12831                 }
12832                 if (act & bit) {
12833                         updatetbl = 0;
12834                         cmdp = NULL;
12835                 } else if (cmdp->rehash == 0)
12836                         /* if not invalidated by cd, we're done */
12837                         goto success;
12838         }
12839
12840         /* If %builtin not in path, check for builtin next */
12841         bcmd = find_builtin(name);
12842         if (bcmd) {
12843                 if (IS_BUILTIN_REGULAR(bcmd))
12844                         goto builtin_success;
12845                 if (act & DO_ALTPATH) {
12846                         if (!(act & DO_ALTBLTIN))
12847                                 goto builtin_success;
12848                 } else if (builtinloc <= 0) {
12849                         goto builtin_success;
12850                 }
12851         }
12852
12853 #if ENABLE_FEATURE_SH_STANDALONE
12854         {
12855                 int applet_no = find_applet_by_name(name);
12856                 if (applet_no >= 0) {
12857                         entry->cmdtype = CMDNORMAL;
12858                         entry->u.index = -2 - applet_no;
12859                         return;
12860                 }
12861         }
12862 #endif
12863
12864         /* We have to search path. */
12865         prev = -1;              /* where to start */
12866         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12867                 if (cmdp->cmdtype == CMDBUILTIN)
12868                         prev = builtinloc;
12869                 else
12870                         prev = cmdp->param.index;
12871         }
12872
12873         e = ENOENT;
12874         idx = -1;
12875  loop:
12876         while ((fullname = path_advance(&path, name)) != NULL) {
12877                 stunalloc(fullname);
12878                 /* NB: code below will still use fullname
12879                  * despite it being "unallocated" */
12880                 idx++;
12881                 if (pathopt) {
12882                         if (prefix(pathopt, "builtin")) {
12883                                 if (bcmd)
12884                                         goto builtin_success;
12885                                 continue;
12886                         }
12887                         if ((act & DO_NOFUNC)
12888                          || !prefix(pathopt, "func")
12889                         ) {     /* ignore unimplemented options */
12890                                 continue;
12891                         }
12892                 }
12893                 /* if rehash, don't redo absolute path names */
12894                 if (fullname[0] == '/' && idx <= prev) {
12895                         if (idx < prev)
12896                                 continue;
12897                         TRACE(("searchexec \"%s\": no change\n", name));
12898                         goto success;
12899                 }
12900                 while (stat(fullname, &statb) < 0) {
12901 #ifdef SYSV
12902                         if (errno == EINTR)
12903                                 continue;
12904 #endif
12905                         if (errno != ENOENT && errno != ENOTDIR)
12906                                 e = errno;
12907                         goto loop;
12908                 }
12909                 e = EACCES;     /* if we fail, this will be the error */
12910                 if (!S_ISREG(statb.st_mode))
12911                         continue;
12912                 if (pathopt) {          /* this is a %func directory */
12913                         stalloc(strlen(fullname) + 1);
12914                         /* NB: stalloc will return space pointed by fullname
12915                          * (because we don't have any intervening allocations
12916                          * between stunalloc above and this stalloc) */
12917                         readcmdfile(fullname);
12918                         cmdp = cmdlookup(name, 0);
12919                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12920                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12921                         stunalloc(fullname);
12922                         goto success;
12923                 }
12924                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12925                 if (!updatetbl) {
12926                         entry->cmdtype = CMDNORMAL;
12927                         entry->u.index = idx;
12928                         return;
12929                 }
12930                 INT_OFF;
12931                 cmdp = cmdlookup(name, 1);
12932                 cmdp->cmdtype = CMDNORMAL;
12933                 cmdp->param.index = idx;
12934                 INT_ON;
12935                 goto success;
12936         }
12937
12938         /* We failed.  If there was an entry for this command, delete it */
12939         if (cmdp && updatetbl)
12940                 delete_cmd_entry();
12941         if (act & DO_ERR)
12942                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12943         entry->cmdtype = CMDUNKNOWN;
12944         return;
12945
12946  builtin_success:
12947         if (!updatetbl) {
12948                 entry->cmdtype = CMDBUILTIN;
12949                 entry->u.cmd = bcmd;
12950                 return;
12951         }
12952         INT_OFF;
12953         cmdp = cmdlookup(name, 1);
12954         cmdp->cmdtype = CMDBUILTIN;
12955         cmdp->param.cmd = bcmd;
12956         INT_ON;
12957  success:
12958         cmdp->rehash = 0;
12959         entry->cmdtype = cmdp->cmdtype;
12960         entry->u = cmdp->param;
12961 }
12962
12963
12964 /*
12965  * The trap builtin.
12966  */
12967 static int FAST_FUNC
12968 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12969 {
12970         char *action;
12971         char **ap;
12972         int signo, exitcode;
12973
12974         nextopt(nullstr);
12975         ap = argptr;
12976         if (!*ap) {
12977                 for (signo = 0; signo < NSIG; signo++) {
12978                         char *tr = trap_ptr[signo];
12979                         if (tr) {
12980                                 /* note: bash adds "SIG", but only if invoked
12981                                  * as "bash". If called as "sh", or if set -o posix,
12982                                  * then it prints short signal names.
12983                                  * We are printing short names: */
12984                                 out1fmt("trap -- %s %s\n",
12985                                                 single_quote(tr),
12986                                                 get_signame(signo));
12987                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12988                  * In this case, we will exit very soon, no need to free(). */
12989                                 /* if (trap_ptr != trap && tp[0]) */
12990                                 /*      free(tr); */
12991                         }
12992                 }
12993                 /*
12994                 if (trap_ptr != trap) {
12995                         free(trap_ptr);
12996                         trap_ptr = trap;
12997                 }
12998                 */
12999                 return 0;
13000         }
13001
13002         action = NULL;
13003         if (ap[1])
13004                 action = *ap++;
13005         exitcode = 0;
13006         while (*ap) {
13007                 signo = get_signum(*ap);
13008                 if (signo < 0 || signo >= NSIG) {
13009                         /* Mimic bash message exactly */
13010                         ash_msg("%s: invalid signal specification", *ap);
13011                         exitcode = 1;
13012                         goto next;
13013                 }
13014                 INT_OFF;
13015                 if (action) {
13016                         if (LONE_DASH(action))
13017                                 action = NULL;
13018                         else {
13019                                 if (action[0]) /* not NULL and not "" and not "-" */
13020                                         may_have_traps = 1;
13021                                 action = ckstrdup(action);
13022                         }
13023                 }
13024                 free(trap[signo]);
13025                 trap[signo] = action;
13026                 if (signo != 0)
13027                         setsignal(signo);
13028                 INT_ON;
13029  next:
13030                 ap++;
13031         }
13032         return exitcode;
13033 }
13034
13035
13036 /* ============ Builtins */
13037
13038 #if ENABLE_ASH_HELP
13039 static int FAST_FUNC
13040 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13041 {
13042         unsigned col;
13043         unsigned i;
13044
13045         out1fmt(
13046                 "Built-in commands:\n"
13047                 "------------------\n");
13048         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13049                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13050                                         builtintab[i].name + 1);
13051                 if (col > 60) {
13052                         out1fmt("\n");
13053                         col = 0;
13054                 }
13055         }
13056 # if ENABLE_FEATURE_SH_STANDALONE
13057         {
13058                 const char *a = applet_names;
13059                 while (*a) {
13060                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13061                         if (col > 60) {
13062                                 out1fmt("\n");
13063                                 col = 0;
13064                         }
13065                         while (*a++ != '\0')
13066                                 continue;
13067                 }
13068         }
13069 # endif
13070         newline_and_flush(stdout);
13071         return EXIT_SUCCESS;
13072 }
13073 #endif
13074
13075 #if MAX_HISTORY
13076 static int FAST_FUNC
13077 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13078 {
13079         show_history(line_input_state);
13080         return EXIT_SUCCESS;
13081 }
13082 #endif
13083
13084 /*
13085  * The export and readonly commands.
13086  */
13087 static int FAST_FUNC
13088 exportcmd(int argc UNUSED_PARAM, char **argv)
13089 {
13090         struct var *vp;
13091         char *name;
13092         const char *p;
13093         char **aptr;
13094         char opt;
13095         int flag;
13096         int flag_off;
13097
13098         /* "readonly" in bash accepts, but ignores -n.
13099          * We do the same: it saves a conditional in nextopt's param.
13100          */
13101         flag_off = 0;
13102         while ((opt = nextopt("np")) != '\0') {
13103                 if (opt == 'n')
13104                         flag_off = VEXPORT;
13105         }
13106         flag = VEXPORT;
13107         if (argv[0][0] == 'r') {
13108                 flag = VREADONLY;
13109                 flag_off = 0; /* readonly ignores -n */
13110         }
13111         flag_off = ~flag_off;
13112
13113         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13114         {
13115                 aptr = argptr;
13116                 name = *aptr;
13117                 if (name) {
13118                         do {
13119                                 p = strchr(name, '=');
13120                                 if (p != NULL) {
13121                                         p++;
13122                                 } else {
13123                                         vp = *findvar(hashvar(name), name);
13124                                         if (vp) {
13125                                                 vp->flags = ((vp->flags | flag) & flag_off);
13126                                                 continue;
13127                                         }
13128                                 }
13129                                 setvar(name, p, (flag & flag_off));
13130                         } while ((name = *++aptr) != NULL);
13131                         return 0;
13132                 }
13133         }
13134
13135         /* No arguments. Show the list of exported or readonly vars.
13136          * -n is ignored.
13137          */
13138         showvars(argv[0], flag, 0);
13139         return 0;
13140 }
13141
13142 /*
13143  * Delete a function if it exists.
13144  */
13145 static void
13146 unsetfunc(const char *name)
13147 {
13148         struct tblentry *cmdp;
13149
13150         cmdp = cmdlookup(name, 0);
13151         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13152                 delete_cmd_entry();
13153 }
13154
13155 /*
13156  * The unset builtin command.  We unset the function before we unset the
13157  * variable to allow a function to be unset when there is a readonly variable
13158  * with the same name.
13159  */
13160 static int FAST_FUNC
13161 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13162 {
13163         char **ap;
13164         int i;
13165         int flag = 0;
13166         int ret = 0;
13167
13168         while ((i = nextopt("vf")) != 0) {
13169                 flag = i;
13170         }
13171
13172         for (ap = argptr; *ap; ap++) {
13173                 if (flag != 'f') {
13174                         i = unsetvar(*ap);
13175                         ret |= i;
13176                         if (!(i & 2))
13177                                 continue;
13178                 }
13179                 if (flag != 'v')
13180                         unsetfunc(*ap);
13181         }
13182         return ret & 1;
13183 }
13184
13185 static const unsigned char timescmd_str[] ALIGN1 = {
13186         ' ',  offsetof(struct tms, tms_utime),
13187         '\n', offsetof(struct tms, tms_stime),
13188         ' ',  offsetof(struct tms, tms_cutime),
13189         '\n', offsetof(struct tms, tms_cstime),
13190         0
13191 };
13192 static int FAST_FUNC
13193 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13194 {
13195         unsigned long clk_tck, s, t;
13196         const unsigned char *p;
13197         struct tms buf;
13198
13199         clk_tck = bb_clk_tck();
13200         times(&buf);
13201
13202         p = timescmd_str;
13203         do {
13204                 t = *(clock_t *)(((char *) &buf) + p[1]);
13205                 s = t / clk_tck;
13206                 t = t % clk_tck;
13207                 out1fmt("%lum%lu.%03lus%c",
13208                         s / 60, s % 60,
13209                         (t * 1000) / clk_tck,
13210                         p[0]);
13211                 p += 2;
13212         } while (*p);
13213
13214         return 0;
13215 }
13216
13217 #if ENABLE_FEATURE_SH_MATH
13218 /*
13219  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13220  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13221  *
13222  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13223  */
13224 static int FAST_FUNC
13225 letcmd(int argc UNUSED_PARAM, char **argv)
13226 {
13227         arith_t i;
13228
13229         argv++;
13230         if (!*argv)
13231                 ash_msg_and_raise_error("expression expected");
13232         do {
13233                 i = ash_arith(*argv);
13234         } while (*++argv);
13235
13236         return !i;
13237 }
13238 #endif
13239
13240 /*
13241  * The read builtin. Options:
13242  *      -r              Do not interpret '\' specially
13243  *      -s              Turn off echo (tty only)
13244  *      -n NCHARS       Read NCHARS max
13245  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13246  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13247  *      -u FD           Read from given FD instead of fd 0
13248  * This uses unbuffered input, which may be avoidable in some cases.
13249  * TODO: bash also has:
13250  *      -a ARRAY        Read into array[0],[1],etc
13251  *      -d DELIM        End on DELIM char, not newline
13252  *      -e              Use line editing (tty only)
13253  */
13254 static int FAST_FUNC
13255 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13256 {
13257         char *opt_n = NULL;
13258         char *opt_p = NULL;
13259         char *opt_t = NULL;
13260         char *opt_u = NULL;
13261         int read_flags = 0;
13262         const char *r;
13263         int i;
13264
13265         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13266                 switch (i) {
13267                 case 'p':
13268                         opt_p = optionarg;
13269                         break;
13270                 case 'n':
13271                         opt_n = optionarg;
13272                         break;
13273                 case 's':
13274                         read_flags |= BUILTIN_READ_SILENT;
13275                         break;
13276                 case 't':
13277                         opt_t = optionarg;
13278                         break;
13279                 case 'r':
13280                         read_flags |= BUILTIN_READ_RAW;
13281                         break;
13282                 case 'u':
13283                         opt_u = optionarg;
13284                         break;
13285                 default:
13286                         break;
13287                 }
13288         }
13289
13290         /* "read -s" needs to save/restore termios, can't allow ^C
13291          * to jump out of it.
13292          */
13293  again:
13294         INT_OFF;
13295         r = shell_builtin_read(setvar0,
13296                 argptr,
13297                 bltinlookup("IFS"), /* can be NULL */
13298                 read_flags,
13299                 opt_n,
13300                 opt_p,
13301                 opt_t,
13302                 opt_u
13303         );
13304         INT_ON;
13305
13306         if ((uintptr_t)r == 1 && errno == EINTR) {
13307                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13308                 if (pending_sig == 0)
13309                         goto again;
13310         }
13311
13312         if ((uintptr_t)r > 1)
13313                 ash_msg_and_raise_error(r);
13314
13315         return (uintptr_t)r;
13316 }
13317
13318 static int FAST_FUNC
13319 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13320 {
13321         static const char permuser[3] ALIGN1 = "ogu";
13322
13323         mode_t mask;
13324         int symbolic_mode = 0;
13325
13326         while (nextopt("S") != '\0') {
13327                 symbolic_mode = 1;
13328         }
13329
13330         INT_OFF;
13331         mask = umask(0);
13332         umask(mask);
13333         INT_ON;
13334
13335         if (*argptr == NULL) {
13336                 if (symbolic_mode) {
13337                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13338                         char *p = buf;
13339                         int i;
13340
13341                         i = 2;
13342                         for (;;) {
13343                                 *p++ = ',';
13344                                 *p++ = permuser[i];
13345                                 *p++ = '=';
13346                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13347                                 if (!(mask & 0400)) *p++ = 'r';
13348                                 if (!(mask & 0200)) *p++ = 'w';
13349                                 if (!(mask & 0100)) *p++ = 'x';
13350                                 mask <<= 3;
13351                                 if (--i < 0)
13352                                         break;
13353                         }
13354                         *p = '\0';
13355                         puts(buf + 1);
13356                 } else {
13357                         out1fmt("%04o\n", mask);
13358                 }
13359         } else {
13360                 char *modestr = *argptr;
13361                 /* numeric umasks are taken as-is */
13362                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13363                 if (!isdigit(modestr[0]))
13364                         mask ^= 0777;
13365                 mask = bb_parse_mode(modestr, mask);
13366                 if ((unsigned)mask > 0777) {
13367                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13368                 }
13369                 if (!isdigit(modestr[0]))
13370                         mask ^= 0777;
13371                 umask(mask);
13372         }
13373         return 0;
13374 }
13375
13376 static int FAST_FUNC
13377 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13378 {
13379         return shell_builtin_ulimit(argv);
13380 }
13381
13382 /* ============ main() and helpers */
13383
13384 /*
13385  * Called to exit the shell.
13386  */
13387 static void
13388 exitshell(void)
13389 {
13390         struct jmploc loc;
13391         char *p;
13392         int status;
13393
13394 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13395         save_history(line_input_state);
13396 #endif
13397         status = exitstatus;
13398         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13399         if (setjmp(loc.loc)) {
13400                 if (exception_type == EXEXIT)
13401                         status = exitstatus;
13402                 goto out;
13403         }
13404         exception_handler = &loc;
13405         p = trap[0];
13406         if (p) {
13407                 trap[0] = NULL;
13408                 evalskip = 0;
13409                 evalstring(p, 0);
13410                 /*free(p); - we'll exit soon */
13411         }
13412  out:
13413         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13414          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13415          */
13416         setjobctl(0);
13417         flush_stdout_stderr();
13418         _exit(status);
13419         /* NOTREACHED */
13420 }
13421
13422 static void
13423 init(void)
13424 {
13425         /* we will never free this */
13426         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13427
13428         sigmode[SIGCHLD - 1] = S_DFL;
13429         setsignal(SIGCHLD);
13430
13431         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13432          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13433          */
13434         signal(SIGHUP, SIG_DFL);
13435
13436         {
13437                 char **envp;
13438                 const char *p;
13439                 struct stat st1, st2;
13440
13441                 initvar();
13442                 for (envp = environ; envp && *envp; envp++) {
13443                         p = endofname(*envp);
13444                         if (p != *envp && *p == '=') {
13445                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13446                         }
13447                 }
13448
13449                 setvareq((char*)defoptindvar, VTEXTFIXED);
13450
13451                 setvar0("PPID", utoa(getppid()));
13452 #if BASH_SHLVL_VAR
13453                 p = lookupvar("SHLVL");
13454                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13455 #endif
13456 #if BASH_HOSTNAME_VAR
13457                 if (!lookupvar("HOSTNAME")) {
13458                         struct utsname uts;
13459                         uname(&uts);
13460                         setvar0("HOSTNAME", uts.nodename);
13461                 }
13462 #endif
13463                 p = lookupvar("PWD");
13464                 if (p) {
13465                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13466                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13467                         ) {
13468                                 p = NULL;
13469                         }
13470                 }
13471                 setpwd(p, 0);
13472         }
13473 }
13474
13475
13476 //usage:#define ash_trivial_usage
13477 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13478 //usage:#define ash_full_usage "\n\n"
13479 //usage:        "Unix shell interpreter"
13480
13481 /*
13482  * Process the shell command line arguments.
13483  */
13484 static void
13485 procargs(char **argv)
13486 {
13487         int i;
13488         const char *xminusc;
13489         char **xargv;
13490
13491         xargv = argv;
13492         arg0 = xargv[0];
13493         /* if (xargv[0]) - mmm, this is always true! */
13494                 xargv++;
13495         for (i = 0; i < NOPTS; i++)
13496                 optlist[i] = 2;
13497         argptr = xargv;
13498         if (options(/*cmdline:*/ 1)) {
13499                 /* it already printed err message */
13500                 raise_exception(EXERROR);
13501         }
13502         xargv = argptr;
13503         xminusc = minusc;
13504         if (*xargv == NULL) {
13505                 if (xminusc)
13506                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13507                 sflag = 1;
13508         }
13509         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13510                 iflag = 1;
13511         if (mflag == 2)
13512                 mflag = iflag;
13513         for (i = 0; i < NOPTS; i++)
13514                 if (optlist[i] == 2)
13515                         optlist[i] = 0;
13516 #if DEBUG == 2
13517         debug = 1;
13518 #endif
13519         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13520         if (xminusc) {
13521                 minusc = *xargv++;
13522                 if (*xargv)
13523                         goto setarg0;
13524         } else if (!sflag) {
13525                 setinputfile(*xargv, 0);
13526  setarg0:
13527                 arg0 = *xargv++;
13528                 commandname = arg0;
13529         }
13530
13531         shellparam.p = xargv;
13532 #if ENABLE_ASH_GETOPTS
13533         shellparam.optind = 1;
13534         shellparam.optoff = -1;
13535 #endif
13536         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13537         while (*xargv) {
13538                 shellparam.nparam++;
13539                 xargv++;
13540         }
13541         optschanged();
13542 }
13543
13544 /*
13545  * Read /etc/profile, ~/.profile, $ENV.
13546  */
13547 static void
13548 read_profile(const char *name)
13549 {
13550         name = expandstr(name);
13551         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13552                 return;
13553         cmdloop(0);
13554         popfile();
13555 }
13556
13557 /*
13558  * This routine is called when an error or an interrupt occurs in an
13559  * interactive shell and control is returned to the main command loop.
13560  * (In dash, this function is auto-generated by build machinery).
13561  */
13562 static void
13563 reset(void)
13564 {
13565         /* from eval.c: */
13566         evalskip = 0;
13567         loopnest = 0;
13568
13569         /* from expand.c: */
13570         ifsfree();
13571
13572         /* from input.c: */
13573         g_parsefile->left_in_buffer = 0;
13574         g_parsefile->left_in_line = 0;      /* clear input buffer */
13575         popallfiles();
13576
13577         /* from redir.c: */
13578         while (redirlist)
13579                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13580 }
13581
13582 #if PROFILE
13583 static short profile_buf[16384];
13584 extern int etext();
13585 #endif
13586
13587 /*
13588  * Main routine.  We initialize things, parse the arguments, execute
13589  * profiles if we're a login shell, and then call cmdloop to execute
13590  * commands.  The setjmp call sets up the location to jump to when an
13591  * exception occurs.  When an exception occurs the variable "state"
13592  * is used to figure out how far we had gotten.
13593  */
13594 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13595 int ash_main(int argc UNUSED_PARAM, char **argv)
13596 {
13597         volatile smallint state;
13598         struct jmploc jmploc;
13599         struct stackmark smark;
13600
13601         /* Initialize global data */
13602         INIT_G_misc();
13603         INIT_G_memstack();
13604         INIT_G_var();
13605 #if ENABLE_ASH_ALIAS
13606         INIT_G_alias();
13607 #endif
13608         INIT_G_cmdtable();
13609
13610 #if PROFILE
13611         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13612 #endif
13613
13614 #if ENABLE_FEATURE_EDITING
13615         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13616 #endif
13617         state = 0;
13618         if (setjmp(jmploc.loc)) {
13619                 smallint e;
13620                 smallint s;
13621
13622                 reset();
13623
13624                 e = exception_type;
13625                 s = state;
13626                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13627                         exitshell();
13628                 }
13629                 if (e == EXINT) {
13630                         newline_and_flush(stderr);
13631                 }
13632
13633                 popstackmark(&smark);
13634                 FORCE_INT_ON; /* enable interrupts */
13635                 if (s == 1)
13636                         goto state1;
13637                 if (s == 2)
13638                         goto state2;
13639                 if (s == 3)
13640                         goto state3;
13641                 goto state4;
13642         }
13643         exception_handler = &jmploc;
13644         rootpid = getpid();
13645
13646         init();
13647         setstackmark(&smark);
13648         procargs(argv);
13649 #if DEBUG
13650         TRACE(("Shell args: "));
13651         trace_puts_args(argv);
13652 #endif
13653
13654         if (argv[0] && argv[0][0] == '-')
13655                 isloginsh = 1;
13656         if (isloginsh) {
13657                 const char *hp;
13658
13659                 state = 1;
13660                 read_profile("/etc/profile");
13661  state1:
13662                 state = 2;
13663                 hp = lookupvar("HOME");
13664                 if (hp)
13665                         read_profile("$HOME/.profile");
13666         }
13667  state2:
13668         state = 3;
13669         if (
13670 #ifndef linux
13671          getuid() == geteuid() && getgid() == getegid() &&
13672 #endif
13673          iflag
13674         ) {
13675                 const char *shinit = lookupvar("ENV");
13676                 if (shinit != NULL && *shinit != '\0')
13677                         read_profile(shinit);
13678         }
13679         popstackmark(&smark);
13680  state3:
13681         state = 4;
13682         if (minusc) {
13683                 /* evalstring pushes parsefile stack.
13684                  * Ensure we don't falsely claim that 0 (stdin)
13685                  * is one of stacked source fds.
13686                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13687                 // if (!sflag) g_parsefile->pf_fd = -1;
13688                 // ^^ not necessary since now we special-case fd 0
13689                 // in is_hidden_fd() to not be considered "hidden fd"
13690                 evalstring(minusc, 0);
13691         }
13692
13693         if (sflag || minusc == NULL) {
13694 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13695                 if (iflag) {
13696                         const char *hp = lookupvar("HISTFILE");
13697                         if (!hp) {
13698                                 hp = lookupvar("HOME");
13699                                 if (hp) {
13700                                         INT_OFF;
13701                                         hp = concat_path_file(hp, ".ash_history");
13702                                         setvar0("HISTFILE", hp);
13703                                         free((char*)hp);
13704                                         INT_ON;
13705                                         hp = lookupvar("HISTFILE");
13706                                 }
13707                         }
13708                         if (hp)
13709                                 line_input_state->hist_file = hp;
13710 # if ENABLE_FEATURE_SH_HISTFILESIZE
13711                         hp = lookupvar("HISTFILESIZE");
13712                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13713 # endif
13714                 }
13715 #endif
13716  state4: /* XXX ??? - why isn't this before the "if" statement */
13717                 cmdloop(1);
13718         }
13719 #if PROFILE
13720         monitor(0);
13721 #endif
13722 #ifdef GPROF
13723         {
13724                 extern void _mcleanup(void);
13725                 _mcleanup();
13726         }
13727 #endif
13728         TRACE(("End of main reached\n"));
13729         exitshell();
13730         /* NOTREACHED */
13731 }
13732
13733
13734 /*-
13735  * Copyright (c) 1989, 1991, 1993, 1994
13736  *      The Regents of the University of California.  All rights reserved.
13737  *
13738  * This code is derived from software contributed to Berkeley by
13739  * Kenneth Almquist.
13740  *
13741  * Redistribution and use in source and binary forms, with or without
13742  * modification, are permitted provided that the following conditions
13743  * are met:
13744  * 1. Redistributions of source code must retain the above copyright
13745  *    notice, this list of conditions and the following disclaimer.
13746  * 2. Redistributions in binary form must reproduce the above copyright
13747  *    notice, this list of conditions and the following disclaimer in the
13748  *    documentation and/or other materials provided with the distribution.
13749  * 3. Neither the name of the University nor the names of its contributors
13750  *    may be used to endorse or promote products derived from this software
13751  *    without specific prior written permission.
13752  *
13753  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13754  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13755  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13756  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13757  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13758  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13759  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13760  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13761  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13762  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13763  * SUCH DAMAGE.
13764  */