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