ash: use mempcpy() where appropriate
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #endif
218 #if ENABLE_ASH_RANDOM_SUPPORT
219 # include "random.h"
220 #else
221 # define CLEAR_RANDOM_T(rnd) ((void)0)
222 #endif
223
224 #include "NUM_APPLETS.h"
225 #if NUM_APPLETS == 1
226 /* STANDALONE does not make sense, and won't compile */
227 # undef CONFIG_FEATURE_SH_STANDALONE
228 # undef ENABLE_FEATURE_SH_STANDALONE
229 # undef IF_FEATURE_SH_STANDALONE
230 # undef IF_NOT_FEATURE_SH_STANDALONE
231 # define ENABLE_FEATURE_SH_STANDALONE 0
232 # define IF_FEATURE_SH_STANDALONE(...)
233 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
234 #endif
235
236 #ifndef PIPE_BUF
237 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
238 #endif
239
240 #if !BB_MMU
241 # error "Do not even bother, ash will not run on NOMMU machine"
242 #endif
243
244
245 /* ============ Hash table sizes. Configurable. */
246
247 #define VTABSIZE 39
248 #define ATABSIZE 39
249 #define CMDTABLESIZE 31         /* should be prime */
250
251
252 /* ============ Shell options */
253
254 static const char *const optletters_optnames[] = {
255         "e"   "errexit",
256         "f"   "noglob",
257         "I"   "ignoreeof",
258         "i"   "interactive",
259         "m"   "monitor",
260         "n"   "noexec",
261         "s"   "stdin",
262         "x"   "xtrace",
263         "v"   "verbose",
264         "C"   "noclobber",
265         "a"   "allexport",
266         "b"   "notify",
267         "u"   "nounset",
268         "\0"  "vi"
269 #if BASH_PIPEFAIL
270         ,"\0"  "pipefail"
271 #endif
272 #if DEBUG
273         ,"\0"  "nolog"
274         ,"\0"  "debug"
275 #endif
276 };
277
278 #define optletters(n)  optletters_optnames[n][0]
279 #define optnames(n)   (optletters_optnames[n] + 1)
280
281 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
282
283
284 /* ============ Misc data */
285
286 #define msg_illnum "Illegal number: %s"
287
288 /*
289  * We enclose jmp_buf in a structure so that we can declare pointers to
290  * jump locations.  The global variable handler contains the location to
291  * jump to when an exception occurs, and the global variable exception_type
292  * contains a code identifying the exception.  To implement nested
293  * exception handlers, the user should save the value of handler on entry
294  * to an inner scope, set handler to point to a jmploc structure for the
295  * inner scope, and restore handler on exit from the scope.
296  */
297 struct jmploc {
298         jmp_buf loc;
299 };
300
301 struct globals_misc {
302         uint8_t exitstatus;     /* exit status of last command */
303         uint8_t back_exitstatus;/* exit status of backquoted command */
304         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
305         int rootpid;            /* pid of main shell */
306         /* shell level: 0 for the main shell, 1 for its children, and so on */
307         int shlvl;
308 #define rootshell (!shlvl)
309         char *minusc;  /* argument to -c option */
310
311         char *curdir; // = nullstr;     /* current working directory */
312         char *physdir; // = nullstr;    /* physical working directory */
313
314         char *arg0; /* value of $0 */
315
316         struct jmploc *exception_handler;
317
318         volatile int suppress_int; /* counter */
319         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
320         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
321         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
322         smallint exception_type; /* kind of exception (0..5) */
323         /* exceptions */
324 #define EXINT 0         /* SIGINT received */
325 #define EXERROR 1       /* a generic error */
326 #define EXEXIT 4        /* exit the shell */
327
328         smallint isloginsh;
329         char nullstr[1];        /* zero length string */
330
331         char optlist[NOPTS];
332 #define eflag optlist[0]
333 #define fflag optlist[1]
334 #define Iflag optlist[2]
335 #define iflag optlist[3]
336 #define mflag optlist[4]
337 #define nflag optlist[5]
338 #define sflag optlist[6]
339 #define xflag optlist[7]
340 #define vflag optlist[8]
341 #define Cflag optlist[9]
342 #define aflag optlist[10]
343 #define bflag optlist[11]
344 #define uflag optlist[12]
345 #define viflag optlist[13]
346 #if BASH_PIPEFAIL
347 # define pipefail optlist[14]
348 #else
349 # define pipefail 0
350 #endif
351 #if DEBUG
352 # define nolog optlist[14 + BASH_PIPEFAIL]
353 # define debug optlist[15 + BASH_PIPEFAIL]
354 #endif
355
356         /* trap handler commands */
357         /*
358          * Sigmode records the current value of the signal handlers for the various
359          * modes.  A value of zero means that the current handler is not known.
360          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
361          */
362         char sigmode[NSIG - 1];
363 #define S_DFL      1            /* default signal handling (SIG_DFL) */
364 #define S_CATCH    2            /* signal is caught */
365 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
366 #define S_HARD_IGN 4            /* signal is ignored permanently */
367
368         /* indicates specified signal received */
369         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
370         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
371         char *trap[NSIG];
372         char **trap_ptr;        /* used only by "trap hack" */
373
374         /* Rarely referenced stuff */
375 #if ENABLE_ASH_RANDOM_SUPPORT
376         random_t random_gen;
377 #endif
378         pid_t backgndpid;        /* pid of last background process */
379 };
380 extern struct globals_misc *const ash_ptr_to_globals_misc;
381 #define G_misc (*ash_ptr_to_globals_misc)
382 #define exitstatus        (G_misc.exitstatus )
383 #define back_exitstatus   (G_misc.back_exitstatus )
384 #define job_warning       (G_misc.job_warning)
385 #define rootpid     (G_misc.rootpid    )
386 #define shlvl       (G_misc.shlvl      )
387 #define minusc      (G_misc.minusc     )
388 #define curdir      (G_misc.curdir     )
389 #define physdir     (G_misc.physdir    )
390 #define arg0        (G_misc.arg0       )
391 #define exception_handler (G_misc.exception_handler)
392 #define exception_type    (G_misc.exception_type   )
393 #define suppress_int      (G_misc.suppress_int     )
394 #define pending_int       (G_misc.pending_int      )
395 #define got_sigchld       (G_misc.got_sigchld      )
396 #define pending_sig       (G_misc.pending_sig      )
397 #define isloginsh   (G_misc.isloginsh  )
398 #define nullstr     (G_misc.nullstr    )
399 #define optlist     (G_misc.optlist    )
400 #define sigmode     (G_misc.sigmode    )
401 #define gotsig      (G_misc.gotsig     )
402 #define may_have_traps    (G_misc.may_have_traps   )
403 #define trap        (G_misc.trap       )
404 #define trap_ptr    (G_misc.trap_ptr   )
405 #define random_gen  (G_misc.random_gen )
406 #define backgndpid  (G_misc.backgndpid )
407 #define INIT_G_misc() do { \
408         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
409         barrier(); \
410         curdir = nullstr; \
411         physdir = nullstr; \
412         trap_ptr = trap; \
413 } while (0)
414
415
416 /* ============ DEBUG */
417 #if DEBUG
418 static void trace_printf(const char *fmt, ...);
419 static void trace_vprintf(const char *fmt, va_list va);
420 # define TRACE(param)    trace_printf param
421 # define TRACEV(param)   trace_vprintf param
422 # define close(fd) do { \
423         int dfd = (fd); \
424         if (close(dfd) < 0) \
425                 bb_error_msg("bug on %d: closing %d(0x%x)", \
426                         __LINE__, dfd, dfd); \
427 } while (0)
428 #else
429 # define TRACE(param)
430 # define TRACEV(param)
431 #endif
432
433
434 /* ============ Utility functions */
435 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
436 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
437
438 static int
439 isdigit_str9(const char *str)
440 {
441         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
442         while (--maxlen && isdigit(*str))
443                 str++;
444         return (*str == '\0');
445 }
446
447 static const char *
448 var_end(const char *var)
449 {
450         while (*var)
451                 if (*var++ == '=')
452                         break;
453         return var;
454 }
455
456
457 /* ============ Interrupts / exceptions */
458
459 static void exitshell(void) NORETURN;
460
461 /*
462  * These macros allow the user to suspend the handling of interrupt signals
463  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
464  * much more efficient and portable.  (But hacking the kernel is so much
465  * more fun than worrying about efficiency and portability. :-))
466  */
467 #if DEBUG_INTONOFF
468 # define INT_OFF do { \
469         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
470         suppress_int++; \
471         barrier(); \
472 } while (0)
473 #else
474 # define INT_OFF do { \
475         suppress_int++; \
476         barrier(); \
477 } while (0)
478 #endif
479
480 /*
481  * Called to raise an exception.  Since C doesn't include exceptions, we
482  * just do a longjmp to the exception handler.  The type of exception is
483  * stored in the global variable "exception_type".
484  */
485 static void raise_exception(int) NORETURN;
486 static void
487 raise_exception(int e)
488 {
489 #if DEBUG
490         if (exception_handler == NULL)
491                 abort();
492 #endif
493         INT_OFF;
494         exception_type = e;
495         longjmp(exception_handler->loc, 1);
496 }
497 #if DEBUG
498 #define raise_exception(e) do { \
499         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
500         raise_exception(e); \
501 } while (0)
502 #endif
503
504 /*
505  * Called when a SIGINT is received.  (If the user specifies
506  * that SIGINT is to be trapped or ignored using the trap builtin, then
507  * this routine is not called.)  Suppressint is nonzero when interrupts
508  * are held using the INT_OFF macro.  (The test for iflag is just
509  * defensive programming.)
510  */
511 static void raise_interrupt(void) NORETURN;
512 static void
513 raise_interrupt(void)
514 {
515         pending_int = 0;
516         /* Signal is not automatically unmasked after it is raised,
517          * do it ourself - unmask all signals */
518         sigprocmask_allsigs(SIG_UNBLOCK);
519         /* pending_sig = 0; - now done in signal_handler() */
520
521         if (!(rootshell && iflag)) {
522                 /* Kill ourself with SIGINT */
523                 signal(SIGINT, SIG_DFL);
524                 raise(SIGINT);
525         }
526         /* bash: ^C even on empty command line sets $? */
527         exitstatus = SIGINT + 128;
528         raise_exception(EXINT);
529         /* NOTREACHED */
530 }
531 #if DEBUG
532 #define raise_interrupt() do { \
533         TRACE(("raising interrupt on line %d\n", __LINE__)); \
534         raise_interrupt(); \
535 } while (0)
536 #endif
537
538 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
539 int_on(void)
540 {
541         barrier();
542         if (--suppress_int == 0 && pending_int) {
543                 raise_interrupt();
544         }
545 }
546 #if DEBUG_INTONOFF
547 # define INT_ON do { \
548         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
549         int_on(); \
550 } while (0)
551 #else
552 # define INT_ON int_on()
553 #endif
554 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
555 force_int_on(void)
556 {
557         barrier();
558         suppress_int = 0;
559         if (pending_int)
560                 raise_interrupt();
561 }
562 #define FORCE_INT_ON force_int_on()
563
564 #define SAVE_INT(v) ((v) = suppress_int)
565
566 #define RESTORE_INT(v) do { \
567         barrier(); \
568         suppress_int = (v); \
569         if (suppress_int == 0 && pending_int) \
570                 raise_interrupt(); \
571 } while (0)
572
573
574 /* ============ Stdout/stderr output */
575
576 static void
577 outstr(const char *p, FILE *file)
578 {
579         INT_OFF;
580         fputs(p, file);
581         INT_ON;
582 }
583
584 static void
585 flush_stdout_stderr(void)
586 {
587         INT_OFF;
588         fflush_all();
589         INT_ON;
590 }
591
592 /* Was called outcslow(c,FILE*), but c was always '\n' */
593 static void
594 newline_and_flush(FILE *dest)
595 {
596         INT_OFF;
597         putc('\n', dest);
598         fflush(dest);
599         INT_ON;
600 }
601
602 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
603 static int
604 out1fmt(const char *fmt, ...)
605 {
606         va_list ap;
607         int r;
608
609         INT_OFF;
610         va_start(ap, fmt);
611         r = vprintf(fmt, ap);
612         va_end(ap);
613         INT_ON;
614         return r;
615 }
616
617 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
618 static int
619 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
620 {
621         va_list ap;
622         int ret;
623
624         va_start(ap, fmt);
625         INT_OFF;
626         ret = vsnprintf(outbuf, length, fmt, ap);
627         va_end(ap);
628         INT_ON;
629         return ret;
630 }
631
632 static void
633 out1str(const char *p)
634 {
635         outstr(p, stdout);
636 }
637
638 static void
639 out2str(const char *p)
640 {
641         outstr(p, stderr);
642         flush_stdout_stderr();
643 }
644
645
646 /* ============ Parser structures */
647
648 /* control characters in argument strings */
649 #define CTL_FIRST CTLESC
650 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
651 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
652 #define CTLENDVAR    ((unsigned char)'\203')
653 #define CTLBACKQ     ((unsigned char)'\204')
654 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
655 #define CTLENDARI    ((unsigned char)'\207')
656 #define CTLQUOTEMARK ((unsigned char)'\210')
657 #define CTL_LAST CTLQUOTEMARK
658
659 /* variable substitution byte (follows CTLVAR) */
660 #define VSTYPE  0x0f            /* type of variable substitution */
661 #define VSNUL   0x10            /* colon--treat the empty string as unset */
662
663 /* values of VSTYPE field */
664 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
665 #define VSMINUS         0x2     /* ${var-text} */
666 #define VSPLUS          0x3     /* ${var+text} */
667 #define VSQUESTION      0x4     /* ${var?message} */
668 #define VSASSIGN        0x5     /* ${var=text} */
669 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
670 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
671 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
672 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
673 #define VSLENGTH        0xa     /* ${#var} */
674 #if BASH_SUBSTR
675 #define VSSUBSTR        0xc     /* ${var:position:length} */
676 #endif
677 #if BASH_PATTERN_SUBST
678 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
679 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
680 #endif
681
682 static const char dolatstr[] ALIGN1 = {
683         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
684 };
685 #define DOLATSTRLEN 6
686
687 #define NCMD      0
688 #define NPIPE     1
689 #define NREDIR    2
690 #define NBACKGND  3
691 #define NSUBSHELL 4
692 #define NAND      5
693 #define NOR       6
694 #define NSEMI     7
695 #define NIF       8
696 #define NWHILE    9
697 #define NUNTIL   10
698 #define NFOR     11
699 #define NCASE    12
700 #define NCLIST   13
701 #define NDEFUN   14
702 #define NARG     15
703 #define NTO      16
704 #if BASH_REDIR_OUTPUT
705 #define NTO2     17
706 #endif
707 #define NCLOBBER 18
708 #define NFROM    19
709 #define NFROMTO  20
710 #define NAPPEND  21
711 #define NTOFD    22
712 #define NFROMFD  23
713 #define NHERE    24
714 #define NXHERE   25
715 #define NNOT     26
716 #define N_NUMBER 27
717
718 union node;
719
720 struct ncmd {
721         smallint type; /* Nxxxx */
722         union node *assign;
723         union node *args;
724         union node *redirect;
725 };
726
727 struct npipe {
728         smallint type;
729         smallint pipe_backgnd;
730         struct nodelist *cmdlist;
731 };
732
733 struct nredir {
734         smallint type;
735         union node *n;
736         union node *redirect;
737 };
738
739 struct nbinary {
740         smallint type;
741         union node *ch1;
742         union node *ch2;
743 };
744
745 struct nif {
746         smallint type;
747         union node *test;
748         union node *ifpart;
749         union node *elsepart;
750 };
751
752 struct nfor {
753         smallint type;
754         union node *args;
755         union node *body;
756         char *var;
757 };
758
759 struct ncase {
760         smallint type;
761         union node *expr;
762         union node *cases;
763 };
764
765 struct nclist {
766         smallint type;
767         union node *next;
768         union node *pattern;
769         union node *body;
770 };
771
772 struct narg {
773         smallint type;
774         union node *next;
775         char *text;
776         struct nodelist *backquote;
777 };
778
779 /* nfile and ndup layout must match!
780  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
781  * that it is actually NTO2 (>&file), and change its type.
782  */
783 struct nfile {
784         smallint type;
785         union node *next;
786         int fd;
787         int _unused_dupfd;
788         union node *fname;
789         char *expfname;
790 };
791
792 struct ndup {
793         smallint type;
794         union node *next;
795         int fd;
796         int dupfd;
797         union node *vname;
798         char *_unused_expfname;
799 };
800
801 struct nhere {
802         smallint type;
803         union node *next;
804         int fd;
805         union node *doc;
806 };
807
808 struct nnot {
809         smallint type;
810         union node *com;
811 };
812
813 union node {
814         smallint type;
815         struct ncmd ncmd;
816         struct npipe npipe;
817         struct nredir nredir;
818         struct nbinary nbinary;
819         struct nif nif;
820         struct nfor nfor;
821         struct ncase ncase;
822         struct nclist nclist;
823         struct narg narg;
824         struct nfile nfile;
825         struct ndup ndup;
826         struct nhere nhere;
827         struct nnot nnot;
828 };
829
830 /*
831  * NODE_EOF is returned by parsecmd when it encounters an end of file.
832  * It must be distinct from NULL.
833  */
834 #define NODE_EOF ((union node *) -1L)
835
836 struct nodelist {
837         struct nodelist *next;
838         union node *n;
839 };
840
841 struct funcnode {
842         int count;
843         union node n;
844 };
845
846 /*
847  * Free a parse tree.
848  */
849 static void
850 freefunc(struct funcnode *f)
851 {
852         if (f && --f->count < 0)
853                 free(f);
854 }
855
856
857 /* ============ Debugging output */
858
859 #if DEBUG
860
861 static FILE *tracefile;
862
863 static void
864 trace_printf(const char *fmt, ...)
865 {
866         va_list va;
867
868         if (debug != 1)
869                 return;
870         if (DEBUG_TIME)
871                 fprintf(tracefile, "%u ", (int) time(NULL));
872         if (DEBUG_PID)
873                 fprintf(tracefile, "[%u] ", (int) getpid());
874         if (DEBUG_SIG)
875                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
876         va_start(va, fmt);
877         vfprintf(tracefile, fmt, va);
878         va_end(va);
879 }
880
881 static void
882 trace_vprintf(const char *fmt, va_list va)
883 {
884         if (debug != 1)
885                 return;
886         vfprintf(tracefile, fmt, va);
887         fprintf(tracefile, "\n");
888 }
889
890 static void
891 trace_puts(const char *s)
892 {
893         if (debug != 1)
894                 return;
895         fputs(s, tracefile);
896 }
897
898 static void
899 trace_puts_quoted(char *s)
900 {
901         char *p;
902         char c;
903
904         if (debug != 1)
905                 return;
906         putc('"', tracefile);
907         for (p = s; *p; p++) {
908                 switch ((unsigned char)*p) {
909                 case '\n': c = 'n'; goto backslash;
910                 case '\t': c = 't'; goto backslash;
911                 case '\r': c = 'r'; goto backslash;
912                 case '\"': c = '\"'; goto backslash;
913                 case '\\': c = '\\'; goto backslash;
914                 case CTLESC: c = 'e'; goto backslash;
915                 case CTLVAR: c = 'v'; goto backslash;
916                 case CTLBACKQ: c = 'q'; goto backslash;
917  backslash:
918                         putc('\\', tracefile);
919                         putc(c, tracefile);
920                         break;
921                 default:
922                         if (*p >= ' ' && *p <= '~')
923                                 putc(*p, tracefile);
924                         else {
925                                 putc('\\', tracefile);
926                                 putc((*p >> 6) & 03, tracefile);
927                                 putc((*p >> 3) & 07, tracefile);
928                                 putc(*p & 07, tracefile);
929                         }
930                         break;
931                 }
932         }
933         putc('"', tracefile);
934 }
935
936 static void
937 trace_puts_args(char **ap)
938 {
939         if (debug != 1)
940                 return;
941         if (!*ap)
942                 return;
943         while (1) {
944                 trace_puts_quoted(*ap);
945                 if (!*++ap) {
946                         putc('\n', tracefile);
947                         break;
948                 }
949                 putc(' ', tracefile);
950         }
951 }
952
953 static void
954 opentrace(void)
955 {
956         char s[100];
957 #ifdef O_APPEND
958         int flags;
959 #endif
960
961         if (debug != 1) {
962                 if (tracefile)
963                         fflush(tracefile);
964                 /* leave open because libedit might be using it */
965                 return;
966         }
967         strcpy(s, "./trace");
968         if (tracefile) {
969                 if (!freopen(s, "a", tracefile)) {
970                         fprintf(stderr, "Can't re-open %s\n", s);
971                         debug = 0;
972                         return;
973                 }
974         } else {
975                 tracefile = fopen(s, "a");
976                 if (tracefile == NULL) {
977                         fprintf(stderr, "Can't open %s\n", s);
978                         debug = 0;
979                         return;
980                 }
981         }
982 #ifdef O_APPEND
983         flags = fcntl(fileno(tracefile), F_GETFL);
984         if (flags >= 0)
985                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
986 #endif
987         setlinebuf(tracefile);
988         fputs("\nTracing started.\n", tracefile);
989 }
990
991 static void
992 indent(int amount, char *pfx, FILE *fp)
993 {
994         int i;
995
996         for (i = 0; i < amount; i++) {
997                 if (pfx && i == amount - 1)
998                         fputs(pfx, fp);
999                 putc('\t', fp);
1000         }
1001 }
1002
1003 /* little circular references here... */
1004 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1005
1006 static void
1007 sharg(union node *arg, FILE *fp)
1008 {
1009         char *p;
1010         struct nodelist *bqlist;
1011         unsigned char subtype;
1012
1013         if (arg->type != NARG) {
1014                 out1fmt("<node type %d>\n", arg->type);
1015                 abort();
1016         }
1017         bqlist = arg->narg.backquote;
1018         for (p = arg->narg.text; *p; p++) {
1019                 switch ((unsigned char)*p) {
1020                 case CTLESC:
1021                         p++;
1022                         putc(*p, fp);
1023                         break;
1024                 case CTLVAR:
1025                         putc('$', fp);
1026                         putc('{', fp);
1027                         subtype = *++p;
1028                         if (subtype == VSLENGTH)
1029                                 putc('#', fp);
1030
1031                         while (*p != '=') {
1032                                 putc(*p, fp);
1033                                 p++;
1034                         }
1035
1036                         if (subtype & VSNUL)
1037                                 putc(':', fp);
1038
1039                         switch (subtype & VSTYPE) {
1040                         case VSNORMAL:
1041                                 putc('}', fp);
1042                                 break;
1043                         case VSMINUS:
1044                                 putc('-', fp);
1045                                 break;
1046                         case VSPLUS:
1047                                 putc('+', fp);
1048                                 break;
1049                         case VSQUESTION:
1050                                 putc('?', fp);
1051                                 break;
1052                         case VSASSIGN:
1053                                 putc('=', fp);
1054                                 break;
1055                         case VSTRIMLEFT:
1056                                 putc('#', fp);
1057                                 break;
1058                         case VSTRIMLEFTMAX:
1059                                 putc('#', fp);
1060                                 putc('#', fp);
1061                                 break;
1062                         case VSTRIMRIGHT:
1063                                 putc('%', fp);
1064                                 break;
1065                         case VSTRIMRIGHTMAX:
1066                                 putc('%', fp);
1067                                 putc('%', fp);
1068                                 break;
1069                         case VSLENGTH:
1070                                 break;
1071                         default:
1072                                 out1fmt("<subtype %d>", subtype);
1073                         }
1074                         break;
1075                 case CTLENDVAR:
1076                         putc('}', fp);
1077                         break;
1078                 case CTLBACKQ:
1079                         putc('$', fp);
1080                         putc('(', fp);
1081                         shtree(bqlist->n, -1, NULL, fp);
1082                         putc(')', fp);
1083                         break;
1084                 default:
1085                         putc(*p, fp);
1086                         break;
1087                 }
1088         }
1089 }
1090
1091 static void
1092 shcmd(union node *cmd, FILE *fp)
1093 {
1094         union node *np;
1095         int first;
1096         const char *s;
1097         int dftfd;
1098
1099         first = 1;
1100         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1101                 if (!first)
1102                         putc(' ', fp);
1103                 sharg(np, fp);
1104                 first = 0;
1105         }
1106         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1107                 if (!first)
1108                         putc(' ', fp);
1109                 dftfd = 0;
1110                 switch (np->nfile.type) {
1111                 case NTO:      s = ">>"+1; dftfd = 1; break;
1112                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1113                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1114 #if BASH_REDIR_OUTPUT
1115                 case NTO2:
1116 #endif
1117                 case NTOFD:    s = ">&"; dftfd = 1; break;
1118                 case NFROM:    s = "<"; break;
1119                 case NFROMFD:  s = "<&"; break;
1120                 case NFROMTO:  s = "<>"; break;
1121                 default:       s = "*error*"; break;
1122                 }
1123                 if (np->nfile.fd != dftfd)
1124                         fprintf(fp, "%d", np->nfile.fd);
1125                 fputs(s, fp);
1126                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1127                         fprintf(fp, "%d", np->ndup.dupfd);
1128                 } else {
1129                         sharg(np->nfile.fname, fp);
1130                 }
1131                 first = 0;
1132         }
1133 }
1134
1135 static void
1136 shtree(union node *n, int ind, char *pfx, FILE *fp)
1137 {
1138         struct nodelist *lp;
1139         const char *s;
1140
1141         if (n == NULL)
1142                 return;
1143
1144         indent(ind, pfx, fp);
1145
1146         if (n == NODE_EOF) {
1147                 fputs("<EOF>", fp);
1148                 return;
1149         }
1150
1151         switch (n->type) {
1152         case NSEMI:
1153                 s = "; ";
1154                 goto binop;
1155         case NAND:
1156                 s = " && ";
1157                 goto binop;
1158         case NOR:
1159                 s = " || ";
1160  binop:
1161                 shtree(n->nbinary.ch1, ind, NULL, fp);
1162                 /* if (ind < 0) */
1163                         fputs(s, fp);
1164                 shtree(n->nbinary.ch2, ind, NULL, fp);
1165                 break;
1166         case NCMD:
1167                 shcmd(n, fp);
1168                 if (ind >= 0)
1169                         putc('\n', fp);
1170                 break;
1171         case NPIPE:
1172                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1173                         shtree(lp->n, 0, NULL, fp);
1174                         if (lp->next)
1175                                 fputs(" | ", fp);
1176                 }
1177                 if (n->npipe.pipe_backgnd)
1178                         fputs(" &", fp);
1179                 if (ind >= 0)
1180                         putc('\n', fp);
1181                 break;
1182         default:
1183                 fprintf(fp, "<node type %d>", n->type);
1184                 if (ind >= 0)
1185                         putc('\n', fp);
1186                 break;
1187         }
1188 }
1189
1190 static void
1191 showtree(union node *n)
1192 {
1193         trace_puts("showtree called\n");
1194         shtree(n, 1, NULL, stderr);
1195 }
1196
1197 #endif /* DEBUG */
1198
1199
1200 /* ============ Parser data */
1201
1202 /*
1203  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1204  */
1205 struct strlist {
1206         struct strlist *next;
1207         char *text;
1208 };
1209
1210 struct alias;
1211
1212 struct strpush {
1213         struct strpush *prev;   /* preceding string on stack */
1214         char *prev_string;
1215         int prev_left_in_line;
1216 #if ENABLE_ASH_ALIAS
1217         struct alias *ap;       /* if push was associated with an alias */
1218 #endif
1219         char *string;           /* remember the string since it may change */
1220
1221         /* Remember last two characters for pungetc. */
1222         int lastc[2];
1223
1224         /* Number of outstanding calls to pungetc. */
1225         int unget;
1226 };
1227
1228 struct parsefile {
1229         struct parsefile *prev; /* preceding file on stack */
1230         int linno;              /* current line */
1231         int pf_fd;              /* file descriptor (or -1 if string) */
1232         int left_in_line;       /* number of chars left in this line */
1233         int left_in_buffer;     /* number of chars left in this buffer past the line */
1234         char *next_to_pgetc;    /* next char in buffer */
1235         char *buf;              /* input buffer */
1236         struct strpush *strpush; /* for pushing strings at this level */
1237         struct strpush basestrpush; /* so pushing one is fast */
1238
1239         /* Remember last two characters for pungetc. */
1240         int lastc[2];
1241
1242         /* Number of outstanding calls to pungetc. */
1243         int unget;
1244 };
1245
1246 static struct parsefile basepf;        /* top level input file */
1247 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1248 static int startlinno;                 /* line # where last token started */
1249 static char *commandname;              /* currently executing command */
1250 static struct strlist *cmdenviron;     /* environment for builtin command */
1251
1252
1253 /* ============ Message printing */
1254
1255 static void
1256 ash_vmsg(const char *msg, va_list ap)
1257 {
1258         fprintf(stderr, "%s: ", arg0);
1259         if (commandname) {
1260                 if (strcmp(arg0, commandname))
1261                         fprintf(stderr, "%s: ", commandname);
1262                 if (!iflag || g_parsefile->pf_fd > 0)
1263                         fprintf(stderr, "line %d: ", startlinno);
1264         }
1265         vfprintf(stderr, msg, ap);
1266         newline_and_flush(stderr);
1267 }
1268
1269 /*
1270  * Exverror is called to raise the error exception.  If the second argument
1271  * is not NULL then error prints an error message using printf style
1272  * formatting.  It then raises the error exception.
1273  */
1274 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1275 static void
1276 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1277 {
1278 #if DEBUG
1279         if (msg) {
1280                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1281                 TRACEV((msg, ap));
1282         } else
1283                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1284         if (msg)
1285 #endif
1286                 ash_vmsg(msg, ap);
1287
1288         flush_stdout_stderr();
1289         raise_exception(cond);
1290         /* NOTREACHED */
1291 }
1292
1293 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1294 static void
1295 ash_msg_and_raise_error(const char *msg, ...)
1296 {
1297         va_list ap;
1298
1299         exitstatus = 2;
1300
1301         va_start(ap, msg);
1302         ash_vmsg_and_raise(EXERROR, msg, ap);
1303         /* NOTREACHED */
1304         va_end(ap);
1305 }
1306
1307 static void raise_error_syntax(const char *) NORETURN;
1308 static void
1309 raise_error_syntax(const char *msg)
1310 {
1311         ash_msg_and_raise_error("syntax error: %s", msg);
1312         /* NOTREACHED */
1313 }
1314
1315 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1316 static void
1317 ash_msg_and_raise(int cond, const char *msg, ...)
1318 {
1319         va_list ap;
1320
1321         va_start(ap, msg);
1322         ash_vmsg_and_raise(cond, msg, ap);
1323         /* NOTREACHED */
1324         va_end(ap);
1325 }
1326
1327 /*
1328  * error/warning routines for external builtins
1329  */
1330 static void
1331 ash_msg(const char *fmt, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, fmt);
1336         ash_vmsg(fmt, ap);
1337         va_end(ap);
1338 }
1339
1340 /*
1341  * Return a string describing an error.  The returned string may be a
1342  * pointer to a static buffer that will be overwritten on the next call.
1343  * Action describes the operation that got the error.
1344  */
1345 static const char *
1346 errmsg(int e, const char *em)
1347 {
1348         if (e == ENOENT || e == ENOTDIR) {
1349                 return em;
1350         }
1351         return strerror(e);
1352 }
1353
1354
1355 /* ============ Memory allocation */
1356
1357 #if 0
1358 /* I consider these wrappers nearly useless:
1359  * ok, they return you to nearest exception handler, but
1360  * how much memory do you leak in the process, making
1361  * memory starvation worse?
1362  */
1363 static void *
1364 ckrealloc(void * p, size_t nbytes)
1365 {
1366         p = realloc(p, nbytes);
1367         if (!p)
1368                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1369         return p;
1370 }
1371
1372 static void *
1373 ckmalloc(size_t nbytes)
1374 {
1375         return ckrealloc(NULL, nbytes);
1376 }
1377
1378 static void *
1379 ckzalloc(size_t nbytes)
1380 {
1381         return memset(ckmalloc(nbytes), 0, nbytes);
1382 }
1383
1384 static char *
1385 ckstrdup(const char *s)
1386 {
1387         char *p = strdup(s);
1388         if (!p)
1389                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1390         return p;
1391 }
1392 #else
1393 /* Using bbox equivalents. They exit if out of memory */
1394 # define ckrealloc xrealloc
1395 # define ckmalloc  xmalloc
1396 # define ckzalloc  xzalloc
1397 # define ckstrdup  xstrdup
1398 #endif
1399
1400 /*
1401  * It appears that grabstackstr() will barf with such alignments
1402  * because stalloc() will return a string allocated in a new stackblock.
1403  */
1404 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1405 enum {
1406         /* Most machines require the value returned from malloc to be aligned
1407          * in some way.  The following macro will get this right
1408          * on many machines.  */
1409         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1410         /* Minimum size of a block */
1411         MINSIZE = SHELL_ALIGN(504),
1412 };
1413
1414 struct stack_block {
1415         struct stack_block *prev;
1416         char space[MINSIZE];
1417 };
1418
1419 struct stackmark {
1420         struct stack_block *stackp;
1421         char *stacknxt;
1422         size_t stacknleft;
1423 };
1424
1425
1426 struct globals_memstack {
1427         struct stack_block *g_stackp; // = &stackbase;
1428         char *g_stacknxt; // = stackbase.space;
1429         char *sstrend; // = stackbase.space + MINSIZE;
1430         size_t g_stacknleft; // = MINSIZE;
1431         struct stack_block stackbase;
1432 };
1433 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1434 #define G_memstack (*ash_ptr_to_globals_memstack)
1435 #define g_stackp     (G_memstack.g_stackp    )
1436 #define g_stacknxt   (G_memstack.g_stacknxt  )
1437 #define sstrend      (G_memstack.sstrend     )
1438 #define g_stacknleft (G_memstack.g_stacknleft)
1439 #define stackbase    (G_memstack.stackbase   )
1440 #define INIT_G_memstack() do { \
1441         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1442         barrier(); \
1443         g_stackp = &stackbase; \
1444         g_stacknxt = stackbase.space; \
1445         g_stacknleft = MINSIZE; \
1446         sstrend = stackbase.space + MINSIZE; \
1447 } while (0)
1448
1449
1450 #define stackblock()     ((void *)g_stacknxt)
1451 #define stackblocksize() g_stacknleft
1452
1453 /*
1454  * Parse trees for commands are allocated in lifo order, so we use a stack
1455  * to make this more efficient, and also to avoid all sorts of exception
1456  * handling code to handle interrupts in the middle of a parse.
1457  *
1458  * The size 504 was chosen because the Ultrix malloc handles that size
1459  * well.
1460  */
1461 static void *
1462 stalloc(size_t nbytes)
1463 {
1464         char *p;
1465         size_t aligned;
1466
1467         aligned = SHELL_ALIGN(nbytes);
1468         if (aligned > g_stacknleft) {
1469                 size_t len;
1470                 size_t blocksize;
1471                 struct stack_block *sp;
1472
1473                 blocksize = aligned;
1474                 if (blocksize < MINSIZE)
1475                         blocksize = MINSIZE;
1476                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1477                 if (len < blocksize)
1478                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1479                 INT_OFF;
1480                 sp = ckmalloc(len);
1481                 sp->prev = g_stackp;
1482                 g_stacknxt = sp->space;
1483                 g_stacknleft = blocksize;
1484                 sstrend = g_stacknxt + blocksize;
1485                 g_stackp = sp;
1486                 INT_ON;
1487         }
1488         p = g_stacknxt;
1489         g_stacknxt += aligned;
1490         g_stacknleft -= aligned;
1491         return p;
1492 }
1493
1494 static void *
1495 stzalloc(size_t nbytes)
1496 {
1497         return memset(stalloc(nbytes), 0, nbytes);
1498 }
1499
1500 static void
1501 stunalloc(void *p)
1502 {
1503 #if DEBUG
1504         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1505                 write(STDERR_FILENO, "stunalloc\n", 10);
1506                 abort();
1507         }
1508 #endif
1509         g_stacknleft += g_stacknxt - (char *)p;
1510         g_stacknxt = p;
1511 }
1512
1513 /*
1514  * Like strdup but works with the ash stack.
1515  */
1516 static char *
1517 sstrdup(const char *p)
1518 {
1519         size_t len = strlen(p) + 1;
1520         return memcpy(stalloc(len), p, len);
1521 }
1522
1523 static inline void
1524 grabstackblock(size_t len)
1525 {
1526         stalloc(len);
1527 }
1528
1529 static void
1530 pushstackmark(struct stackmark *mark, size_t len)
1531 {
1532         mark->stackp = g_stackp;
1533         mark->stacknxt = g_stacknxt;
1534         mark->stacknleft = g_stacknleft;
1535         grabstackblock(len);
1536 }
1537
1538 static void
1539 setstackmark(struct stackmark *mark)
1540 {
1541         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1542 }
1543
1544 static void
1545 popstackmark(struct stackmark *mark)
1546 {
1547         struct stack_block *sp;
1548
1549         if (!mark->stackp)
1550                 return;
1551
1552         INT_OFF;
1553         while (g_stackp != mark->stackp) {
1554                 sp = g_stackp;
1555                 g_stackp = sp->prev;
1556                 free(sp);
1557         }
1558         g_stacknxt = mark->stacknxt;
1559         g_stacknleft = mark->stacknleft;
1560         sstrend = mark->stacknxt + mark->stacknleft;
1561         INT_ON;
1562 }
1563
1564 /*
1565  * When the parser reads in a string, it wants to stick the string on the
1566  * stack and only adjust the stack pointer when it knows how big the
1567  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1568  * of space on top of the stack and stackblocklen returns the length of
1569  * this block.  Growstackblock will grow this space by at least one byte,
1570  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1571  * part of the block that has been used.
1572  */
1573 static void
1574 growstackblock(void)
1575 {
1576         size_t newlen;
1577
1578         newlen = g_stacknleft * 2;
1579         if (newlen < g_stacknleft)
1580                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1581         if (newlen < 128)
1582                 newlen += 128;
1583
1584         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1585                 struct stack_block *sp;
1586                 struct stack_block *prevstackp;
1587                 size_t grosslen;
1588
1589                 INT_OFF;
1590                 sp = g_stackp;
1591                 prevstackp = sp->prev;
1592                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1593                 sp = ckrealloc(sp, grosslen);
1594                 sp->prev = prevstackp;
1595                 g_stackp = sp;
1596                 g_stacknxt = sp->space;
1597                 g_stacknleft = newlen;
1598                 sstrend = sp->space + newlen;
1599                 INT_ON;
1600         } else {
1601                 char *oldspace = g_stacknxt;
1602                 size_t oldlen = g_stacknleft;
1603                 char *p = stalloc(newlen);
1604
1605                 /* free the space we just allocated */
1606                 g_stacknxt = memcpy(p, oldspace, oldlen);
1607                 g_stacknleft += newlen;
1608         }
1609 }
1610
1611 /*
1612  * The following routines are somewhat easier to use than the above.
1613  * The user declares a variable of type STACKSTR, which may be declared
1614  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1615  * the user uses the macro STPUTC to add characters to the string.  In
1616  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1617  * grown as necessary.  When the user is done, she can just leave the
1618  * string there and refer to it using stackblock().  Or she can allocate
1619  * the space for it using grabstackstr().  If it is necessary to allow
1620  * someone else to use the stack temporarily and then continue to grow
1621  * the string, the user should use grabstack to allocate the space, and
1622  * then call ungrabstr(p) to return to the previous mode of operation.
1623  *
1624  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1625  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1626  * is space for at least one character.
1627  */
1628 static void *
1629 growstackstr(void)
1630 {
1631         size_t len = stackblocksize();
1632         growstackblock();
1633         return (char *)stackblock() + len;
1634 }
1635
1636 /*
1637  * Called from CHECKSTRSPACE.
1638  */
1639 static char *
1640 makestrspace(size_t newlen, char *p)
1641 {
1642         size_t len = p - g_stacknxt;
1643         size_t size;
1644
1645         for (;;) {
1646                 size_t nleft;
1647
1648                 size = stackblocksize();
1649                 nleft = size - len;
1650                 if (nleft >= newlen)
1651                         break;
1652                 growstackblock();
1653         }
1654         return (char *)stackblock() + len;
1655 }
1656
1657 static char *
1658 stack_nputstr(const char *s, size_t n, char *p)
1659 {
1660         p = makestrspace(n, p);
1661         p = (char *)memcpy(p, s, n) + n;
1662         return p;
1663 }
1664
1665 static char *
1666 stack_putstr(const char *s, char *p)
1667 {
1668         return stack_nputstr(s, strlen(s), p);
1669 }
1670
1671 static char *
1672 _STPUTC(int c, char *p)
1673 {
1674         if (p == sstrend)
1675                 p = growstackstr();
1676         *p++ = c;
1677         return p;
1678 }
1679
1680 #define STARTSTACKSTR(p)        ((p) = stackblock())
1681 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1682 #define CHECKSTRSPACE(n, p) do { \
1683         char *q = (p); \
1684         size_t l = (n); \
1685         size_t m = sstrend - q; \
1686         if (l > m) \
1687                 (p) = makestrspace(l, q); \
1688 } while (0)
1689 #define USTPUTC(c, p)           (*(p)++ = (c))
1690 #define STACKSTRNUL(p) do { \
1691         if ((p) == sstrend) \
1692                 (p) = growstackstr(); \
1693         *(p) = '\0'; \
1694 } while (0)
1695 #define STUNPUTC(p)             (--(p))
1696 #define STTOPC(p)               ((p)[-1])
1697 #define STADJUST(amount, p)     ((p) += (amount))
1698
1699 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1700 #define ungrabstackstr(s, p)    stunalloc(s)
1701 #define stackstrend()           ((void *)sstrend)
1702
1703
1704 /* ============ String helpers */
1705
1706 /*
1707  * prefix -- see if pfx is a prefix of string.
1708  */
1709 static char *
1710 prefix(const char *string, const char *pfx)
1711 {
1712         while (*pfx) {
1713                 if (*pfx++ != *string++)
1714                         return NULL;
1715         }
1716         return (char *) string;
1717 }
1718
1719 /*
1720  * Check for a valid number.  This should be elsewhere.
1721  */
1722 static int
1723 is_number(const char *p)
1724 {
1725         do {
1726                 if (!isdigit(*p))
1727                         return 0;
1728         } while (*++p != '\0');
1729         return 1;
1730 }
1731
1732 /*
1733  * Convert a string of digits to an integer, printing an error message on
1734  * failure.
1735  */
1736 static int
1737 number(const char *s)
1738 {
1739         if (!is_number(s))
1740                 ash_msg_and_raise_error(msg_illnum, s);
1741         return atoi(s);
1742 }
1743
1744 /*
1745  * Produce a single quoted string suitable as input to the shell.
1746  * The return string is allocated on the stack.
1747  */
1748 static char *
1749 single_quote(const char *s)
1750 {
1751         char *p;
1752
1753         STARTSTACKSTR(p);
1754
1755         do {
1756                 char *q;
1757                 size_t len;
1758
1759                 len = strchrnul(s, '\'') - s;
1760
1761                 q = p = makestrspace(len + 3, p);
1762
1763                 *q++ = '\'';
1764                 q = (char *)memcpy(q, s, len) + len;
1765                 *q++ = '\'';
1766                 s += len;
1767
1768                 STADJUST(q - p, p);
1769
1770                 if (*s != '\'')
1771                         break;
1772                 len = 0;
1773                 do len++; while (*++s == '\'');
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '"';
1778                 q = (char *)memcpy(q, s - len, len) + len;
1779                 *q++ = '"';
1780
1781                 STADJUST(q - p, p);
1782         } while (*s);
1783
1784         USTPUTC('\0', p);
1785
1786         return stackblock();
1787 }
1788
1789 /*
1790  * Produce a possibly single quoted string suitable as input to the shell.
1791  * If 'conditional' is nonzero, quoting is only done if the string contains
1792  * non-shellsafe characters, or is identical to a shell keyword (reserved
1793  * word); if it is zero, quoting is always done.
1794  * If quoting was done, the return string is allocated on the stack,
1795  * otherwise a pointer to the original string is returned.
1796  */
1797 static const char *
1798 maybe_single_quote(const char *s)
1799 {
1800         const char *p = s;
1801
1802         while (*p) {
1803                 /* Assuming ACSII */
1804                 /* quote ctrl_chars space !"#$%&'()* */
1805                 if (*p < '+')
1806                         goto need_quoting;
1807                 /* quote ;<=>? */
1808                 if (*p >= ';' && *p <= '?')
1809                         goto need_quoting;
1810                 /* quote `[\ */
1811                 if (*p == '`')
1812                         goto need_quoting;
1813                 if (*p == '[')
1814                         goto need_quoting;
1815                 if (*p == '\\')
1816                         goto need_quoting;
1817                 /* quote {|}~ DEL and high bytes */
1818                 if (*p > 'z')
1819                         goto need_quoting;
1820                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1821                 /* TODO: maybe avoid quoting % */
1822                 p++;
1823         }
1824         return s;
1825
1826  need_quoting:
1827         return single_quote(s);
1828 }
1829
1830
1831 /* ============ nextopt */
1832
1833 static char **argptr;                  /* argument list for builtin commands */
1834 static char *optionarg;                /* set by nextopt (like getopt) */
1835 static char *optptr;                   /* used by nextopt */
1836
1837 /*
1838  * XXX - should get rid of. Have all builtins use getopt(3).
1839  * The library getopt must have the BSD extension static variable
1840  * "optreset", otherwise it can't be used within the shell safely.
1841  *
1842  * Standard option processing (a la getopt) for builtin routines.
1843  * The only argument that is passed to nextopt is the option string;
1844  * the other arguments are unnecessary. It returns the character,
1845  * or '\0' on end of input.
1846  */
1847 static int
1848 nextopt(const char *optstring)
1849 {
1850         char *p;
1851         const char *q;
1852         char c;
1853
1854         p = optptr;
1855         if (p == NULL || *p == '\0') {
1856                 /* We ate entire "-param", take next one */
1857                 p = *argptr;
1858                 if (p == NULL)
1859                         return '\0';
1860                 if (*p != '-')
1861                         return '\0';
1862                 if (*++p == '\0') /* just "-" ? */
1863                         return '\0';
1864                 argptr++;
1865                 if (LONE_DASH(p)) /* "--" ? */
1866                         return '\0';
1867                 /* p => next "-param" */
1868         }
1869         /* p => some option char in the middle of a "-param" */
1870         c = *p++;
1871         for (q = optstring; *q != c;) {
1872                 if (*q == '\0')
1873                         ash_msg_and_raise_error("illegal option -%c", c);
1874                 if (*++q == ':')
1875                         q++;
1876         }
1877         if (*++q == ':') {
1878                 if (*p == '\0') {
1879                         p = *argptr++;
1880                         if (p == NULL)
1881                                 ash_msg_and_raise_error("no arg for -%c option", c);
1882                 }
1883                 optionarg = p;
1884                 p = NULL;
1885         }
1886         optptr = p;
1887         return c;
1888 }
1889
1890
1891 /* ============ Shell variables */
1892
1893 /*
1894  * The parsefile structure pointed to by the global variable parsefile
1895  * contains information about the current file being read.
1896  */
1897 struct shparam {
1898         int nparam;             /* # of positional parameters (without $0) */
1899 #if ENABLE_ASH_GETOPTS
1900         int optind;             /* next parameter to be processed by getopts */
1901         int optoff;             /* used by getopts */
1902 #endif
1903         unsigned char malloced; /* if parameter list dynamically allocated */
1904         char **p;               /* parameter list */
1905 };
1906
1907 /*
1908  * Free the list of positional parameters.
1909  */
1910 static void
1911 freeparam(volatile struct shparam *param)
1912 {
1913         if (param->malloced) {
1914                 char **ap, **ap1;
1915                 ap = ap1 = param->p;
1916                 while (*ap)
1917                         free(*ap++);
1918                 free(ap1);
1919         }
1920 }
1921
1922 #if ENABLE_ASH_GETOPTS
1923 static void FAST_FUNC getoptsreset(const char *value);
1924 #endif
1925
1926 struct var {
1927         struct var *next;               /* next entry in hash list */
1928         int flags;                      /* flags are defined above */
1929         const char *var_text;           /* name=value */
1930         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1931                                         /* the variable gets set/unset */
1932 };
1933
1934 struct localvar {
1935         struct localvar *next;          /* next local variable in list */
1936         struct var *vp;                 /* the variable that was made local */
1937         int flags;                      /* saved flags */
1938         const char *text;               /* saved text */
1939 };
1940
1941 /* flags */
1942 #define VEXPORT         0x01    /* variable is exported */
1943 #define VREADONLY       0x02    /* variable cannot be modified */
1944 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1945 #define VTEXTFIXED      0x08    /* text is statically allocated */
1946 #define VSTACK          0x10    /* text is allocated on the stack */
1947 #define VUNSET          0x20    /* the variable is not set */
1948 #define VNOFUNC         0x40    /* don't call the callback function */
1949 #define VNOSET          0x80    /* do not set variable - just readonly test */
1950 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1951 #if ENABLE_ASH_RANDOM_SUPPORT
1952 # define VDYNAMIC       0x200   /* dynamic variable */
1953 #else
1954 # define VDYNAMIC       0
1955 #endif
1956
1957
1958 /* Need to be before varinit_data[] */
1959 #if ENABLE_LOCALE_SUPPORT
1960 static void FAST_FUNC
1961 change_lc_all(const char *value)
1962 {
1963         if (value && *value != '\0')
1964                 setlocale(LC_ALL, value);
1965 }
1966 static void FAST_FUNC
1967 change_lc_ctype(const char *value)
1968 {
1969         if (value && *value != '\0')
1970                 setlocale(LC_CTYPE, value);
1971 }
1972 #endif
1973 #if ENABLE_ASH_MAIL
1974 static void chkmail(void);
1975 static void changemail(const char *var_value) FAST_FUNC;
1976 #else
1977 # define chkmail()  ((void)0)
1978 #endif
1979 static void changepath(const char *) FAST_FUNC;
1980 #if ENABLE_ASH_RANDOM_SUPPORT
1981 static void change_random(const char *) FAST_FUNC;
1982 #endif
1983
1984 static const struct {
1985         int flags;
1986         const char *var_text;
1987         void (*var_func)(const char *) FAST_FUNC;
1988 } varinit_data[] = {
1989         /*
1990          * Note: VEXPORT would not work correctly here for NOFORK applets:
1991          * some environment strings may be constant.
1992          */
1993         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1994 #if ENABLE_ASH_MAIL
1995         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1996         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1997 #endif
1998         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1999         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2000         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2001         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2002 #if ENABLE_ASH_GETOPTS
2003         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2004 #endif
2005 #if ENABLE_ASH_RANDOM_SUPPORT
2006         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2007 #endif
2008 #if ENABLE_LOCALE_SUPPORT
2009         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2010         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2011 #endif
2012 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2013         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2014 #endif
2015 };
2016
2017 struct redirtab;
2018
2019 struct globals_var {
2020         struct shparam shellparam;      /* $@ current positional parameters */
2021         struct redirtab *redirlist;
2022         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2023         struct var *vartab[VTABSIZE];
2024         struct var varinit[ARRAY_SIZE(varinit_data)];
2025 };
2026 extern struct globals_var *const ash_ptr_to_globals_var;
2027 #define G_var (*ash_ptr_to_globals_var)
2028 #define shellparam    (G_var.shellparam   )
2029 //#define redirlist     (G_var.redirlist    )
2030 #define preverrout_fd (G_var.preverrout_fd)
2031 #define vartab        (G_var.vartab       )
2032 #define varinit       (G_var.varinit      )
2033 #define INIT_G_var() do { \
2034         unsigned i; \
2035         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2036         barrier(); \
2037         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2038                 varinit[i].flags    = varinit_data[i].flags; \
2039                 varinit[i].var_text = varinit_data[i].var_text; \
2040                 varinit[i].var_func = varinit_data[i].var_func; \
2041         } \
2042 } while (0)
2043
2044 #define vifs      varinit[0]
2045 #if ENABLE_ASH_MAIL
2046 # define vmail    (&vifs)[1]
2047 # define vmpath   (&vmail)[1]
2048 # define vpath    (&vmpath)[1]
2049 #else
2050 # define vpath    (&vifs)[1]
2051 #endif
2052 #define vps1      (&vpath)[1]
2053 #define vps2      (&vps1)[1]
2054 #define vps4      (&vps2)[1]
2055 #if ENABLE_ASH_GETOPTS
2056 # define voptind  (&vps4)[1]
2057 # if ENABLE_ASH_RANDOM_SUPPORT
2058 #  define vrandom (&voptind)[1]
2059 # endif
2060 #else
2061 # if ENABLE_ASH_RANDOM_SUPPORT
2062 #  define vrandom (&vps4)[1]
2063 # endif
2064 #endif
2065
2066 /*
2067  * The following macros access the values of the above variables.
2068  * They have to skip over the name.  They return the null string
2069  * for unset variables.
2070  */
2071 #define ifsval()        (vifs.var_text + 4)
2072 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2073 #if ENABLE_ASH_MAIL
2074 # define mailval()      (vmail.var_text + 5)
2075 # define mpathval()     (vmpath.var_text + 9)
2076 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2077 #endif
2078 #define pathval()       (vpath.var_text + 5)
2079 #define ps1val()        (vps1.var_text + 4)
2080 #define ps2val()        (vps2.var_text + 4)
2081 #define ps4val()        (vps4.var_text + 4)
2082 #if ENABLE_ASH_GETOPTS
2083 # define optindval()    (voptind.var_text + 7)
2084 #endif
2085
2086 #if ENABLE_ASH_GETOPTS
2087 static void FAST_FUNC
2088 getoptsreset(const char *value)
2089 {
2090         shellparam.optind = number(value) ?: 1;
2091         shellparam.optoff = -1;
2092 }
2093 #endif
2094
2095 /*
2096  * Compares two strings up to the first = or '\0'.  The first
2097  * string must be terminated by '='; the second may be terminated by
2098  * either '=' or '\0'.
2099  */
2100 static int
2101 varcmp(const char *p, const char *q)
2102 {
2103         int c, d;
2104
2105         while ((c = *p) == (d = *q)) {
2106                 if (c == '\0' || c == '=')
2107                         goto out;
2108                 p++;
2109                 q++;
2110         }
2111         if (c == '=')
2112                 c = '\0';
2113         if (d == '=')
2114                 d = '\0';
2115  out:
2116         return c - d;
2117 }
2118
2119 /*
2120  * Find the appropriate entry in the hash table from the name.
2121  */
2122 static struct var **
2123 hashvar(const char *p)
2124 {
2125         unsigned hashval;
2126
2127         hashval = ((unsigned char) *p) << 4;
2128         while (*p && *p != '=')
2129                 hashval += (unsigned char) *p++;
2130         return &vartab[hashval % VTABSIZE];
2131 }
2132
2133 static int
2134 vpcmp(const void *a, const void *b)
2135 {
2136         return varcmp(*(const char **)a, *(const char **)b);
2137 }
2138
2139 /*
2140  * This routine initializes the builtin variables.
2141  */
2142 static void
2143 initvar(void)
2144 {
2145         struct var *vp;
2146         struct var *end;
2147         struct var **vpp;
2148
2149         /*
2150          * PS1 depends on uid
2151          */
2152 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2153         vps1.var_text = "PS1=\\w \\$ ";
2154 #else
2155         if (!geteuid())
2156                 vps1.var_text = "PS1=# ";
2157 #endif
2158         vp = varinit;
2159         end = vp + ARRAY_SIZE(varinit);
2160         do {
2161                 vpp = hashvar(vp->var_text);
2162                 vp->next = *vpp;
2163                 *vpp = vp;
2164         } while (++vp < end);
2165 }
2166
2167 static struct var **
2168 findvar(struct var **vpp, const char *name)
2169 {
2170         for (; *vpp; vpp = &(*vpp)->next) {
2171                 if (varcmp((*vpp)->var_text, name) == 0) {
2172                         break;
2173                 }
2174         }
2175         return vpp;
2176 }
2177
2178 /*
2179  * Find the value of a variable.  Returns NULL if not set.
2180  */
2181 static const char* FAST_FUNC
2182 lookupvar(const char *name)
2183 {
2184         struct var *v;
2185
2186         v = *findvar(hashvar(name), name);
2187         if (v) {
2188 #if ENABLE_ASH_RANDOM_SUPPORT
2189         /*
2190          * Dynamic variables are implemented roughly the same way they are
2191          * in bash. Namely, they're "special" so long as they aren't unset.
2192          * As soon as they're unset, they're no longer dynamic, and dynamic
2193          * lookup will no longer happen at that point. -- PFM.
2194          */
2195                 if (v->flags & VDYNAMIC)
2196                         v->var_func(NULL);
2197 #endif
2198                 if (!(v->flags & VUNSET))
2199                         return var_end(v->var_text);
2200         }
2201         return NULL;
2202 }
2203
2204 #if ENABLE_UNICODE_SUPPORT
2205 static void
2206 reinit_unicode_for_ash(void)
2207 {
2208         /* Unicode support should be activated even if LANG is set
2209          * _during_ shell execution, not only if it was set when
2210          * shell was started. Therefore, re-check LANG every time:
2211          */
2212         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2213          || ENABLE_UNICODE_USING_LOCALE
2214         ) {
2215                 const char *s = lookupvar("LC_ALL");
2216                 if (!s) s = lookupvar("LC_CTYPE");
2217                 if (!s) s = lookupvar("LANG");
2218                 reinit_unicode(s);
2219         }
2220 }
2221 #else
2222 # define reinit_unicode_for_ash() ((void)0)
2223 #endif
2224
2225 /*
2226  * Search the environment of a builtin command.
2227  */
2228 static const char *
2229 bltinlookup(const char *name)
2230 {
2231         struct strlist *sp;
2232
2233         for (sp = cmdenviron; sp; sp = sp->next) {
2234                 if (varcmp(sp->text, name) == 0)
2235                         return var_end(sp->text);
2236         }
2237         return lookupvar(name);
2238 }
2239
2240 /*
2241  * Same as setvar except that the variable and value are passed in
2242  * the first argument as name=value.  Since the first argument will
2243  * be actually stored in the table, it should not be a string that
2244  * will go away.
2245  * Called with interrupts off.
2246  */
2247 static void
2248 setvareq(char *s, int flags)
2249 {
2250         struct var *vp, **vpp;
2251
2252         vpp = hashvar(s);
2253         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2254         vp = *findvar(vpp, s);
2255         if (vp) {
2256                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2257                         const char *n;
2258
2259                         if (flags & VNOSAVE)
2260                                 free(s);
2261                         n = vp->var_text;
2262                         exitstatus = 1;
2263                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2264                 }
2265
2266                 if (flags & VNOSET)
2267                         return;
2268
2269                 if (vp->var_func && !(flags & VNOFUNC))
2270                         vp->var_func(var_end(s));
2271
2272                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2273                         free((char*)vp->var_text);
2274
2275                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2276         } else {
2277                 /* variable s is not found */
2278                 if (flags & VNOSET)
2279                         return;
2280                 vp = ckzalloc(sizeof(*vp));
2281                 vp->next = *vpp;
2282                 /*vp->func = NULL; - ckzalloc did it */
2283                 *vpp = vp;
2284         }
2285         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2286                 s = ckstrdup(s);
2287         vp->var_text = s;
2288         vp->flags = flags;
2289 }
2290
2291 /*
2292  * Set the value of a variable.  The flags argument is ored with the
2293  * flags of the variable.  If val is NULL, the variable is unset.
2294  */
2295 static void
2296 setvar(const char *name, const char *val, int flags)
2297 {
2298         const char *q;
2299         char *p;
2300         char *nameeq;
2301         size_t namelen;
2302         size_t vallen;
2303
2304         q = endofname(name);
2305         p = strchrnul(q, '=');
2306         namelen = p - name;
2307         if (!namelen || p != q)
2308                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2309         vallen = 0;
2310         if (val == NULL) {
2311                 flags |= VUNSET;
2312         } else {
2313                 vallen = strlen(val);
2314         }
2315
2316         INT_OFF;
2317         nameeq = ckmalloc(namelen + vallen + 2);
2318         p = mempcpy(nameeq, name, namelen);
2319         if (val) {
2320                 *p++ = '=';
2321                 p = mempcpy(p, val, vallen);
2322         }
2323         *p = '\0';
2324         setvareq(nameeq, flags | VNOSAVE);
2325         INT_ON;
2326 }
2327
2328 static void FAST_FUNC
2329 setvar0(const char *name, const char *val)
2330 {
2331         setvar(name, val, 0);
2332 }
2333
2334 /*
2335  * Unset the specified variable.
2336  */
2337 static int
2338 unsetvar(const char *s)
2339 {
2340         struct var **vpp;
2341         struct var *vp;
2342         int retval;
2343
2344         vpp = findvar(hashvar(s), s);
2345         vp = *vpp;
2346         retval = 2;
2347         if (vp) {
2348                 int flags = vp->flags;
2349
2350                 retval = 1;
2351                 if (flags & VREADONLY)
2352                         goto out;
2353 #if ENABLE_ASH_RANDOM_SUPPORT
2354                 vp->flags &= ~VDYNAMIC;
2355 #endif
2356                 if (flags & VUNSET)
2357                         goto ok;
2358                 if ((flags & VSTRFIXED) == 0) {
2359                         INT_OFF;
2360                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2361                                 free((char*)vp->var_text);
2362                         *vpp = vp->next;
2363                         free(vp);
2364                         INT_ON;
2365                 } else {
2366                         setvar0(s, NULL);
2367                         vp->flags &= ~VEXPORT;
2368                 }
2369  ok:
2370                 retval = 0;
2371         }
2372  out:
2373         return retval;
2374 }
2375
2376 /*
2377  * Process a linked list of variable assignments.
2378  */
2379 static void
2380 listsetvar(struct strlist *list_set_var, int flags)
2381 {
2382         struct strlist *lp = list_set_var;
2383
2384         if (!lp)
2385                 return;
2386         INT_OFF;
2387         do {
2388                 setvareq(lp->text, flags);
2389                 lp = lp->next;
2390         } while (lp);
2391         INT_ON;
2392 }
2393
2394 /*
2395  * Generate a list of variables satisfying the given conditions.
2396  */
2397 static char **
2398 listvars(int on, int off, char ***end)
2399 {
2400         struct var **vpp;
2401         struct var *vp;
2402         char **ep;
2403         int mask;
2404
2405         STARTSTACKSTR(ep);
2406         vpp = vartab;
2407         mask = on | off;
2408         do {
2409                 for (vp = *vpp; vp; vp = vp->next) {
2410                         if ((vp->flags & mask) == on) {
2411                                 if (ep == stackstrend())
2412                                         ep = growstackstr();
2413                                 *ep++ = (char*)vp->var_text;
2414                         }
2415                 }
2416         } while (++vpp < vartab + VTABSIZE);
2417         if (ep == stackstrend())
2418                 ep = growstackstr();
2419         if (end)
2420                 *end = ep;
2421         *ep++ = NULL;
2422         return grabstackstr(ep);
2423 }
2424
2425
2426 /* ============ Path search helper
2427  *
2428  * The variable path (passed by reference) should be set to the start
2429  * of the path before the first call; path_advance will update
2430  * this value as it proceeds.  Successive calls to path_advance will return
2431  * the possible path expansions in sequence.  If an option (indicated by
2432  * a percent sign) appears in the path entry then the global variable
2433  * pathopt will be set to point to it; otherwise pathopt will be set to
2434  * NULL.
2435  */
2436 static const char *pathopt;     /* set by path_advance */
2437
2438 static char *
2439 path_advance(const char **path, const char *name)
2440 {
2441         const char *p;
2442         char *q;
2443         const char *start;
2444         size_t len;
2445
2446         if (*path == NULL)
2447                 return NULL;
2448         start = *path;
2449         for (p = start; *p && *p != ':' && *p != '%'; p++)
2450                 continue;
2451         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2452         while (stackblocksize() < len)
2453                 growstackblock();
2454         q = stackblock();
2455         if (p != start) {
2456                 memcpy(q, start, p - start);
2457                 q += p - start;
2458                 *q++ = '/';
2459         }
2460         strcpy(q, name);
2461         pathopt = NULL;
2462         if (*p == '%') {
2463                 pathopt = ++p;
2464                 while (*p && *p != ':')
2465                         p++;
2466         }
2467         if (*p == ':')
2468                 *path = p + 1;
2469         else
2470                 *path = NULL;
2471         return stalloc(len);
2472 }
2473
2474
2475 /* ============ Prompt */
2476
2477 static smallint doprompt;                   /* if set, prompt the user */
2478 static smallint needprompt;                 /* true if interactive and at start of line */
2479
2480 #if ENABLE_FEATURE_EDITING
2481 static line_input_t *line_input_state;
2482 static const char *cmdedit_prompt;
2483 static void
2484 putprompt(const char *s)
2485 {
2486         if (ENABLE_ASH_EXPAND_PRMT) {
2487                 free((char*)cmdedit_prompt);
2488                 cmdedit_prompt = ckstrdup(s);
2489                 return;
2490         }
2491         cmdedit_prompt = s;
2492 }
2493 #else
2494 static void
2495 putprompt(const char *s)
2496 {
2497         out2str(s);
2498 }
2499 #endif
2500
2501 /* expandstr() needs parsing machinery, so it is far away ahead... */
2502 static const char *expandstr(const char *ps);
2503
2504 static void
2505 setprompt_if(smallint do_set, int whichprompt)
2506 {
2507         const char *prompt;
2508         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2509
2510         if (!do_set)
2511                 return;
2512
2513         needprompt = 0;
2514
2515         switch (whichprompt) {
2516         case 1:
2517                 prompt = ps1val();
2518                 break;
2519         case 2:
2520                 prompt = ps2val();
2521                 break;
2522         default:                        /* 0 */
2523                 prompt = nullstr;
2524         }
2525 #if ENABLE_ASH_EXPAND_PRMT
2526         pushstackmark(&smark, stackblocksize());
2527         putprompt(expandstr(prompt));
2528         popstackmark(&smark);
2529 #else
2530         putprompt(prompt);
2531 #endif
2532 }
2533
2534
2535 /* ============ The cd and pwd commands */
2536
2537 #define CD_PHYSICAL 1
2538 #define CD_PRINT 2
2539
2540 static int
2541 cdopt(void)
2542 {
2543         int flags = 0;
2544         int i, j;
2545
2546         j = 'L';
2547         while ((i = nextopt("LP")) != '\0') {
2548                 if (i != j) {
2549                         flags ^= CD_PHYSICAL;
2550                         j = i;
2551                 }
2552         }
2553
2554         return flags;
2555 }
2556
2557 /*
2558  * Update curdir (the name of the current directory) in response to a
2559  * cd command.
2560  */
2561 static const char *
2562 updatepwd(const char *dir)
2563 {
2564         char *new;
2565         char *p;
2566         char *cdcomppath;
2567         const char *lim;
2568
2569         cdcomppath = sstrdup(dir);
2570         STARTSTACKSTR(new);
2571         if (*dir != '/') {
2572                 if (curdir == nullstr)
2573                         return 0;
2574                 new = stack_putstr(curdir, new);
2575         }
2576         new = makestrspace(strlen(dir) + 2, new);
2577         lim = (char *)stackblock() + 1;
2578         if (*dir != '/') {
2579                 if (new[-1] != '/')
2580                         USTPUTC('/', new);
2581                 if (new > lim && *lim == '/')
2582                         lim++;
2583         } else {
2584                 USTPUTC('/', new);
2585                 cdcomppath++;
2586                 if (dir[1] == '/' && dir[2] != '/') {
2587                         USTPUTC('/', new);
2588                         cdcomppath++;
2589                         lim++;
2590                 }
2591         }
2592         p = strtok(cdcomppath, "/");
2593         while (p) {
2594                 switch (*p) {
2595                 case '.':
2596                         if (p[1] == '.' && p[2] == '\0') {
2597                                 while (new > lim) {
2598                                         STUNPUTC(new);
2599                                         if (new[-1] == '/')
2600                                                 break;
2601                                 }
2602                                 break;
2603                         }
2604                         if (p[1] == '\0')
2605                                 break;
2606                         /* fall through */
2607                 default:
2608                         new = stack_putstr(p, new);
2609                         USTPUTC('/', new);
2610                 }
2611                 p = strtok(NULL, "/");
2612         }
2613         if (new > lim)
2614                 STUNPUTC(new);
2615         *new = 0;
2616         return stackblock();
2617 }
2618
2619 /*
2620  * Find out what the current directory is. If we already know the current
2621  * directory, this routine returns immediately.
2622  */
2623 static char *
2624 getpwd(void)
2625 {
2626         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2627         return dir ? dir : nullstr;
2628 }
2629
2630 static void
2631 setpwd(const char *val, int setold)
2632 {
2633         char *oldcur, *dir;
2634
2635         oldcur = dir = curdir;
2636
2637         if (setold) {
2638                 setvar("OLDPWD", oldcur, VEXPORT);
2639         }
2640         INT_OFF;
2641         if (physdir != nullstr) {
2642                 if (physdir != oldcur)
2643                         free(physdir);
2644                 physdir = nullstr;
2645         }
2646         if (oldcur == val || !val) {
2647                 char *s = getpwd();
2648                 physdir = s;
2649                 if (!val)
2650                         dir = s;
2651         } else
2652                 dir = ckstrdup(val);
2653         if (oldcur != dir && oldcur != nullstr) {
2654                 free(oldcur);
2655         }
2656         curdir = dir;
2657         INT_ON;
2658         setvar("PWD", dir, VEXPORT);
2659 }
2660
2661 static void hashcd(void);
2662
2663 /*
2664  * Actually do the chdir.  We also call hashcd to let other routines
2665  * know that the current directory has changed.
2666  */
2667 static int
2668 docd(const char *dest, int flags)
2669 {
2670         const char *dir = NULL;
2671         int err;
2672
2673         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2674
2675         INT_OFF;
2676         if (!(flags & CD_PHYSICAL)) {
2677                 dir = updatepwd(dest);
2678                 if (dir)
2679                         dest = dir;
2680         }
2681         err = chdir(dest);
2682         if (err)
2683                 goto out;
2684         setpwd(dir, 1);
2685         hashcd();
2686  out:
2687         INT_ON;
2688         return err;
2689 }
2690
2691 static int FAST_FUNC
2692 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2693 {
2694         const char *dest;
2695         const char *path;
2696         const char *p;
2697         char c;
2698         struct stat statb;
2699         int flags;
2700
2701         flags = cdopt();
2702         dest = *argptr;
2703         if (!dest)
2704                 dest = bltinlookup("HOME");
2705         else if (LONE_DASH(dest)) {
2706                 dest = bltinlookup("OLDPWD");
2707                 flags |= CD_PRINT;
2708         }
2709         if (!dest)
2710                 dest = nullstr;
2711         if (*dest == '/')
2712                 goto step6;
2713         if (*dest == '.') {
2714                 c = dest[1];
2715  dotdot:
2716                 switch (c) {
2717                 case '\0':
2718                 case '/':
2719                         goto step6;
2720                 case '.':
2721                         c = dest[2];
2722                         if (c != '.')
2723                                 goto dotdot;
2724                 }
2725         }
2726         if (!*dest)
2727                 dest = ".";
2728         path = bltinlookup("CDPATH");
2729         while (path) {
2730                 c = *path;
2731                 p = path_advance(&path, dest);
2732                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2733                         if (c && c != ':')
2734                                 flags |= CD_PRINT;
2735  docd:
2736                         if (!docd(p, flags))
2737                                 goto out;
2738                         goto err;
2739                 }
2740         }
2741
2742  step6:
2743         p = dest;
2744         goto docd;
2745
2746  err:
2747         ash_msg_and_raise_error("can't cd to %s", dest);
2748         /* NOTREACHED */
2749  out:
2750         if (flags & CD_PRINT)
2751                 out1fmt("%s\n", curdir);
2752         return 0;
2753 }
2754
2755 static int FAST_FUNC
2756 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2757 {
2758         int flags;
2759         const char *dir = curdir;
2760
2761         flags = cdopt();
2762         if (flags) {
2763                 if (physdir == nullstr)
2764                         setpwd(dir, 0);
2765                 dir = physdir;
2766         }
2767         out1fmt("%s\n", dir);
2768         return 0;
2769 }
2770
2771
2772 /* ============ ... */
2773
2774
2775 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2776
2777 /* Syntax classes */
2778 #define CWORD     0             /* character is nothing special */
2779 #define CNL       1             /* newline character */
2780 #define CBACK     2             /* a backslash character */
2781 #define CSQUOTE   3             /* single quote */
2782 #define CDQUOTE   4             /* double quote */
2783 #define CENDQUOTE 5             /* a terminating quote */
2784 #define CBQUOTE   6             /* backwards single quote */
2785 #define CVAR      7             /* a dollar sign */
2786 #define CENDVAR   8             /* a '}' character */
2787 #define CLP       9             /* a left paren in arithmetic */
2788 #define CRP      10             /* a right paren in arithmetic */
2789 #define CENDFILE 11             /* end of file */
2790 #define CCTL     12             /* like CWORD, except it must be escaped */
2791 #define CSPCL    13             /* these terminate a word */
2792 #define CIGN     14             /* character should be ignored */
2793
2794 #define PEOF     256
2795 #if ENABLE_ASH_ALIAS
2796 # define PEOA    257
2797 #endif
2798
2799 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2800
2801 #if ENABLE_FEATURE_SH_MATH
2802 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2803 #else
2804 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2805 #endif
2806 static const uint16_t S_I_T[] ALIGN2 = {
2807 #if ENABLE_ASH_ALIAS
2808         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2809 #endif
2810         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2811         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2812         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2813         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2814         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2815         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2816         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2817         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2818         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2819         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2820         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2821 #if !USE_SIT_FUNCTION
2822         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2823         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2824         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2825 #endif
2826 #undef SIT_ITEM
2827 };
2828 /* Constants below must match table above */
2829 enum {
2830 #if ENABLE_ASH_ALIAS
2831         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2832 #endif
2833         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2834         CNL_CNL_CNL_CNL                    , /*  2 */
2835         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2836         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2837         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2838         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2839         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2840         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2841         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2842         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2843         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2844         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2845         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2846         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2847 };
2848
2849 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2850  * caller must ensure proper cast on it if c is *char_ptr!
2851  */
2852 /* Values for syntax param */
2853 #define BASESYNTAX 0    /* not in quotes */
2854 #define DQSYNTAX   1    /* in double quotes */
2855 #define SQSYNTAX   2    /* in single quotes */
2856 #define ARISYNTAX  3    /* in arithmetic */
2857 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2858
2859 #if USE_SIT_FUNCTION
2860
2861 static int
2862 SIT(int c, int syntax)
2863 {
2864         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2865         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2866         /*
2867          * This causes '/' to be prepended with CTLESC in dquoted string,
2868          * making "./file"* treated incorrectly because we feed
2869          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2870          * The "homegrown" glob implementation is okay with that,
2871          * but glibc one isn't. With '/' always treated as CWORD,
2872          * both work fine.
2873          */
2874 # if ENABLE_ASH_ALIAS
2875         static const uint8_t syntax_index_table[] ALIGN1 = {
2876                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2877                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2878                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2879                 11, 3                           /* "}~" */
2880         };
2881 # else
2882         static const uint8_t syntax_index_table[] ALIGN1 = {
2883                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2884                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2885                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2886                 10, 2                           /* "}~" */
2887         };
2888 # endif
2889         const char *s;
2890         int indx;
2891
2892         if (c == PEOF)
2893                 return CENDFILE;
2894 # if ENABLE_ASH_ALIAS
2895         if (c == PEOA)
2896                 indx = 0;
2897         else
2898 # endif
2899         {
2900                 /* Cast is purely for paranoia here,
2901                  * just in case someone passed signed char to us */
2902                 if ((unsigned char)c >= CTL_FIRST
2903                  && (unsigned char)c <= CTL_LAST
2904                 ) {
2905                         return CCTL;
2906                 }
2907                 s = strchrnul(spec_symbls, c);
2908                 if (*s == '\0')
2909                         return CWORD;
2910                 indx = syntax_index_table[s - spec_symbls];
2911         }
2912         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2913 }
2914
2915 #else   /* !USE_SIT_FUNCTION */
2916
2917 static const uint8_t syntax_index_table[] ALIGN1 = {
2918         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2919         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2921         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2922         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2923         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2924         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2925         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2926         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2927         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2928         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2929         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2930         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2944         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2945         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2946         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2947         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2948         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2949         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2950         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2951         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2952         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2953         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2954         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2956         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2958         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2959         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2960         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2961         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2962         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2964         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2965         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2966 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2967         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2976         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2977         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2979         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2980         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2981         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2982         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2983         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2984         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3006         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3009         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3010         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3011         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3012         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3013         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3014         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3015         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3016         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3017         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3018         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3019         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3037         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3038         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3039         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3040         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3041         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3042         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3043         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3044         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3045         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3046         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3047         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3048         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3049         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3050         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3051         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3052         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3053         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3054         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3055         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3056         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3057         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3176         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3177 # if ENABLE_ASH_ALIAS
3178         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3179 # endif
3180 };
3181
3182 #if 1
3183 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3184 #else /* debug version, caught one signed char bug */
3185 # define SIT(c, syntax) \
3186         ({ \
3187                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3188                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3189                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3190                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3191                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3192         })
3193 #endif
3194
3195 #endif  /* !USE_SIT_FUNCTION */
3196
3197
3198 /* ============ Alias handling */
3199
3200 #if ENABLE_ASH_ALIAS
3201
3202 #define ALIASINUSE 1
3203 #define ALIASDEAD  2
3204
3205 struct alias {
3206         struct alias *next;
3207         char *name;
3208         char *val;
3209         int flag;
3210 };
3211
3212
3213 static struct alias **atab; // [ATABSIZE];
3214 #define INIT_G_alias() do { \
3215         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3216 } while (0)
3217
3218
3219 static struct alias **
3220 __lookupalias(const char *name)
3221 {
3222         unsigned int hashval;
3223         struct alias **app;
3224         const char *p;
3225         unsigned int ch;
3226
3227         p = name;
3228
3229         ch = (unsigned char)*p;
3230         hashval = ch << 4;
3231         while (ch) {
3232                 hashval += ch;
3233                 ch = (unsigned char)*++p;
3234         }
3235         app = &atab[hashval % ATABSIZE];
3236
3237         for (; *app; app = &(*app)->next) {
3238                 if (strcmp(name, (*app)->name) == 0) {
3239                         break;
3240                 }
3241         }
3242
3243         return app;
3244 }
3245
3246 static struct alias *
3247 lookupalias(const char *name, int check)
3248 {
3249         struct alias *ap = *__lookupalias(name);
3250
3251         if (check && ap && (ap->flag & ALIASINUSE))
3252                 return NULL;
3253         return ap;
3254 }
3255
3256 static struct alias *
3257 freealias(struct alias *ap)
3258 {
3259         struct alias *next;
3260
3261         if (ap->flag & ALIASINUSE) {
3262                 ap->flag |= ALIASDEAD;
3263                 return ap;
3264         }
3265
3266         next = ap->next;
3267         free(ap->name);
3268         free(ap->val);
3269         free(ap);
3270         return next;
3271 }
3272
3273 static void
3274 setalias(const char *name, const char *val)
3275 {
3276         struct alias *ap, **app;
3277
3278         app = __lookupalias(name);
3279         ap = *app;
3280         INT_OFF;
3281         if (ap) {
3282                 if (!(ap->flag & ALIASINUSE)) {
3283                         free(ap->val);
3284                 }
3285                 ap->val = ckstrdup(val);
3286                 ap->flag &= ~ALIASDEAD;
3287         } else {
3288                 /* not found */
3289                 ap = ckzalloc(sizeof(struct alias));
3290                 ap->name = ckstrdup(name);
3291                 ap->val = ckstrdup(val);
3292                 /*ap->flag = 0; - ckzalloc did it */
3293                 /*ap->next = NULL;*/
3294                 *app = ap;
3295         }
3296         INT_ON;
3297 }
3298
3299 static int
3300 unalias(const char *name)
3301 {
3302         struct alias **app;
3303
3304         app = __lookupalias(name);
3305
3306         if (*app) {
3307                 INT_OFF;
3308                 *app = freealias(*app);
3309                 INT_ON;
3310                 return 0;
3311         }
3312
3313         return 1;
3314 }
3315
3316 static void
3317 rmaliases(void)
3318 {
3319         struct alias *ap, **app;
3320         int i;
3321
3322         INT_OFF;
3323         for (i = 0; i < ATABSIZE; i++) {
3324                 app = &atab[i];
3325                 for (ap = *app; ap; ap = *app) {
3326                         *app = freealias(*app);
3327                         if (ap == *app) {
3328                                 app = &ap->next;
3329                         }
3330                 }
3331         }
3332         INT_ON;
3333 }
3334
3335 static void
3336 printalias(const struct alias *ap)
3337 {
3338         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3339 }
3340
3341 /*
3342  * TODO - sort output
3343  */
3344 static int FAST_FUNC
3345 aliascmd(int argc UNUSED_PARAM, char **argv)
3346 {
3347         char *n, *v;
3348         int ret = 0;
3349         struct alias *ap;
3350
3351         if (!argv[1]) {
3352                 int i;
3353
3354                 for (i = 0; i < ATABSIZE; i++) {
3355                         for (ap = atab[i]; ap; ap = ap->next) {
3356                                 printalias(ap);
3357                         }
3358                 }
3359                 return 0;
3360         }
3361         while ((n = *++argv) != NULL) {
3362                 v = strchr(n+1, '=');
3363                 if (v == NULL) { /* n+1: funny ksh stuff */
3364                         ap = *__lookupalias(n);
3365                         if (ap == NULL) {
3366                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3367                                 ret = 1;
3368                         } else
3369                                 printalias(ap);
3370                 } else {
3371                         *v++ = '\0';
3372                         setalias(n, v);
3373                 }
3374         }
3375
3376         return ret;
3377 }
3378
3379 static int FAST_FUNC
3380 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3381 {
3382         int i;
3383
3384         while (nextopt("a") != '\0') {
3385                 rmaliases();
3386                 return 0;
3387         }
3388         for (i = 0; *argptr; argptr++) {
3389                 if (unalias(*argptr)) {
3390                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3391                         i = 1;
3392                 }
3393         }
3394
3395         return i;
3396 }
3397
3398 #endif /* ASH_ALIAS */
3399
3400
3401 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3402 #define FORK_FG    0
3403 #define FORK_BG    1
3404 #define FORK_NOJOB 2
3405
3406 /* mode flags for showjob(s) */
3407 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3408 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3409 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3410 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3411
3412 /*
3413  * A job structure contains information about a job.  A job is either a
3414  * single process or a set of processes contained in a pipeline.  In the
3415  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3416  * array of pids.
3417  */
3418 struct procstat {
3419         pid_t   ps_pid;         /* process id */
3420         int     ps_status;      /* last process status from wait() */
3421         char    *ps_cmd;        /* text of command being run */
3422 };
3423
3424 struct job {
3425         struct procstat ps0;    /* status of process */
3426         struct procstat *ps;    /* status or processes when more than one */
3427 #if JOBS
3428         int stopstatus;         /* status of a stopped job */
3429 #endif
3430         unsigned nprocs;        /* number of processes */
3431
3432 #define JOBRUNNING      0       /* at least one proc running */
3433 #define JOBSTOPPED      1       /* all procs are stopped */
3434 #define JOBDONE         2       /* all procs are completed */
3435         unsigned
3436                 state: 8,
3437 #if JOBS
3438                 sigint: 1,      /* job was killed by SIGINT */
3439                 jobctl: 1,      /* job running under job control */
3440 #endif
3441                 waited: 1,      /* true if this entry has been waited for */
3442                 used: 1,        /* true if this entry is in used */
3443                 changed: 1;     /* true if status has changed */
3444         struct job *prev_job;   /* previous job */
3445 };
3446
3447 static struct job *makejob(/*union node *,*/ int);
3448 static int forkshell(struct job *, union node *, int);
3449 static int waitforjob(struct job *);
3450
3451 #if !JOBS
3452 enum { doing_jobctl = 0 };
3453 #define setjobctl(on) do {} while (0)
3454 #else
3455 static smallint doing_jobctl; //references:8
3456 static void setjobctl(int);
3457 #endif
3458
3459 /*
3460  * Ignore a signal.
3461  */
3462 static void
3463 ignoresig(int signo)
3464 {
3465         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3466         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3467                 /* No, need to do it */
3468                 signal(signo, SIG_IGN);
3469         }
3470         sigmode[signo - 1] = S_HARD_IGN;
3471 }
3472
3473 /*
3474  * Only one usage site - in setsignal()
3475  */
3476 static void
3477 signal_handler(int signo)
3478 {
3479         if (signo == SIGCHLD) {
3480                 got_sigchld = 1;
3481                 if (!trap[SIGCHLD])
3482                         return;
3483         }
3484
3485         gotsig[signo - 1] = 1;
3486         pending_sig = signo;
3487
3488         if (signo == SIGINT && !trap[SIGINT]) {
3489                 if (!suppress_int) {
3490                         pending_sig = 0;
3491                         raise_interrupt(); /* does not return */
3492                 }
3493                 pending_int = 1;
3494         }
3495 }
3496
3497 /*
3498  * Set the signal handler for the specified signal.  The routine figures
3499  * out what it should be set to.
3500  */
3501 static void
3502 setsignal(int signo)
3503 {
3504         char *t;
3505         char cur_act, new_act;
3506         struct sigaction act;
3507
3508         t = trap[signo];
3509         new_act = S_DFL;
3510         if (t != NULL) { /* trap for this sig is set */
3511                 new_act = S_CATCH;
3512                 if (t[0] == '\0') /* trap is "": ignore this sig */
3513                         new_act = S_IGN;
3514         }
3515
3516         if (rootshell && new_act == S_DFL) {
3517                 switch (signo) {
3518                 case SIGINT:
3519                         if (iflag || minusc || sflag == 0)
3520                                 new_act = S_CATCH;
3521                         break;
3522                 case SIGQUIT:
3523 #if DEBUG
3524                         if (debug)
3525                                 break;
3526 #endif
3527                         /* man bash:
3528                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3529                          * commands run by bash have signal handlers
3530                          * set to the values inherited by the shell
3531                          * from its parent". */
3532                         new_act = S_IGN;
3533                         break;
3534                 case SIGTERM:
3535                         if (iflag)
3536                                 new_act = S_IGN;
3537                         break;
3538 #if JOBS
3539                 case SIGTSTP:
3540                 case SIGTTOU:
3541                         if (mflag)
3542                                 new_act = S_IGN;
3543                         break;
3544 #endif
3545                 }
3546         }
3547 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3548 //whereas we have to restore it to what shell got on entry
3549 //from the parent. See comment above
3550
3551         if (signo == SIGCHLD)
3552                 new_act = S_CATCH;
3553
3554         t = &sigmode[signo - 1];
3555         cur_act = *t;
3556         if (cur_act == 0) {
3557                 /* current setting is not yet known */
3558                 if (sigaction(signo, NULL, &act)) {
3559                         /* pretend it worked; maybe we should give a warning,
3560                          * but other shells don't. We don't alter sigmode,
3561                          * so we retry every time.
3562                          * btw, in Linux it never fails. --vda */
3563                         return;
3564                 }
3565                 if (act.sa_handler == SIG_IGN) {
3566                         cur_act = S_HARD_IGN;
3567                         if (mflag
3568                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3569                         ) {
3570                                 cur_act = S_IGN;   /* don't hard ignore these */
3571                         }
3572                 }
3573         }
3574         if (cur_act == S_HARD_IGN || cur_act == new_act)
3575                 return;
3576
3577         act.sa_handler = SIG_DFL;
3578         switch (new_act) {
3579         case S_CATCH:
3580                 act.sa_handler = signal_handler;
3581                 break;
3582         case S_IGN:
3583                 act.sa_handler = SIG_IGN;
3584                 break;
3585         }
3586
3587         /* flags and mask matter only if !DFL and !IGN, but we do it
3588          * for all cases for more deterministic behavior:
3589          */
3590         act.sa_flags = 0;
3591         sigfillset(&act.sa_mask);
3592
3593         sigaction_set(signo, &act);
3594
3595         *t = new_act;
3596 }
3597
3598 /* mode flags for set_curjob */
3599 #define CUR_DELETE 2
3600 #define CUR_RUNNING 1
3601 #define CUR_STOPPED 0
3602
3603 #if JOBS
3604 /* pgrp of shell on invocation */
3605 static int initialpgrp; //references:2
3606 static int ttyfd = -1; //5
3607 #endif
3608 /* array of jobs */
3609 static struct job *jobtab; //5
3610 /* size of array */
3611 static unsigned njobs; //4
3612 /* current job */
3613 static struct job *curjob; //lots
3614 /* number of presumed living untracked jobs */
3615 static int jobless; //4
3616
3617 #if 0
3618 /* Bash has a feature: it restores termios after a successful wait for
3619  * a foreground job which had at least one stopped or sigkilled member.
3620  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3621  * properly restoring tty state. Should we do this too?
3622  * A reproducer: ^Z an interactive python:
3623  *
3624  * # python
3625  * Python 2.7.12 (...)
3626  * >>> ^Z
3627  *      { python leaves tty in -icanon -echo state. We do survive that... }
3628  *  [1]+  Stopped                    python
3629  *      { ...however, next program (python #2) does not survive it well: }
3630  * # python
3631  * Python 2.7.12 (...)
3632  * >>> Traceback (most recent call last):
3633  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3634  *   File "<stdin>", line 1, in <module>
3635  * NameError: name 'qwerty' is not defined
3636  *
3637  * The implementation below is modeled on bash code and seems to work.
3638  * However, I'm not sure we should do this. For one: what if I'd fg
3639  * the stopped python instead? It'll be confused by "restored" tty state.
3640  */
3641 static struct termios shell_tty_info;
3642 static void
3643 get_tty_state(void)
3644 {
3645         if (rootshell && ttyfd >= 0)
3646                 tcgetattr(ttyfd, &shell_tty_info);
3647 }
3648 static void
3649 set_tty_state(void)
3650 {
3651         /* if (rootshell) - caller ensures this */
3652         if (ttyfd >= 0)
3653                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3654 }
3655 static int
3656 job_signal_status(struct job *jp)
3657 {
3658         int status;
3659         unsigned i;
3660         struct procstat *ps = jp->ps;
3661         for (i = 0; i < jp->nprocs; i++) {
3662                 status = ps[i].ps_status;
3663                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3664                         return status;
3665         }
3666         return 0;
3667 }
3668 static void
3669 restore_tty_if_stopped_or_signaled(struct job *jp)
3670 {
3671 //TODO: check what happens if we come from waitforjob() in expbackq()
3672         if (rootshell) {
3673                 int s = job_signal_status(jp);
3674                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3675                         set_tty_state();
3676         }
3677 }
3678 #else
3679 # define get_tty_state() ((void)0)
3680 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3681 #endif
3682
3683 static void
3684 set_curjob(struct job *jp, unsigned mode)
3685 {
3686         struct job *jp1;
3687         struct job **jpp, **curp;
3688
3689         /* first remove from list */
3690         jpp = curp = &curjob;
3691         while (1) {
3692                 jp1 = *jpp;
3693                 if (jp1 == jp)
3694                         break;
3695                 jpp = &jp1->prev_job;
3696         }
3697         *jpp = jp1->prev_job;
3698
3699         /* Then re-insert in correct position */
3700         jpp = curp;
3701         switch (mode) {
3702         default:
3703 #if DEBUG
3704                 abort();
3705 #endif
3706         case CUR_DELETE:
3707                 /* job being deleted */
3708                 break;
3709         case CUR_RUNNING:
3710                 /* newly created job or backgrounded job,
3711                  * put after all stopped jobs.
3712                  */
3713                 while (1) {
3714                         jp1 = *jpp;
3715 #if JOBS
3716                         if (!jp1 || jp1->state != JOBSTOPPED)
3717 #endif
3718                                 break;
3719                         jpp = &jp1->prev_job;
3720                 }
3721                 /* FALLTHROUGH */
3722 #if JOBS
3723         case CUR_STOPPED:
3724 #endif
3725                 /* newly stopped job - becomes curjob */
3726                 jp->prev_job = *jpp;
3727                 *jpp = jp;
3728                 break;
3729         }
3730 }
3731
3732 #if JOBS || DEBUG
3733 static int
3734 jobno(const struct job *jp)
3735 {
3736         return jp - jobtab + 1;
3737 }
3738 #endif
3739
3740 /*
3741  * Convert a job name to a job structure.
3742  */
3743 #if !JOBS
3744 #define getjob(name, getctl) getjob(name)
3745 #endif
3746 static struct job *
3747 getjob(const char *name, int getctl)
3748 {
3749         struct job *jp;
3750         struct job *found;
3751         const char *err_msg = "%s: no such job";
3752         unsigned num;
3753         int c;
3754         const char *p;
3755         char *(*match)(const char *, const char *);
3756
3757         jp = curjob;
3758         p = name;
3759         if (!p)
3760                 goto currentjob;
3761
3762         if (*p != '%')
3763                 goto err;
3764
3765         c = *++p;
3766         if (!c)
3767                 goto currentjob;
3768
3769         if (!p[1]) {
3770                 if (c == '+' || c == '%') {
3771  currentjob:
3772                         err_msg = "No current job";
3773                         goto check;
3774                 }
3775                 if (c == '-') {
3776                         if (jp)
3777                                 jp = jp->prev_job;
3778                         err_msg = "No previous job";
3779  check:
3780                         if (!jp)
3781                                 goto err;
3782                         goto gotit;
3783                 }
3784         }
3785
3786         if (is_number(p)) {
3787                 num = atoi(p);
3788                 if (num > 0 && num <= njobs) {
3789                         jp = jobtab + num - 1;
3790                         if (jp->used)
3791                                 goto gotit;
3792                         goto err;
3793                 }
3794         }
3795
3796         match = prefix;
3797         if (*p == '?') {
3798                 match = strstr;
3799                 p++;
3800         }
3801
3802         found = NULL;
3803         while (jp) {
3804                 if (match(jp->ps[0].ps_cmd, p)) {
3805                         if (found)
3806                                 goto err;
3807                         found = jp;
3808                         err_msg = "%s: ambiguous";
3809                 }
3810                 jp = jp->prev_job;
3811         }
3812         if (!found)
3813                 goto err;
3814         jp = found;
3815
3816  gotit:
3817 #if JOBS
3818         err_msg = "job %s not created under job control";
3819         if (getctl && jp->jobctl == 0)
3820                 goto err;
3821 #endif
3822         return jp;
3823  err:
3824         ash_msg_and_raise_error(err_msg, name);
3825 }
3826
3827 /*
3828  * Mark a job structure as unused.
3829  */
3830 static void
3831 freejob(struct job *jp)
3832 {
3833         struct procstat *ps;
3834         int i;
3835
3836         INT_OFF;
3837         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3838                 if (ps->ps_cmd != nullstr)
3839                         free(ps->ps_cmd);
3840         }
3841         if (jp->ps != &jp->ps0)
3842                 free(jp->ps);
3843         jp->used = 0;
3844         set_curjob(jp, CUR_DELETE);
3845         INT_ON;
3846 }
3847
3848 #if JOBS
3849 static void
3850 xtcsetpgrp(int fd, pid_t pgrp)
3851 {
3852         if (tcsetpgrp(fd, pgrp))
3853                 ash_msg_and_raise_error("can't set tty process group (%m)");
3854 }
3855
3856 /*
3857  * Turn job control on and off.
3858  *
3859  * Note:  This code assumes that the third arg to ioctl is a character
3860  * pointer, which is true on Berkeley systems but not System V.  Since
3861  * System V doesn't have job control yet, this isn't a problem now.
3862  *
3863  * Called with interrupts off.
3864  */
3865 static void
3866 setjobctl(int on)
3867 {
3868         int fd;
3869         int pgrp;
3870
3871         if (on == doing_jobctl || rootshell == 0)
3872                 return;
3873         if (on) {
3874                 int ofd;
3875                 ofd = fd = open(_PATH_TTY, O_RDWR);
3876                 if (fd < 0) {
3877         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3878          * That sometimes helps to acquire controlling tty.
3879          * Obviously, a workaround for bugs when someone
3880          * failed to provide a controlling tty to bash! :) */
3881                         fd = 2;
3882                         while (!isatty(fd))
3883                                 if (--fd < 0)
3884                                         goto out;
3885                 }
3886                 /* fd is a tty at this point */
3887                 fd = fcntl(fd, F_DUPFD, 10);
3888                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3889                         close(ofd);
3890                 if (fd < 0)
3891                         goto out; /* F_DUPFD failed */
3892                 close_on_exec_on(fd);
3893                 while (1) { /* while we are in the background */
3894                         pgrp = tcgetpgrp(fd);
3895                         if (pgrp < 0) {
3896  out:
3897                                 ash_msg("can't access tty; job control turned off");
3898                                 mflag = on = 0;
3899                                 goto close;
3900                         }
3901                         if (pgrp == getpgrp())
3902                                 break;
3903                         killpg(0, SIGTTIN);
3904                 }
3905                 initialpgrp = pgrp;
3906
3907                 setsignal(SIGTSTP);
3908                 setsignal(SIGTTOU);
3909                 setsignal(SIGTTIN);
3910                 pgrp = rootpid;
3911                 setpgid(0, pgrp);
3912                 xtcsetpgrp(fd, pgrp);
3913         } else {
3914                 /* turning job control off */
3915                 fd = ttyfd;
3916                 pgrp = initialpgrp;
3917                 /* was xtcsetpgrp, but this can make exiting ash
3918                  * loop forever if pty is already deleted */
3919                 tcsetpgrp(fd, pgrp);
3920                 setpgid(0, pgrp);
3921                 setsignal(SIGTSTP);
3922                 setsignal(SIGTTOU);
3923                 setsignal(SIGTTIN);
3924  close:
3925                 if (fd >= 0)
3926                         close(fd);
3927                 fd = -1;
3928         }
3929         ttyfd = fd;
3930         doing_jobctl = on;
3931 }
3932
3933 static int FAST_FUNC
3934 killcmd(int argc, char **argv)
3935 {
3936         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3937                 int i = 1;
3938                 do {
3939                         if (argv[i][0] == '%') {
3940                                 /*
3941                                  * "kill %N" - job kill
3942                                  * Converting to pgrp / pid kill
3943                                  */
3944                                 struct job *jp;
3945                                 char *dst;
3946                                 int j, n;
3947
3948                                 jp = getjob(argv[i], 0);
3949                                 /*
3950                                  * In jobs started under job control, we signal
3951                                  * entire process group by kill -PGRP_ID.
3952                                  * This happens, f.e., in interactive shell.
3953                                  *
3954                                  * Otherwise, we signal each child via
3955                                  * kill PID1 PID2 PID3.
3956                                  * Testcases:
3957                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3958                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3959                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3960                                  */
3961                                 n = jp->nprocs; /* can't be 0 (I hope) */
3962                                 if (jp->jobctl)
3963                                         n = 1;
3964                                 dst = alloca(n * sizeof(int)*4);
3965                                 argv[i] = dst;
3966                                 for (j = 0; j < n; j++) {
3967                                         struct procstat *ps = &jp->ps[j];
3968                                         /* Skip non-running and not-stopped members
3969                                          * (i.e. dead members) of the job
3970                                          */
3971                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3972                                                 continue;
3973                                         /*
3974                                          * kill_main has matching code to expect
3975                                          * leading space. Needed to not confuse
3976                                          * negative pids with "kill -SIGNAL_NO" syntax
3977                                          */
3978                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3979                                 }
3980                                 *dst = '\0';
3981                         }
3982                 } while (argv[++i]);
3983         }
3984         return kill_main(argc, argv);
3985 }
3986
3987 static void
3988 showpipe(struct job *jp /*, FILE *out*/)
3989 {
3990         struct procstat *ps;
3991         struct procstat *psend;
3992
3993         psend = jp->ps + jp->nprocs;
3994         for (ps = jp->ps + 1; ps < psend; ps++)
3995                 printf(" | %s", ps->ps_cmd);
3996         newline_and_flush(stdout);
3997         flush_stdout_stderr();
3998 }
3999
4000
4001 static int
4002 restartjob(struct job *jp, int mode)
4003 {
4004         struct procstat *ps;
4005         int i;
4006         int status;
4007         pid_t pgid;
4008
4009         INT_OFF;
4010         if (jp->state == JOBDONE)
4011                 goto out;
4012         jp->state = JOBRUNNING;
4013         pgid = jp->ps[0].ps_pid;
4014         if (mode == FORK_FG) {
4015                 get_tty_state();
4016                 xtcsetpgrp(ttyfd, pgid);
4017         }
4018         killpg(pgid, SIGCONT);
4019         ps = jp->ps;
4020         i = jp->nprocs;
4021         do {
4022                 if (WIFSTOPPED(ps->ps_status)) {
4023                         ps->ps_status = -1;
4024                 }
4025                 ps++;
4026         } while (--i);
4027  out:
4028         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4029         INT_ON;
4030         return status;
4031 }
4032
4033 static int FAST_FUNC
4034 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4035 {
4036         struct job *jp;
4037         int mode;
4038         int retval;
4039
4040         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4041         nextopt(nullstr);
4042         argv = argptr;
4043         do {
4044                 jp = getjob(*argv, 1);
4045                 if (mode == FORK_BG) {
4046                         set_curjob(jp, CUR_RUNNING);
4047                         printf("[%d] ", jobno(jp));
4048                 }
4049                 out1str(jp->ps[0].ps_cmd);
4050                 showpipe(jp /*, stdout*/);
4051                 retval = restartjob(jp, mode);
4052         } while (*argv && *++argv);
4053         return retval;
4054 }
4055 #endif
4056
4057 static int
4058 sprint_status48(char *s, int status, int sigonly)
4059 {
4060         int col;
4061         int st;
4062
4063         col = 0;
4064         if (!WIFEXITED(status)) {
4065 #if JOBS
4066                 if (WIFSTOPPED(status))
4067                         st = WSTOPSIG(status);
4068                 else
4069 #endif
4070                         st = WTERMSIG(status);
4071                 if (sigonly) {
4072                         if (st == SIGINT || st == SIGPIPE)
4073                                 goto out;
4074 #if JOBS
4075                         if (WIFSTOPPED(status))
4076                                 goto out;
4077 #endif
4078                 }
4079                 st &= 0x7f;
4080 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4081                 col = fmtstr(s, 32, strsignal(st));
4082                 if (WCOREDUMP(status)) {
4083                         strcpy(s + col, " (core dumped)");
4084                         col += sizeof(" (core dumped)")-1;
4085                 }
4086         } else if (!sigonly) {
4087                 st = WEXITSTATUS(status);
4088                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4089         }
4090  out:
4091         return col;
4092 }
4093
4094 static int
4095 wait_block_or_sig(int *status)
4096 {
4097         int pid;
4098
4099         do {
4100                 sigset_t mask;
4101
4102                 /* Poll all children for changes in their state */
4103                 got_sigchld = 0;
4104                 /* if job control is active, accept stopped processes too */
4105                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4106                 if (pid != 0)
4107                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4108
4109                 /* Children exist, but none are ready. Sleep until interesting signal */
4110 #if 1
4111                 sigfillset(&mask);
4112                 sigprocmask(SIG_SETMASK, &mask, &mask);
4113                 while (!got_sigchld && !pending_sig)
4114                         sigsuspend(&mask);
4115                 sigprocmask(SIG_SETMASK, &mask, NULL);
4116 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4117                 while (!got_sigchld && !pending_sig)
4118                         pause();
4119 #endif
4120
4121                 /* If it was SIGCHLD, poll children again */
4122         } while (got_sigchld);
4123
4124         return pid;
4125 }
4126
4127 #define DOWAIT_NONBLOCK 0
4128 #define DOWAIT_BLOCK    1
4129 #define DOWAIT_BLOCK_OR_SIG 2
4130
4131 static int
4132 dowait(int block, struct job *job)
4133 {
4134         int pid;
4135         int status;
4136         struct job *jp;
4137         struct job *thisjob = NULL;
4138
4139         TRACE(("dowait(0x%x) called\n", block));
4140
4141         /* It's wrong to call waitpid() outside of INT_OFF region:
4142          * signal can arrive just after syscall return and handler can
4143          * longjmp away, losing stop/exit notification processing.
4144          * Thus, for "jobs" builtin, and for waiting for a fg job,
4145          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4146          *
4147          * However, for "wait" builtin it is wrong to simply call waitpid()
4148          * in INT_OFF region: "wait" needs to wait for any running job
4149          * to change state, but should exit on any trap too.
4150          * In INT_OFF region, a signal just before syscall entry can set
4151          * pending_sig variables, but we can't check them, and we would
4152          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4153          *
4154          * Because of this, we run inside INT_OFF, but use a special routine
4155          * which combines waitpid() and sigsuspend().
4156          * This is the reason why we need to have a handler for SIGCHLD:
4157          * SIG_DFL handler does not wake sigsuspend().
4158          */
4159         INT_OFF;
4160         if (block == DOWAIT_BLOCK_OR_SIG) {
4161                 pid = wait_block_or_sig(&status);
4162         } else {
4163                 int wait_flags = 0;
4164                 if (block == DOWAIT_NONBLOCK)
4165                         wait_flags = WNOHANG;
4166                 /* if job control is active, accept stopped processes too */
4167                 if (doing_jobctl)
4168                         wait_flags |= WUNTRACED;
4169                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4170                 pid = waitpid(-1, &status, wait_flags);
4171         }
4172         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4173                                 pid, status, errno, strerror(errno)));
4174         if (pid <= 0)
4175                 goto out;
4176
4177         thisjob = NULL;
4178         for (jp = curjob; jp; jp = jp->prev_job) {
4179                 int jobstate;
4180                 struct procstat *ps;
4181                 struct procstat *psend;
4182                 if (jp->state == JOBDONE)
4183                         continue;
4184                 jobstate = JOBDONE;
4185                 ps = jp->ps;
4186                 psend = ps + jp->nprocs;
4187                 do {
4188                         if (ps->ps_pid == pid) {
4189                                 TRACE(("Job %d: changing status of proc %d "
4190                                         "from 0x%x to 0x%x\n",
4191                                         jobno(jp), pid, ps->ps_status, status));
4192                                 ps->ps_status = status;
4193                                 thisjob = jp;
4194                         }
4195                         if (ps->ps_status == -1)
4196                                 jobstate = JOBRUNNING;
4197 #if JOBS
4198                         if (jobstate == JOBRUNNING)
4199                                 continue;
4200                         if (WIFSTOPPED(ps->ps_status)) {
4201                                 jp->stopstatus = ps->ps_status;
4202                                 jobstate = JOBSTOPPED;
4203                         }
4204 #endif
4205                 } while (++ps < psend);
4206                 if (!thisjob)
4207                         continue;
4208
4209                 /* Found the job where one of its processes changed its state.
4210                  * Is there at least one live and running process in this job? */
4211                 if (jobstate != JOBRUNNING) {
4212                         /* No. All live processes in the job are stopped
4213                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4214                          */
4215                         thisjob->changed = 1;
4216                         if (thisjob->state != jobstate) {
4217                                 TRACE(("Job %d: changing state from %d to %d\n",
4218                                         jobno(thisjob), thisjob->state, jobstate));
4219                                 thisjob->state = jobstate;
4220 #if JOBS
4221                                 if (jobstate == JOBSTOPPED)
4222                                         set_curjob(thisjob, CUR_STOPPED);
4223 #endif
4224                         }
4225                 }
4226                 goto out;
4227         }
4228         /* The process wasn't found in job list */
4229 #if JOBS
4230         if (!WIFSTOPPED(status))
4231                 jobless--;
4232 #endif
4233  out:
4234         INT_ON;
4235
4236         if (thisjob && thisjob == job) {
4237                 char s[48 + 1];
4238                 int len;
4239
4240                 len = sprint_status48(s, status, 1);
4241                 if (len) {
4242                         s[len] = '\n';
4243                         s[len + 1] = '\0';
4244                         out2str(s);
4245                 }
4246         }
4247         return pid;
4248 }
4249
4250 #if JOBS
4251 static void
4252 showjob(struct job *jp, int mode)
4253 {
4254         struct procstat *ps;
4255         struct procstat *psend;
4256         int col;
4257         int indent_col;
4258         char s[16 + 16 + 48];
4259         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4260
4261         ps = jp->ps;
4262
4263         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4264                 /* just output process (group) id of pipeline */
4265                 fprintf(out, "%d\n", ps->ps_pid);
4266                 return;
4267         }
4268
4269         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4270         indent_col = col;
4271
4272         if (jp == curjob)
4273                 s[col - 3] = '+';
4274         else if (curjob && jp == curjob->prev_job)
4275                 s[col - 3] = '-';
4276
4277         if (mode & SHOW_PIDS)
4278                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4279
4280         psend = ps + jp->nprocs;
4281
4282         if (jp->state == JOBRUNNING) {
4283                 strcpy(s + col, "Running");
4284                 col += sizeof("Running") - 1;
4285         } else {
4286                 int status = psend[-1].ps_status;
4287                 if (jp->state == JOBSTOPPED)
4288                         status = jp->stopstatus;
4289                 col += sprint_status48(s + col, status, 0);
4290         }
4291         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4292
4293         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4294          * or prints several "PID             | <cmdN>" lines,
4295          * depending on SHOW_PIDS bit.
4296          * We do not print status of individual processes
4297          * between PID and <cmdN>. bash does it, but not very well:
4298          * first line shows overall job status, not process status,
4299          * making it impossible to know 1st process status.
4300          */
4301         goto start;
4302         do {
4303                 /* for each process */
4304                 s[0] = '\0';
4305                 col = 33;
4306                 if (mode & SHOW_PIDS)
4307                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4308  start:
4309                 fprintf(out, "%s%*c%s%s",
4310                                 s,
4311                                 33 - col >= 0 ? 33 - col : 0, ' ',
4312                                 ps == jp->ps ? "" : "| ",
4313                                 ps->ps_cmd
4314                 );
4315         } while (++ps != psend);
4316         newline_and_flush(out);
4317
4318         jp->changed = 0;
4319
4320         if (jp->state == JOBDONE) {
4321                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4322                 freejob(jp);
4323         }
4324 }
4325
4326 /*
4327  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4328  * statuses have changed since the last call to showjobs.
4329  */
4330 static void
4331 showjobs(int mode)
4332 {
4333         struct job *jp;
4334
4335         TRACE(("showjobs(0x%x) called\n", mode));
4336
4337         /* Handle all finished jobs */
4338         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4339                 continue;
4340
4341         for (jp = curjob; jp; jp = jp->prev_job) {
4342                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4343                         showjob(jp, mode);
4344                 }
4345         }
4346 }
4347
4348 static int FAST_FUNC
4349 jobscmd(int argc UNUSED_PARAM, char **argv)
4350 {
4351         int mode, m;
4352
4353         mode = 0;
4354         while ((m = nextopt("lp")) != '\0') {
4355                 if (m == 'l')
4356                         mode |= SHOW_PIDS;
4357                 else
4358                         mode |= SHOW_ONLY_PGID;
4359         }
4360
4361         argv = argptr;
4362         if (*argv) {
4363                 do
4364                         showjob(getjob(*argv, 0), mode);
4365                 while (*++argv);
4366         } else {
4367                 showjobs(mode);
4368         }
4369
4370         return 0;
4371 }
4372 #endif /* JOBS */
4373
4374 /* Called only on finished or stopped jobs (no members are running) */
4375 static int
4376 getstatus(struct job *job)
4377 {
4378         int status;
4379         int retval;
4380         struct procstat *ps;
4381
4382         /* Fetch last member's status */
4383         ps = job->ps + job->nprocs - 1;
4384         status = ps->ps_status;
4385         if (pipefail) {
4386                 /* "set -o pipefail" mode: use last _nonzero_ status */
4387                 while (status == 0 && --ps >= job->ps)
4388                         status = ps->ps_status;
4389         }
4390
4391         retval = WEXITSTATUS(status);
4392         if (!WIFEXITED(status)) {
4393 #if JOBS
4394                 retval = WSTOPSIG(status);
4395                 if (!WIFSTOPPED(status))
4396 #endif
4397                 {
4398                         /* XXX: limits number of signals */
4399                         retval = WTERMSIG(status);
4400 #if JOBS
4401                         if (retval == SIGINT)
4402                                 job->sigint = 1;
4403 #endif
4404                 }
4405                 retval += 128;
4406         }
4407         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4408                 jobno(job), job->nprocs, status, retval));
4409         return retval;
4410 }
4411
4412 static int FAST_FUNC
4413 waitcmd(int argc UNUSED_PARAM, char **argv)
4414 {
4415         struct job *job;
4416         int retval;
4417         struct job *jp;
4418
4419         nextopt(nullstr);
4420         retval = 0;
4421
4422         argv = argptr;
4423         if (!*argv) {
4424                 /* wait for all jobs */
4425                 for (;;) {
4426                         jp = curjob;
4427                         while (1) {
4428                                 if (!jp) /* no running procs */
4429                                         goto ret;
4430                                 if (jp->state == JOBRUNNING)
4431                                         break;
4432                                 jp->waited = 1;
4433                                 jp = jp->prev_job;
4434                         }
4435         /* man bash:
4436          * "When bash is waiting for an asynchronous command via
4437          * the wait builtin, the reception of a signal for which a trap
4438          * has been set will cause the wait builtin to return immediately
4439          * with an exit status greater than 128, immediately after which
4440          * the trap is executed."
4441          */
4442                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4443         /* if child sends us a signal *and immediately exits*,
4444          * dowait() returns pid > 0. Check this case,
4445          * not "if (dowait() < 0)"!
4446          */
4447                         if (pending_sig)
4448                                 goto sigout;
4449                 }
4450         }
4451
4452         retval = 127;
4453         do {
4454                 if (**argv != '%') {
4455                         pid_t pid = number(*argv);
4456                         job = curjob;
4457                         while (1) {
4458                                 if (!job)
4459                                         goto repeat;
4460                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4461                                         break;
4462                                 job = job->prev_job;
4463                         }
4464                 } else {
4465                         job = getjob(*argv, 0);
4466                 }
4467                 /* loop until process terminated or stopped */
4468                 while (job->state == JOBRUNNING) {
4469                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4470                         if (pending_sig)
4471                                 goto sigout;
4472                 }
4473                 job->waited = 1;
4474                 retval = getstatus(job);
4475  repeat: ;
4476         } while (*++argv);
4477
4478  ret:
4479         return retval;
4480  sigout:
4481         retval = 128 + pending_sig;
4482         return retval;
4483 }
4484
4485 static struct job *
4486 growjobtab(void)
4487 {
4488         size_t len;
4489         ptrdiff_t offset;
4490         struct job *jp, *jq;
4491
4492         len = njobs * sizeof(*jp);
4493         jq = jobtab;
4494         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4495
4496         offset = (char *)jp - (char *)jq;
4497         if (offset) {
4498                 /* Relocate pointers */
4499                 size_t l = len;
4500
4501                 jq = (struct job *)((char *)jq + l);
4502                 while (l) {
4503                         l -= sizeof(*jp);
4504                         jq--;
4505 #define joff(p) ((struct job *)((char *)(p) + l))
4506 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4507                         if (joff(jp)->ps == &jq->ps0)
4508                                 jmove(joff(jp)->ps);
4509                         if (joff(jp)->prev_job)
4510                                 jmove(joff(jp)->prev_job);
4511                 }
4512                 if (curjob)
4513                         jmove(curjob);
4514 #undef joff
4515 #undef jmove
4516         }
4517
4518         njobs += 4;
4519         jobtab = jp;
4520         jp = (struct job *)((char *)jp + len);
4521         jq = jp + 3;
4522         do {
4523                 jq->used = 0;
4524         } while (--jq >= jp);
4525         return jp;
4526 }
4527
4528 /*
4529  * Return a new job structure.
4530  * Called with interrupts off.
4531  */
4532 static struct job *
4533 makejob(/*union node *node,*/ int nprocs)
4534 {
4535         int i;
4536         struct job *jp;
4537
4538         for (i = njobs, jp = jobtab; ; jp++) {
4539                 if (--i < 0) {
4540                         jp = growjobtab();
4541                         break;
4542                 }
4543                 if (jp->used == 0)
4544                         break;
4545                 if (jp->state != JOBDONE || !jp->waited)
4546                         continue;
4547 #if JOBS
4548                 if (doing_jobctl)
4549                         continue;
4550 #endif
4551                 freejob(jp);
4552                 break;
4553         }
4554         memset(jp, 0, sizeof(*jp));
4555 #if JOBS
4556         /* jp->jobctl is a bitfield.
4557          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4558         if (doing_jobctl)
4559                 jp->jobctl = 1;
4560 #endif
4561         jp->prev_job = curjob;
4562         curjob = jp;
4563         jp->used = 1;
4564         jp->ps = &jp->ps0;
4565         if (nprocs > 1) {
4566                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4567         }
4568         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4569                                 jobno(jp)));
4570         return jp;
4571 }
4572
4573 #if JOBS
4574 /*
4575  * Return a string identifying a command (to be printed by the
4576  * jobs command).
4577  */
4578 static char *cmdnextc;
4579
4580 static void
4581 cmdputs(const char *s)
4582 {
4583         static const char vstype[VSTYPE + 1][3] = {
4584                 "", "}", "-", "+", "?", "=",
4585                 "%", "%%", "#", "##"
4586                 IF_BASH_SUBSTR(, ":")
4587                 IF_BASH_PATTERN_SUBST(, "/", "//")
4588         };
4589
4590         const char *p, *str;
4591         char cc[2];
4592         char *nextc;
4593         unsigned char c;
4594         unsigned char subtype = 0;
4595         int quoted = 0;
4596
4597         cc[1] = '\0';
4598         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4599         p = s;
4600         while ((c = *p++) != '\0') {
4601                 str = NULL;
4602                 switch (c) {
4603                 case CTLESC:
4604                         c = *p++;
4605                         break;
4606                 case CTLVAR:
4607                         subtype = *p++;
4608                         if ((subtype & VSTYPE) == VSLENGTH)
4609                                 str = "${#";
4610                         else
4611                                 str = "${";
4612                         goto dostr;
4613                 case CTLENDVAR:
4614                         str = "\"}" + !(quoted & 1);
4615                         quoted >>= 1;
4616                         subtype = 0;
4617                         goto dostr;
4618                 case CTLBACKQ:
4619                         str = "$(...)";
4620                         goto dostr;
4621 #if ENABLE_FEATURE_SH_MATH
4622                 case CTLARI:
4623                         str = "$((";
4624                         goto dostr;
4625                 case CTLENDARI:
4626                         str = "))";
4627                         goto dostr;
4628 #endif
4629                 case CTLQUOTEMARK:
4630                         quoted ^= 1;
4631                         c = '"';
4632                         break;
4633                 case '=':
4634                         if (subtype == 0)
4635                                 break;
4636                         if ((subtype & VSTYPE) != VSNORMAL)
4637                                 quoted <<= 1;
4638                         str = vstype[subtype & VSTYPE];
4639                         if (subtype & VSNUL)
4640                                 c = ':';
4641                         else
4642                                 goto checkstr;
4643                         break;
4644                 case '\'':
4645                 case '\\':
4646                 case '"':
4647                 case '$':
4648                         /* These can only happen inside quotes */
4649                         cc[0] = c;
4650                         str = cc;
4651                         c = '\\';
4652                         break;
4653                 default:
4654                         break;
4655                 }
4656                 USTPUTC(c, nextc);
4657  checkstr:
4658                 if (!str)
4659                         continue;
4660  dostr:
4661                 while ((c = *str++) != '\0') {
4662                         USTPUTC(c, nextc);
4663                 }
4664         } /* while *p++ not NUL */
4665
4666         if (quoted & 1) {
4667                 USTPUTC('"', nextc);
4668         }
4669         *nextc = 0;
4670         cmdnextc = nextc;
4671 }
4672
4673 /* cmdtxt() and cmdlist() call each other */
4674 static void cmdtxt(union node *n);
4675
4676 static void
4677 cmdlist(union node *np, int sep)
4678 {
4679         for (; np; np = np->narg.next) {
4680                 if (!sep)
4681                         cmdputs(" ");
4682                 cmdtxt(np);
4683                 if (sep && np->narg.next)
4684                         cmdputs(" ");
4685         }
4686 }
4687
4688 static void
4689 cmdtxt(union node *n)
4690 {
4691         union node *np;
4692         struct nodelist *lp;
4693         const char *p;
4694
4695         if (!n)
4696                 return;
4697         switch (n->type) {
4698         default:
4699 #if DEBUG
4700                 abort();
4701 #endif
4702         case NPIPE:
4703                 lp = n->npipe.cmdlist;
4704                 for (;;) {
4705                         cmdtxt(lp->n);
4706                         lp = lp->next;
4707                         if (!lp)
4708                                 break;
4709                         cmdputs(" | ");
4710                 }
4711                 break;
4712         case NSEMI:
4713                 p = "; ";
4714                 goto binop;
4715         case NAND:
4716                 p = " && ";
4717                 goto binop;
4718         case NOR:
4719                 p = " || ";
4720  binop:
4721                 cmdtxt(n->nbinary.ch1);
4722                 cmdputs(p);
4723                 n = n->nbinary.ch2;
4724                 goto donode;
4725         case NREDIR:
4726         case NBACKGND:
4727                 n = n->nredir.n;
4728                 goto donode;
4729         case NNOT:
4730                 cmdputs("!");
4731                 n = n->nnot.com;
4732  donode:
4733                 cmdtxt(n);
4734                 break;
4735         case NIF:
4736                 cmdputs("if ");
4737                 cmdtxt(n->nif.test);
4738                 cmdputs("; then ");
4739                 if (n->nif.elsepart) {
4740                         cmdtxt(n->nif.ifpart);
4741                         cmdputs("; else ");
4742                         n = n->nif.elsepart;
4743                 } else {
4744                         n = n->nif.ifpart;
4745                 }
4746                 p = "; fi";
4747                 goto dotail;
4748         case NSUBSHELL:
4749                 cmdputs("(");
4750                 n = n->nredir.n;
4751                 p = ")";
4752                 goto dotail;
4753         case NWHILE:
4754                 p = "while ";
4755                 goto until;
4756         case NUNTIL:
4757                 p = "until ";
4758  until:
4759                 cmdputs(p);
4760                 cmdtxt(n->nbinary.ch1);
4761                 n = n->nbinary.ch2;
4762                 p = "; done";
4763  dodo:
4764                 cmdputs("; do ");
4765  dotail:
4766                 cmdtxt(n);
4767                 goto dotail2;
4768         case NFOR:
4769                 cmdputs("for ");
4770                 cmdputs(n->nfor.var);
4771                 cmdputs(" in ");
4772                 cmdlist(n->nfor.args, 1);
4773                 n = n->nfor.body;
4774                 p = "; done";
4775                 goto dodo;
4776         case NDEFUN:
4777                 cmdputs(n->narg.text);
4778                 p = "() { ... }";
4779                 goto dotail2;
4780         case NCMD:
4781                 cmdlist(n->ncmd.args, 1);
4782                 cmdlist(n->ncmd.redirect, 0);
4783                 break;
4784         case NARG:
4785                 p = n->narg.text;
4786  dotail2:
4787                 cmdputs(p);
4788                 break;
4789         case NHERE:
4790         case NXHERE:
4791                 p = "<<...";
4792                 goto dotail2;
4793         case NCASE:
4794                 cmdputs("case ");
4795                 cmdputs(n->ncase.expr->narg.text);
4796                 cmdputs(" in ");
4797                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4798                         cmdtxt(np->nclist.pattern);
4799                         cmdputs(") ");
4800                         cmdtxt(np->nclist.body);
4801                         cmdputs(";; ");
4802                 }
4803                 p = "esac";
4804                 goto dotail2;
4805         case NTO:
4806                 p = ">";
4807                 goto redir;
4808         case NCLOBBER:
4809                 p = ">|";
4810                 goto redir;
4811         case NAPPEND:
4812                 p = ">>";
4813                 goto redir;
4814 #if BASH_REDIR_OUTPUT
4815         case NTO2:
4816 #endif
4817         case NTOFD:
4818                 p = ">&";
4819                 goto redir;
4820         case NFROM:
4821                 p = "<";
4822                 goto redir;
4823         case NFROMFD:
4824                 p = "<&";
4825                 goto redir;
4826         case NFROMTO:
4827                 p = "<>";
4828  redir:
4829                 cmdputs(utoa(n->nfile.fd));
4830                 cmdputs(p);
4831                 if (n->type == NTOFD || n->type == NFROMFD) {
4832                         cmdputs(utoa(n->ndup.dupfd));
4833                         break;
4834                 }
4835                 n = n->nfile.fname;
4836                 goto donode;
4837         }
4838 }
4839
4840 static char *
4841 commandtext(union node *n)
4842 {
4843         char *name;
4844
4845         STARTSTACKSTR(cmdnextc);
4846         cmdtxt(n);
4847         name = stackblock();
4848         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4849         return ckstrdup(name);
4850 }
4851 #endif /* JOBS */
4852
4853 /*
4854  * Fork off a subshell.  If we are doing job control, give the subshell its
4855  * own process group.  Jp is a job structure that the job is to be added to.
4856  * N is the command that will be evaluated by the child.  Both jp and n may
4857  * be NULL.  The mode parameter can be one of the following:
4858  *      FORK_FG - Fork off a foreground process.
4859  *      FORK_BG - Fork off a background process.
4860  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4861  *                   process group even if job control is on.
4862  *
4863  * When job control is turned off, background processes have their standard
4864  * input redirected to /dev/null (except for the second and later processes
4865  * in a pipeline).
4866  *
4867  * Called with interrupts off.
4868  */
4869 /*
4870  * Clear traps on a fork.
4871  */
4872 static void
4873 clear_traps(void)
4874 {
4875         char **tp;
4876
4877         INT_OFF;
4878         for (tp = trap; tp < &trap[NSIG]; tp++) {
4879                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4880                         if (trap_ptr == trap)
4881                                 free(*tp);
4882                         /* else: it "belongs" to trap_ptr vector, don't free */
4883                         *tp = NULL;
4884                         if ((tp - trap) != 0)
4885                                 setsignal(tp - trap);
4886                 }
4887         }
4888         may_have_traps = 0;
4889         INT_ON;
4890 }
4891
4892 /* Lives far away from here, needed for forkchild */
4893 static void closescript(void);
4894
4895 /* Called after fork(), in child */
4896 /* jp and n are NULL when called by openhere() for heredoc support */
4897 static NOINLINE void
4898 forkchild(struct job *jp, union node *n, int mode)
4899 {
4900         int oldlvl;
4901
4902         TRACE(("Child shell %d\n", getpid()));
4903         oldlvl = shlvl;
4904         shlvl++;
4905
4906         /* man bash: "Non-builtin commands run by bash have signal handlers
4907          * set to the values inherited by the shell from its parent".
4908          * Do we do it correctly? */
4909
4910         closescript();
4911
4912         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4913          && n && n->type == NCMD        /* is it single cmd? */
4914         /* && n->ncmd.args->type == NARG - always true? */
4915          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4916          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4917         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4918         ) {
4919                 TRACE(("Trap hack\n"));
4920                 /* Awful hack for `trap` or $(trap).
4921                  *
4922                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4923                  * contains an example where "trap" is executed in a subshell:
4924                  *
4925                  * save_traps=$(trap)
4926                  * ...
4927                  * eval "$save_traps"
4928                  *
4929                  * Standard does not say that "trap" in subshell shall print
4930                  * parent shell's traps. It only says that its output
4931                  * must have suitable form, but then, in the above example
4932                  * (which is not supposed to be normative), it implies that.
4933                  *
4934                  * bash (and probably other shell) does implement it
4935                  * (traps are reset to defaults, but "trap" still shows them),
4936                  * but as a result, "trap" logic is hopelessly messed up:
4937                  *
4938                  * # trap
4939                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4940                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4941                  * # true | trap   <--- trap is in subshell - no output (ditto)
4942                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4943                  * trap -- 'echo Ho' SIGWINCH
4944                  * # echo `(trap)`         <--- in subshell in subshell - output
4945                  * trap -- 'echo Ho' SIGWINCH
4946                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4947                  * trap -- 'echo Ho' SIGWINCH
4948                  *
4949                  * The rules when to forget and when to not forget traps
4950                  * get really complex and nonsensical.
4951                  *
4952                  * Our solution: ONLY bare $(trap) or `trap` is special.
4953                  */
4954                 /* Save trap handler strings for trap builtin to print */
4955                 trap_ptr = xmemdup(trap, sizeof(trap));
4956                 /* Fall through into clearing traps */
4957         }
4958         clear_traps();
4959 #if JOBS
4960         /* do job control only in root shell */
4961         doing_jobctl = 0;
4962         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4963                 pid_t pgrp;
4964
4965                 if (jp->nprocs == 0)
4966                         pgrp = getpid();
4967                 else
4968                         pgrp = jp->ps[0].ps_pid;
4969                 /* this can fail because we are doing it in the parent also */
4970                 setpgid(0, pgrp);
4971                 if (mode == FORK_FG)
4972                         xtcsetpgrp(ttyfd, pgrp);
4973                 setsignal(SIGTSTP);
4974                 setsignal(SIGTTOU);
4975         } else
4976 #endif
4977         if (mode == FORK_BG) {
4978                 /* man bash: "When job control is not in effect,
4979                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4980                 ignoresig(SIGINT);
4981                 ignoresig(SIGQUIT);
4982                 if (jp->nprocs == 0) {
4983                         close(0);
4984                         if (open(bb_dev_null, O_RDONLY) != 0)
4985                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4986                 }
4987         }
4988         if (oldlvl == 0) {
4989                 if (iflag) { /* why if iflag only? */
4990                         setsignal(SIGINT);
4991                         setsignal(SIGTERM);
4992                 }
4993                 /* man bash:
4994                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4995                  * commands run by bash have signal handlers
4996                  * set to the values inherited by the shell
4997                  * from its parent".
4998                  * Take care of the second rule: */
4999                 setsignal(SIGQUIT);
5000         }
5001 #if JOBS
5002         if (n && n->type == NCMD
5003          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5004         ) {
5005                 TRACE(("Job hack\n"));
5006                 /* "jobs": we do not want to clear job list for it,
5007                  * instead we remove only _its_ own_ job from job list.
5008                  * This makes "jobs .... | cat" more useful.
5009                  */
5010                 freejob(curjob);
5011                 return;
5012         }
5013 #endif
5014         for (jp = curjob; jp; jp = jp->prev_job)
5015                 freejob(jp);
5016         jobless = 0;
5017 }
5018
5019 /* Called after fork(), in parent */
5020 #if !JOBS
5021 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5022 #endif
5023 static void
5024 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5025 {
5026         TRACE(("In parent shell: child = %d\n", pid));
5027         if (!jp) {
5028                 /* jp is NULL when called by openhere() for heredoc support */
5029                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5030                         continue;
5031                 jobless++;
5032                 return;
5033         }
5034 #if JOBS
5035         if (mode != FORK_NOJOB && jp->jobctl) {
5036                 int pgrp;
5037
5038                 if (jp->nprocs == 0)
5039                         pgrp = pid;
5040                 else
5041                         pgrp = jp->ps[0].ps_pid;
5042                 /* This can fail because we are doing it in the child also */
5043                 setpgid(pid, pgrp);
5044         }
5045 #endif
5046         if (mode == FORK_BG) {
5047                 backgndpid = pid;               /* set $! */
5048                 set_curjob(jp, CUR_RUNNING);
5049         }
5050         if (jp) {
5051                 struct procstat *ps = &jp->ps[jp->nprocs++];
5052                 ps->ps_pid = pid;
5053                 ps->ps_status = -1;
5054                 ps->ps_cmd = nullstr;
5055 #if JOBS
5056                 if (doing_jobctl && n)
5057                         ps->ps_cmd = commandtext(n);
5058 #endif
5059         }
5060 }
5061
5062 /* jp and n are NULL when called by openhere() for heredoc support */
5063 static int
5064 forkshell(struct job *jp, union node *n, int mode)
5065 {
5066         int pid;
5067
5068         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5069         pid = fork();
5070         if (pid < 0) {
5071                 TRACE(("Fork failed, errno=%d", errno));
5072                 if (jp)
5073                         freejob(jp);
5074                 ash_msg_and_raise_error("can't fork");
5075         }
5076         if (pid == 0) {
5077                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5078                 forkchild(jp, n, mode);
5079         } else {
5080                 forkparent(jp, n, mode, pid);
5081         }
5082         return pid;
5083 }
5084
5085 /*
5086  * Wait for job to finish.
5087  *
5088  * Under job control we have the problem that while a child process
5089  * is running interrupts generated by the user are sent to the child
5090  * but not to the shell.  This means that an infinite loop started by
5091  * an interactive user may be hard to kill.  With job control turned off,
5092  * an interactive user may place an interactive program inside a loop.
5093  * If the interactive program catches interrupts, the user doesn't want
5094  * these interrupts to also abort the loop.  The approach we take here
5095  * is to have the shell ignore interrupt signals while waiting for a
5096  * foreground process to terminate, and then send itself an interrupt
5097  * signal if the child process was terminated by an interrupt signal.
5098  * Unfortunately, some programs want to do a bit of cleanup and then
5099  * exit on interrupt; unless these processes terminate themselves by
5100  * sending a signal to themselves (instead of calling exit) they will
5101  * confuse this approach.
5102  *
5103  * Called with interrupts off.
5104  */
5105 static int
5106 waitforjob(struct job *jp)
5107 {
5108         int st;
5109
5110         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5111
5112         INT_OFF;
5113         while (jp->state == JOBRUNNING) {
5114                 /* In non-interactive shells, we _can_ get
5115                  * a keyboard signal here and be EINTRed,
5116                  * but we just loop back, waiting for command to complete.
5117                  *
5118                  * man bash:
5119                  * "If bash is waiting for a command to complete and receives
5120                  * a signal for which a trap has been set, the trap
5121                  * will not be executed until the command completes."
5122                  *
5123                  * Reality is that even if trap is not set, bash
5124                  * will not act on the signal until command completes.
5125                  * Try this. sleep5intoff.c:
5126                  * #include <signal.h>
5127                  * #include <unistd.h>
5128                  * int main() {
5129                  *         sigset_t set;
5130                  *         sigemptyset(&set);
5131                  *         sigaddset(&set, SIGINT);
5132                  *         sigaddset(&set, SIGQUIT);
5133                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5134                  *         sleep(5);
5135                  *         return 0;
5136                  * }
5137                  * $ bash -c './sleep5intoff; echo hi'
5138                  * ^C^C^C^C <--- pressing ^C once a second
5139                  * $ _
5140                  * $ bash -c './sleep5intoff; echo hi'
5141                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5142                  * $ _
5143                  */
5144                 dowait(DOWAIT_BLOCK, jp);
5145         }
5146         INT_ON;
5147
5148         st = getstatus(jp);
5149 #if JOBS
5150         if (jp->jobctl) {
5151                 xtcsetpgrp(ttyfd, rootpid);
5152                 restore_tty_if_stopped_or_signaled(jp);
5153
5154                 /*
5155                  * This is truly gross.
5156                  * If we're doing job control, then we did a TIOCSPGRP which
5157                  * caused us (the shell) to no longer be in the controlling
5158                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5159                  * intuit from the subprocess exit status whether a SIGINT
5160                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5161                  */
5162                 if (jp->sigint) /* TODO: do the same with all signals */
5163                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5164         }
5165         if (jp->state == JOBDONE)
5166 #endif
5167                 freejob(jp);
5168         return st;
5169 }
5170
5171 /*
5172  * return 1 if there are stopped jobs, otherwise 0
5173  */
5174 static int
5175 stoppedjobs(void)
5176 {
5177         struct job *jp;
5178         int retval;
5179
5180         retval = 0;
5181         if (job_warning)
5182                 goto out;
5183         jp = curjob;
5184         if (jp && jp->state == JOBSTOPPED) {
5185                 out2str("You have stopped jobs.\n");
5186                 job_warning = 2;
5187                 retval++;
5188         }
5189  out:
5190         return retval;
5191 }
5192
5193
5194 /*
5195  * Code for dealing with input/output redirection.
5196  */
5197
5198 #undef EMPTY
5199 #undef CLOSED
5200 #define EMPTY -2                /* marks an unused slot in redirtab */
5201 #define CLOSED -3               /* marks a slot of previously-closed fd */
5202
5203 /*
5204  * Open a file in noclobber mode.
5205  * The code was copied from bash.
5206  */
5207 static int
5208 noclobberopen(const char *fname)
5209 {
5210         int r, fd;
5211         struct stat finfo, finfo2;
5212
5213         /*
5214          * If the file exists and is a regular file, return an error
5215          * immediately.
5216          */
5217         r = stat(fname, &finfo);
5218         if (r == 0 && S_ISREG(finfo.st_mode)) {
5219                 errno = EEXIST;
5220                 return -1;
5221         }
5222
5223         /*
5224          * If the file was not present (r != 0), make sure we open it
5225          * exclusively so that if it is created before we open it, our open
5226          * will fail.  Make sure that we do not truncate an existing file.
5227          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5228          * file was not a regular file, we leave O_EXCL off.
5229          */
5230         if (r != 0)
5231                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5232         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5233
5234         /* If the open failed, return the file descriptor right away. */
5235         if (fd < 0)
5236                 return fd;
5237
5238         /*
5239          * OK, the open succeeded, but the file may have been changed from a
5240          * non-regular file to a regular file between the stat and the open.
5241          * We are assuming that the O_EXCL open handles the case where FILENAME
5242          * did not exist and is symlinked to an existing file between the stat
5243          * and open.
5244          */
5245
5246         /*
5247          * If we can open it and fstat the file descriptor, and neither check
5248          * revealed that it was a regular file, and the file has not been
5249          * replaced, return the file descriptor.
5250          */
5251         if (fstat(fd, &finfo2) == 0
5252          && !S_ISREG(finfo2.st_mode)
5253          && finfo.st_dev == finfo2.st_dev
5254          && finfo.st_ino == finfo2.st_ino
5255         ) {
5256                 return fd;
5257         }
5258
5259         /* The file has been replaced.  badness. */
5260         close(fd);
5261         errno = EEXIST;
5262         return -1;
5263 }
5264
5265 /*
5266  * Handle here documents.  Normally we fork off a process to write the
5267  * data to a pipe.  If the document is short, we can stuff the data in
5268  * the pipe without forking.
5269  */
5270 /* openhere needs this forward reference */
5271 static void expandhere(union node *arg, int fd);
5272 static int
5273 openhere(union node *redir)
5274 {
5275         int pip[2];
5276         size_t len = 0;
5277
5278         if (pipe(pip) < 0)
5279                 ash_msg_and_raise_error("pipe call failed");
5280         if (redir->type == NHERE) {
5281                 len = strlen(redir->nhere.doc->narg.text);
5282                 if (len <= PIPE_BUF) {
5283                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5284                         goto out;
5285                 }
5286         }
5287         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5288                 /* child */
5289                 close(pip[0]);
5290                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5291                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5292                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5293                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5294                 signal(SIGPIPE, SIG_DFL);
5295                 if (redir->type == NHERE)
5296                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5297                 else /* NXHERE */
5298                         expandhere(redir->nhere.doc, pip[1]);
5299                 _exit(EXIT_SUCCESS);
5300         }
5301  out:
5302         close(pip[1]);
5303         return pip[0];
5304 }
5305
5306 static int
5307 openredirect(union node *redir)
5308 {
5309         char *fname;
5310         int f;
5311
5312         switch (redir->nfile.type) {
5313 /* Can't happen, our single caller does this itself */
5314 //      case NTOFD:
5315 //      case NFROMFD:
5316 //              return -1;
5317         case NHERE:
5318         case NXHERE:
5319                 return openhere(redir);
5320         }
5321
5322         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5323          * allocated space. Do it only when we know it is safe.
5324          */
5325         fname = redir->nfile.expfname;
5326
5327         switch (redir->nfile.type) {
5328         default:
5329 #if DEBUG
5330                 abort();
5331 #endif
5332         case NFROM:
5333                 f = open(fname, O_RDONLY);
5334                 if (f < 0)
5335                         goto eopen;
5336                 break;
5337         case NFROMTO:
5338                 f = open(fname, O_RDWR|O_CREAT, 0666);
5339                 if (f < 0)
5340                         goto ecreate;
5341                 break;
5342         case NTO:
5343 #if BASH_REDIR_OUTPUT
5344         case NTO2:
5345 #endif
5346                 /* Take care of noclobber mode. */
5347                 if (Cflag) {
5348                         f = noclobberopen(fname);
5349                         if (f < 0)
5350                                 goto ecreate;
5351                         break;
5352                 }
5353                 /* FALLTHROUGH */
5354         case NCLOBBER:
5355                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5356                 if (f < 0)
5357                         goto ecreate;
5358                 break;
5359         case NAPPEND:
5360                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5361                 if (f < 0)
5362                         goto ecreate;
5363                 break;
5364         }
5365
5366         return f;
5367  ecreate:
5368         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5369  eopen:
5370         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5371 }
5372
5373 /*
5374  * Copy a file descriptor to be >= 10. Throws exception on error.
5375  */
5376 static int
5377 savefd(int from)
5378 {
5379         int newfd;
5380         int err;
5381
5382         newfd = fcntl(from, F_DUPFD, 10);
5383         err = newfd < 0 ? errno : 0;
5384         if (err != EBADF) {
5385                 if (err)
5386                         ash_msg_and_raise_error("%d: %m", from);
5387                 close(from);
5388                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5389         }
5390
5391         return newfd;
5392 }
5393 static int
5394 dup2_or_raise(int from, int to)
5395 {
5396         int newfd;
5397
5398         newfd = (from != to) ? dup2(from, to) : to;
5399         if (newfd < 0) {
5400                 /* Happens when source fd is not open: try "echo >&99" */
5401                 ash_msg_and_raise_error("%d: %m", from);
5402         }
5403         return newfd;
5404 }
5405
5406 /* Struct def and variable are moved down to the first usage site */
5407 struct two_fd_t {
5408         int orig, copy;
5409 };
5410 struct redirtab {
5411         struct redirtab *next;
5412         int pair_count;
5413         struct two_fd_t two_fd[];
5414 };
5415 #define redirlist (G_var.redirlist)
5416 enum {
5417         COPYFD_RESTORE = (int)~(INT_MAX),
5418 };
5419
5420 static int
5421 need_to_remember(struct redirtab *rp, int fd)
5422 {
5423         int i;
5424
5425         if (!rp) /* remembering was not requested */
5426                 return 0;
5427
5428         for (i = 0; i < rp->pair_count; i++) {
5429                 if (rp->two_fd[i].orig == fd) {
5430                         /* already remembered */
5431                         return 0;
5432                 }
5433         }
5434         return 1;
5435 }
5436
5437 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5438 static int
5439 is_hidden_fd(struct redirtab *rp, int fd)
5440 {
5441         int i;
5442         struct parsefile *pf;
5443
5444         if (fd == -1)
5445                 return 0;
5446         /* Check open scripts' fds */
5447         pf = g_parsefile;
5448         while (pf) {
5449                 /* We skip pf_fd == 0 case because of the following case:
5450                  * $ ash  # running ash interactively
5451                  * $ . ./script.sh
5452                  * and in script.sh: "exec 9>&0".
5453                  * Even though top-level pf_fd _is_ 0,
5454                  * it's still ok to use it: "read" builtin uses it,
5455                  * why should we cripple "exec" builtin?
5456                  */
5457                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5458                         return 1;
5459                 }
5460                 pf = pf->prev;
5461         }
5462
5463         if (!rp)
5464                 return 0;
5465         /* Check saved fds of redirects */
5466         fd |= COPYFD_RESTORE;
5467         for (i = 0; i < rp->pair_count; i++) {
5468                 if (rp->two_fd[i].copy == fd) {
5469                         return 1;
5470                 }
5471         }
5472         return 0;
5473 }
5474
5475 /*
5476  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5477  * old file descriptors are stashed away so that the redirection can be
5478  * undone by calling popredir.
5479  */
5480 /* flags passed to redirect */
5481 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5482 #define REDIR_SAVEFD2 03        /* set preverrout */
5483 static void
5484 redirect(union node *redir, int flags)
5485 {
5486         struct redirtab *sv;
5487         int sv_pos;
5488         int i;
5489         int fd;
5490         int newfd;
5491         int copied_fd2 = -1;
5492
5493         if (!redir) {
5494                 return;
5495         }
5496
5497         sv = NULL;
5498         sv_pos = 0;
5499         INT_OFF;
5500         if (flags & REDIR_PUSH) {
5501                 union node *tmp = redir;
5502                 do {
5503                         sv_pos++;
5504 #if BASH_REDIR_OUTPUT
5505                         if (tmp->nfile.type == NTO2)
5506                                 sv_pos++;
5507 #endif
5508                         tmp = tmp->nfile.next;
5509                 } while (tmp);
5510                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5511                 sv->next = redirlist;
5512                 sv->pair_count = sv_pos;
5513                 redirlist = sv;
5514                 while (sv_pos > 0) {
5515                         sv_pos--;
5516                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5517                 }
5518         }
5519
5520         do {
5521                 int right_fd = -1;
5522                 fd = redir->nfile.fd;
5523                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5524                         right_fd = redir->ndup.dupfd;
5525                         //bb_error_msg("doing %d > %d", fd, right_fd);
5526                         /* redirect from/to same file descriptor? */
5527                         if (right_fd == fd)
5528                                 continue;
5529                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5530                         if (is_hidden_fd(sv, right_fd)) {
5531                                 errno = EBADF; /* as if it is closed */
5532                                 ash_msg_and_raise_error("%d: %m", right_fd);
5533                         }
5534                         newfd = -1;
5535                 } else {
5536                         newfd = openredirect(redir); /* always >= 0 */
5537                         if (fd == newfd) {
5538                                 /* Descriptor wasn't open before redirect.
5539                                  * Mark it for close in the future */
5540                                 if (need_to_remember(sv, fd)) {
5541                                         goto remember_to_close;
5542                                 }
5543                                 continue;
5544                         }
5545                 }
5546 #if BASH_REDIR_OUTPUT
5547  redirect_more:
5548 #endif
5549                 if (need_to_remember(sv, fd)) {
5550                         /* Copy old descriptor */
5551                         /* Careful to not accidentally "save"
5552                          * to the same fd as right side fd in N>&M */
5553                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5554 #if defined(F_DUPFD_CLOEXEC)
5555                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5556 #else
5557                         i = fcntl(fd, F_DUPFD, minfd);
5558 #endif
5559                         if (i == -1) {
5560                                 i = errno;
5561                                 if (i != EBADF) {
5562                                         /* Strange error (e.g. "too many files" EMFILE?) */
5563                                         if (newfd >= 0)
5564                                                 close(newfd);
5565                                         errno = i;
5566                                         ash_msg_and_raise_error("%d: %m", fd);
5567                                         /* NOTREACHED */
5568                                 }
5569                                 /* EBADF: it is not open - good, remember to close it */
5570  remember_to_close:
5571                                 i = CLOSED;
5572                         } else { /* fd is open, save its copy */
5573 #if !defined(F_DUPFD_CLOEXEC)
5574                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5575 #endif
5576                                 /* "exec fd>&-" should not close fds
5577                                  * which point to script file(s).
5578                                  * Force them to be restored afterwards */
5579                                 if (is_hidden_fd(sv, fd))
5580                                         i |= COPYFD_RESTORE;
5581                         }
5582                         if (fd == 2)
5583                                 copied_fd2 = i;
5584                         sv->two_fd[sv_pos].orig = fd;
5585                         sv->two_fd[sv_pos].copy = i;
5586                         sv_pos++;
5587                 }
5588                 if (newfd < 0) {
5589                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5590                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5591                                 /* Don't want to trigger debugging */
5592                                 if (fd != -1)
5593                                         close(fd);
5594                         } else {
5595                                 dup2_or_raise(redir->ndup.dupfd, fd);
5596                         }
5597                 } else if (fd != newfd) { /* move newfd to fd */
5598                         dup2_or_raise(newfd, fd);
5599 #if BASH_REDIR_OUTPUT
5600                         if (!(redir->nfile.type == NTO2 && fd == 2))
5601 #endif
5602                                 close(newfd);
5603                 }
5604 #if BASH_REDIR_OUTPUT
5605                 if (redir->nfile.type == NTO2 && fd == 1) {
5606                         /* We already redirected it to fd 1, now copy it to 2 */
5607                         newfd = 1;
5608                         fd = 2;
5609                         goto redirect_more;
5610                 }
5611 #endif
5612         } while ((redir = redir->nfile.next) != NULL);
5613
5614         INT_ON;
5615         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5616                 preverrout_fd = copied_fd2;
5617 }
5618
5619 /*
5620  * Undo the effects of the last redirection.
5621  */
5622 static void
5623 popredir(int drop, int restore)
5624 {
5625         struct redirtab *rp;
5626         int i;
5627
5628         if (redirlist == NULL)
5629                 return;
5630         INT_OFF;
5631         rp = redirlist;
5632         for (i = 0; i < rp->pair_count; i++) {
5633                 int fd = rp->two_fd[i].orig;
5634                 int copy = rp->two_fd[i].copy;
5635                 if (copy == CLOSED) {
5636                         if (!drop)
5637                                 close(fd);
5638                         continue;
5639                 }
5640                 if (copy != EMPTY) {
5641                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5642                                 copy &= ~COPYFD_RESTORE;
5643                                 /*close(fd);*/
5644                                 dup2_or_raise(copy, fd);
5645                         }
5646                         close(copy & ~COPYFD_RESTORE);
5647                 }
5648         }
5649         redirlist = rp->next;
5650         free(rp);
5651         INT_ON;
5652 }
5653
5654 /*
5655  * Undo all redirections.  Called on error or interrupt.
5656  */
5657
5658 static int
5659 redirectsafe(union node *redir, int flags)
5660 {
5661         int err;
5662         volatile int saveint;
5663         struct jmploc *volatile savehandler = exception_handler;
5664         struct jmploc jmploc;
5665
5666         SAVE_INT(saveint);
5667         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5668         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5669         if (!err) {
5670                 exception_handler = &jmploc;
5671                 redirect(redir, flags);
5672         }
5673         exception_handler = savehandler;
5674         if (err && exception_type != EXERROR)
5675                 longjmp(exception_handler->loc, 1);
5676         RESTORE_INT(saveint);
5677         return err;
5678 }
5679
5680
5681 /* ============ Routines to expand arguments to commands
5682  *
5683  * We have to deal with backquotes, shell variables, and file metacharacters.
5684  */
5685
5686 #if ENABLE_FEATURE_SH_MATH
5687 static arith_t
5688 ash_arith(const char *s)
5689 {
5690         arith_state_t math_state;
5691         arith_t result;
5692
5693         math_state.lookupvar = lookupvar;
5694         math_state.setvar    = setvar0;
5695         //math_state.endofname = endofname;
5696
5697         INT_OFF;
5698         result = arith(&math_state, s);
5699         if (math_state.errmsg)
5700                 ash_msg_and_raise_error(math_state.errmsg);
5701         INT_ON;
5702
5703         return result;
5704 }
5705 #endif
5706
5707 /*
5708  * expandarg flags
5709  */
5710 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5711 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5712 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5713 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5714 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5715  * POSIX says for this case:
5716  *  Pathname expansion shall not be performed on the word by a
5717  *  non-interactive shell; an interactive shell may perform it, but shall
5718  *  do so only when the expansion would result in one word.
5719  * Currently, our code complies to the above rule by never globbing
5720  * redirection filenames.
5721  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5722  * (this means that on a typical Linux distro, bash almost always
5723  * performs globbing, and thus diverges from what we do).
5724  */
5725 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5726 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5727 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5728 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5729 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5730 /*
5731  * rmescape() flags
5732  */
5733 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5734 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5735 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5736 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5737 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5738
5739 /* Add CTLESC when necessary. */
5740 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR)
5741 /* Do not skip NUL characters. */
5742 #define QUOTES_KEEPNUL EXP_TILDE
5743
5744 /*
5745  * Structure specifying which parts of the string should be searched
5746  * for IFS characters.
5747  */
5748 struct ifsregion {
5749         struct ifsregion *next; /* next region in list */
5750         int begoff;             /* offset of start of region */
5751         int endoff;             /* offset of end of region */
5752         int nulonly;            /* search for nul bytes only */
5753 };
5754
5755 struct arglist {
5756         struct strlist *list;
5757         struct strlist **lastp;
5758 };
5759
5760 /* output of current string */
5761 static char *expdest;
5762 /* list of back quote expressions */
5763 static struct nodelist *argbackq;
5764 /* first struct in list of ifs regions */
5765 static struct ifsregion ifsfirst;
5766 /* last struct in list */
5767 static struct ifsregion *ifslastp;
5768 /* holds expanded arg list */
5769 static struct arglist exparg;
5770
5771 /*
5772  * Our own itoa().
5773  */
5774 #if !ENABLE_FEATURE_SH_MATH
5775 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5776 typedef long arith_t;
5777 # define ARITH_FMT "%ld"
5778 #endif
5779 static int
5780 cvtnum(arith_t num)
5781 {
5782         int len;
5783
5784         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5785         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5786         STADJUST(len, expdest);
5787         return len;
5788 }
5789
5790 /*
5791  * Break the argument string into pieces based upon IFS and add the
5792  * strings to the argument list.  The regions of the string to be
5793  * searched for IFS characters have been stored by recordregion.
5794  */
5795 static void
5796 ifsbreakup(char *string, struct arglist *arglist)
5797 {
5798         struct ifsregion *ifsp;
5799         struct strlist *sp;
5800         char *start;
5801         char *p;
5802         char *q;
5803         const char *ifs, *realifs;
5804         int ifsspc;
5805         int nulonly;
5806
5807         start = string;
5808         if (ifslastp != NULL) {
5809                 ifsspc = 0;
5810                 nulonly = 0;
5811                 realifs = ifsset() ? ifsval() : defifs;
5812                 ifsp = &ifsfirst;
5813                 do {
5814                         p = string + ifsp->begoff;
5815                         nulonly = ifsp->nulonly;
5816                         ifs = nulonly ? nullstr : realifs;
5817                         ifsspc = 0;
5818                         while (p < string + ifsp->endoff) {
5819                                 q = p;
5820                                 if ((unsigned char)*p == CTLESC)
5821                                         p++;
5822                                 if (!strchr(ifs, *p)) {
5823                                         p++;
5824                                         continue;
5825                                 }
5826                                 if (!nulonly)
5827                                         ifsspc = (strchr(defifs, *p) != NULL);
5828                                 /* Ignore IFS whitespace at start */
5829                                 if (q == start && ifsspc) {
5830                                         p++;
5831                                         start = p;
5832                                         continue;
5833                                 }
5834                                 *q = '\0';
5835                                 sp = stzalloc(sizeof(*sp));
5836                                 sp->text = start;
5837                                 *arglist->lastp = sp;
5838                                 arglist->lastp = &sp->next;
5839                                 p++;
5840                                 if (!nulonly) {
5841                                         for (;;) {
5842                                                 if (p >= string + ifsp->endoff) {
5843                                                         break;
5844                                                 }
5845                                                 q = p;
5846                                                 if ((unsigned char)*p == CTLESC)
5847                                                         p++;
5848                                                 if (strchr(ifs, *p) == NULL) {
5849                                                         p = q;
5850                                                         break;
5851                                                 }
5852                                                 if (strchr(defifs, *p) == NULL) {
5853                                                         if (ifsspc) {
5854                                                                 p++;
5855                                                                 ifsspc = 0;
5856                                                         } else {
5857                                                                 p = q;
5858                                                                 break;
5859                                                         }
5860                                                 } else
5861                                                         p++;
5862                                         }
5863                                 }
5864                                 start = p;
5865                         } /* while */
5866                         ifsp = ifsp->next;
5867                 } while (ifsp != NULL);
5868                 if (nulonly)
5869                         goto add;
5870         }
5871
5872         if (!*start)
5873                 return;
5874
5875  add:
5876         sp = stzalloc(sizeof(*sp));
5877         sp->text = start;
5878         *arglist->lastp = sp;
5879         arglist->lastp = &sp->next;
5880 }
5881
5882 static void
5883 ifsfree(void)
5884 {
5885         struct ifsregion *p = ifsfirst.next;
5886
5887         if (!p)
5888                 goto out;
5889
5890         INT_OFF;
5891         do {
5892                 struct ifsregion *ifsp;
5893                 ifsp = p->next;
5894                 free(p);
5895                 p = ifsp;
5896         } while (p);
5897         ifsfirst.next = NULL;
5898         INT_ON;
5899  out:
5900         ifslastp = NULL;
5901 }
5902
5903 static size_t
5904 esclen(const char *start, const char *p)
5905 {
5906         size_t esc = 0;
5907
5908         while (p > start && (unsigned char)*--p == CTLESC) {
5909                 esc++;
5910         }
5911         return esc;
5912 }
5913
5914 /*
5915  * Remove any CTLESC characters from a string.
5916  */
5917 static char *
5918 rmescapes(char *str, int flag)
5919 {
5920         static const char qchars[] ALIGN1 = {
5921                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5922
5923         char *p, *q, *r;
5924         unsigned inquotes;
5925         unsigned protect_against_glob;
5926         unsigned globbing;
5927         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5928
5929         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5930         if (!p)
5931                 return str;
5932
5933         q = p;
5934         r = str;
5935         if (flag & RMESCAPE_ALLOC) {
5936                 size_t len = p - str;
5937                 size_t fulllen = len + strlen(p) + 1;
5938
5939                 if (flag & RMESCAPE_GROW) {
5940                         int strloc = str - (char *)stackblock();
5941                         r = makestrspace(fulllen, expdest);
5942                         /* p and str may be invalidated by makestrspace */
5943                         str = (char *)stackblock() + strloc;
5944                         p = str + len;
5945                 } else if (flag & RMESCAPE_HEAP) {
5946                         r = ckmalloc(fulllen);
5947                 } else {
5948                         r = stalloc(fulllen);
5949                 }
5950                 q = r;
5951                 if (len > 0) {
5952                         q = (char *)memcpy(q, str, len) + len;
5953                 }
5954         }
5955
5956         inquotes = 0;
5957         globbing = flag & RMESCAPE_GLOB;
5958         protect_against_glob = globbing;
5959         while (*p) {
5960                 if ((unsigned char)*p == CTLQUOTEMARK) {
5961 // Note: both inquotes and protect_against_glob only affect whether
5962 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5963                         inquotes = ~inquotes;
5964                         p++;
5965                         protect_against_glob = globbing;
5966                         continue;
5967                 }
5968                 if ((unsigned char)*p == CTLESC) {
5969                         p++;
5970 #if DEBUG
5971                         if (*p == '\0')
5972                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5973 #endif
5974                         if (protect_against_glob) {
5975                                 /*
5976                                  * We used to trust glob() and fnmatch() to eat
5977                                  * superfluous escapes (\z where z has no
5978                                  * special meaning anyway). But this causes
5979                                  * bugs such as string of one greek letter rho
5980                                  * (unicode-encoded as two bytes "cf,81")
5981                                  * getting encoded as "cf,CTLESC,81"
5982                                  * and here, converted to "cf,\,81" -
5983                                  * which does not go well with some flavors
5984                                  * of fnmatch() in unicode locales
5985                                  * (for example, glibc <= 2.22).
5986                                  *
5987                                  * Lets add "\" only on the chars which need it.
5988                                  * Testcases for less obvious chars are shown.
5989                                  */
5990                                 if (*p == '*'
5991                                  || *p == '?'
5992                                  || *p == '['
5993                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5994                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5995                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5996                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5997                                 /* Some libc support [^negate], that's why "^" also needs love */
5998                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5999                                 ) {
6000                                         *q++ = '\\';
6001                                 }
6002                         }
6003                 } else if (*p == '\\' && !inquotes) {
6004                         /* naked back slash */
6005                         protect_against_glob = 0;
6006                         goto copy;
6007                 }
6008 #if BASH_PATTERN_SUBST
6009                 else if (*p == '/' && slash) {
6010                         /* stop handling globbing and mark location of slash */
6011                         globbing = slash = 0;
6012                         *p = CTLESC;
6013                 }
6014 #endif
6015                 protect_against_glob = globbing;
6016  copy:
6017                 *q++ = *p++;
6018         }
6019         *q = '\0';
6020         if (flag & RMESCAPE_GROW) {
6021                 expdest = r;
6022                 STADJUST(q - r + 1, expdest);
6023         }
6024         return r;
6025 }
6026 #define pmatch(a, b) !fnmatch((a), (b), 0)
6027
6028 /*
6029  * Prepare a pattern for a expmeta (internal glob(3)) call.
6030  *
6031  * Returns an stalloced string.
6032  */
6033 static char *
6034 preglob(const char *pattern, int flag)
6035 {
6036         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
6037 }
6038
6039 /*
6040  * Put a string on the stack.
6041  */
6042 static void
6043 memtodest(const char *p, size_t len, int syntax, int quotes)
6044 {
6045         char *q;
6046
6047         if (!len)
6048                 return;
6049
6050         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6051
6052         do {
6053                 unsigned char c = *p++;
6054                 if (c) {
6055                         if (quotes & QUOTES_ESC) {
6056                                 int n = SIT(c, syntax);
6057                                 if (n == CCTL
6058                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6059                                      && n == CBACK
6060                                     )
6061                                 ) {
6062                                         USTPUTC(CTLESC, q);
6063                                 }
6064                         }
6065                 } else if (!(quotes & QUOTES_KEEPNUL))
6066                         continue;
6067                 USTPUTC(c, q);
6068         } while (--len);
6069
6070         expdest = q;
6071 }
6072
6073 static size_t
6074 strtodest(const char *p, int syntax, int quotes)
6075 {
6076         size_t len = strlen(p);
6077         memtodest(p, len, syntax, quotes);
6078         return len;
6079 }
6080
6081 /*
6082  * Record the fact that we have to scan this region of the
6083  * string for IFS characters.
6084  */
6085 static void
6086 recordregion(int start, int end, int nulonly)
6087 {
6088         struct ifsregion *ifsp;
6089
6090         if (ifslastp == NULL) {
6091                 ifsp = &ifsfirst;
6092         } else {
6093                 INT_OFF;
6094                 ifsp = ckzalloc(sizeof(*ifsp));
6095                 /*ifsp->next = NULL; - ckzalloc did it */
6096                 ifslastp->next = ifsp;
6097                 INT_ON;
6098         }
6099         ifslastp = ifsp;
6100         ifslastp->begoff = start;
6101         ifslastp->endoff = end;
6102         ifslastp->nulonly = nulonly;
6103 }
6104
6105 static void
6106 removerecordregions(int endoff)
6107 {
6108         if (ifslastp == NULL)
6109                 return;
6110
6111         if (ifsfirst.endoff > endoff) {
6112                 while (ifsfirst.next) {
6113                         struct ifsregion *ifsp;
6114                         INT_OFF;
6115                         ifsp = ifsfirst.next->next;
6116                         free(ifsfirst.next);
6117                         ifsfirst.next = ifsp;
6118                         INT_ON;
6119                 }
6120                 if (ifsfirst.begoff > endoff) {
6121                         ifslastp = NULL;
6122                 } else {
6123                         ifslastp = &ifsfirst;
6124                         ifsfirst.endoff = endoff;
6125                 }
6126                 return;
6127         }
6128
6129         ifslastp = &ifsfirst;
6130         while (ifslastp->next && ifslastp->next->begoff < endoff)
6131                 ifslastp = ifslastp->next;
6132         while (ifslastp->next) {
6133                 struct ifsregion *ifsp;
6134                 INT_OFF;
6135                 ifsp = ifslastp->next->next;
6136                 free(ifslastp->next);
6137                 ifslastp->next = ifsp;
6138                 INT_ON;
6139         }
6140         if (ifslastp->endoff > endoff)
6141                 ifslastp->endoff = endoff;
6142 }
6143
6144 static char *
6145 exptilde(char *startp, char *p, int flags)
6146 {
6147         unsigned char c;
6148         char *name;
6149         struct passwd *pw;
6150         const char *home;
6151         int quotes = flags & QUOTES_ESC;
6152
6153         name = p + 1;
6154
6155         while ((c = *++p) != '\0') {
6156                 switch (c) {
6157                 case CTLESC:
6158                         return startp;
6159                 case CTLQUOTEMARK:
6160                         return startp;
6161                 case ':':
6162                         if (flags & EXP_VARTILDE)
6163                                 goto done;
6164                         break;
6165                 case '/':
6166                 case CTLENDVAR:
6167                         goto done;
6168                 }
6169         }
6170  done:
6171         *p = '\0';
6172         if (*name == '\0') {
6173                 home = lookupvar("HOME");
6174         } else {
6175                 pw = getpwnam(name);
6176                 if (pw == NULL)
6177                         goto lose;
6178                 home = pw->pw_dir;
6179         }
6180         if (!home || !*home)
6181                 goto lose;
6182         *p = c;
6183         strtodest(home, SQSYNTAX, quotes);
6184         return p;
6185  lose:
6186         *p = c;
6187         return startp;
6188 }
6189
6190 /*
6191  * Execute a command inside back quotes.  If it's a builtin command, we
6192  * want to save its output in a block obtained from malloc.  Otherwise
6193  * we fork off a subprocess and get the output of the command via a pipe.
6194  * Should be called with interrupts off.
6195  */
6196 struct backcmd {                /* result of evalbackcmd */
6197         int fd;                 /* file descriptor to read from */
6198         int nleft;              /* number of chars in buffer */
6199         char *buf;              /* buffer */
6200         struct job *jp;         /* job structure for command */
6201 };
6202
6203 /* These forward decls are needed to use "eval" code for backticks handling: */
6204 #define EV_EXIT 01              /* exit after evaluating tree */
6205 static int evaltree(union node *, int);
6206
6207 static void FAST_FUNC
6208 evalbackcmd(union node *n, struct backcmd *result)
6209 {
6210         int pip[2];
6211         struct job *jp;
6212
6213         result->fd = -1;
6214         result->buf = NULL;
6215         result->nleft = 0;
6216         result->jp = NULL;
6217         if (n == NULL) {
6218                 goto out;
6219         }
6220
6221         if (pipe(pip) < 0)
6222                 ash_msg_and_raise_error("pipe call failed");
6223         jp = makejob(/*n,*/ 1);
6224         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6225                 /* child */
6226                 FORCE_INT_ON;
6227                 close(pip[0]);
6228                 if (pip[1] != 1) {
6229                         /*close(1);*/
6230                         dup2_or_raise(pip[1], 1);
6231                         close(pip[1]);
6232                 }
6233 /* TODO: eflag clearing makes the following not abort:
6234  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6235  * which is what bash does (unless it is in POSIX mode).
6236  * dash deleted "eflag = 0" line in the commit
6237  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6238  *  [EVAL] Don't clear eflag in evalbackcmd
6239  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6240  */
6241                 eflag = 0;
6242                 ifsfree();
6243                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6244                 /* NOTREACHED */
6245         }
6246         /* parent */
6247         close(pip[1]);
6248         result->fd = pip[0];
6249         result->jp = jp;
6250
6251  out:
6252         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6253                 result->fd, result->buf, result->nleft, result->jp));
6254 }
6255
6256 /*
6257  * Expand stuff in backwards quotes.
6258  */
6259 static void
6260 expbackq(union node *cmd, int flag)
6261 {
6262         struct backcmd in;
6263         int i;
6264         char buf[128];
6265         char *p;
6266         char *dest;
6267         int startloc;
6268         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6269         struct stackmark smark;
6270
6271         INT_OFF;
6272         startloc = expdest - (char *)stackblock();
6273         pushstackmark(&smark, startloc);
6274         evalbackcmd(cmd, &in);
6275         popstackmark(&smark);
6276
6277         p = in.buf;
6278         i = in.nleft;
6279         if (i == 0)
6280                 goto read;
6281         for (;;) {
6282                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6283  read:
6284                 if (in.fd < 0)
6285                         break;
6286                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6287                 TRACE(("expbackq: read returns %d\n", i));
6288                 if (i <= 0)
6289                         break;
6290                 p = buf;
6291         }
6292
6293         free(in.buf);
6294         if (in.fd >= 0) {
6295                 close(in.fd);
6296                 back_exitstatus = waitforjob(in.jp);
6297         }
6298         INT_ON;
6299
6300         /* Eat all trailing newlines */
6301         dest = expdest;
6302         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6303                 STUNPUTC(dest);
6304         expdest = dest;
6305
6306         if (!(flag & EXP_QUOTED))
6307                 recordregion(startloc, dest - (char *)stackblock(), 0);
6308         TRACE(("evalbackq: size:%d:'%.*s'\n",
6309                 (int)((dest - (char *)stackblock()) - startloc),
6310                 (int)((dest - (char *)stackblock()) - startloc),
6311                 stackblock() + startloc));
6312 }
6313
6314 #if ENABLE_FEATURE_SH_MATH
6315 /*
6316  * Expand arithmetic expression.  Backup to start of expression,
6317  * evaluate, place result in (backed up) result, adjust string position.
6318  */
6319 static void
6320 expari(int flag)
6321 {
6322         char *p, *start;
6323         int begoff;
6324         int len;
6325
6326         /* ifsfree(); */
6327
6328         /*
6329          * This routine is slightly over-complicated for
6330          * efficiency.  Next we scan backwards looking for the
6331          * start of arithmetic.
6332          */
6333         start = stackblock();
6334         p = expdest - 1;
6335         *p = '\0';
6336         p--;
6337         while (1) {
6338                 int esc;
6339
6340                 while ((unsigned char)*p != CTLARI) {
6341                         p--;
6342 #if DEBUG
6343                         if (p < start) {
6344                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6345                         }
6346 #endif
6347                 }
6348
6349                 esc = esclen(start, p);
6350                 if (!(esc % 2)) {
6351                         break;
6352                 }
6353
6354                 p -= esc + 1;
6355         }
6356
6357         begoff = p - start;
6358
6359         removerecordregions(begoff);
6360
6361         expdest = p;
6362
6363         if (flag & QUOTES_ESC)
6364                 rmescapes(p + 1, 0);
6365
6366         len = cvtnum(ash_arith(p + 1));
6367
6368         if (!(flag & EXP_QUOTED))
6369                 recordregion(begoff, begoff + len, 0);
6370 }
6371 #endif
6372
6373 /* argstr needs it */
6374 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6375
6376 /*
6377  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6378  * characters to allow for further processing.  Otherwise treat
6379  * $@ like $* since no splitting will be performed.
6380  *
6381  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6382  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6383  * for correct expansion of "B=$A" word.
6384  */
6385 static void
6386 argstr(char *p, int flags, struct strlist *var_str_list)
6387 {
6388         static const char spclchars[] ALIGN1 = {
6389                 '=',
6390                 ':',
6391                 CTLQUOTEMARK,
6392                 CTLENDVAR,
6393                 CTLESC,
6394                 CTLVAR,
6395                 CTLBACKQ,
6396 #if ENABLE_FEATURE_SH_MATH
6397                 CTLENDARI,
6398 #endif
6399                 '\0'
6400         };
6401         const char *reject = spclchars;
6402         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6403         int inquotes;
6404         size_t length;
6405         int startloc;
6406
6407         if (!(flags & EXP_VARTILDE)) {
6408                 reject += 2;
6409         } else if (flags & EXP_VARTILDE2) {
6410                 reject++;
6411         }
6412         inquotes = 0;
6413         length = 0;
6414         if (flags & EXP_TILDE) {
6415                 char *q;
6416
6417                 flags &= ~EXP_TILDE;
6418  tilde:
6419                 q = p;
6420                 if (*q == '~')
6421                         p = exptilde(p, q, flags);
6422         }
6423  start:
6424         startloc = expdest - (char *)stackblock();
6425         for (;;) {
6426                 unsigned char c;
6427
6428                 length += strcspn(p + length, reject);
6429                 c = p[length];
6430                 if (c) {
6431                         if (!(c & 0x80)
6432                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6433                         ) {
6434                                 /* c == '=' || c == ':' || c == CTLENDARI */
6435                                 length++;
6436                         }
6437                 }
6438                 if (length > 0) {
6439                         int newloc;
6440                         expdest = stack_nputstr(p, length, expdest);
6441                         newloc = expdest - (char *)stackblock();
6442                         if (breakall && !inquotes && newloc > startloc) {
6443                                 recordregion(startloc, newloc, 0);
6444                         }
6445                         startloc = newloc;
6446                 }
6447                 p += length + 1;
6448                 length = 0;
6449
6450                 switch (c) {
6451                 case '\0':
6452                         goto breakloop;
6453                 case '=':
6454                         if (flags & EXP_VARTILDE2) {
6455                                 p--;
6456                                 continue;
6457                         }
6458                         flags |= EXP_VARTILDE2;
6459                         reject++;
6460                         /* fall through */
6461                 case ':':
6462                         /*
6463                          * sort of a hack - expand tildes in variable
6464                          * assignments (after the first '=' and after ':'s).
6465                          */
6466                         if (*--p == '~') {
6467                                 goto tilde;
6468                         }
6469                         continue;
6470                 }
6471
6472                 switch (c) {
6473                 case CTLENDVAR: /* ??? */
6474                         goto breakloop;
6475                 case CTLQUOTEMARK:
6476                         inquotes ^= EXP_QUOTED;
6477                         /* "$@" syntax adherence hack */
6478                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6479                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6480                                 goto start;
6481                         }
6482  addquote:
6483                         if (flags & QUOTES_ESC) {
6484                                 p--;
6485                                 length++;
6486                                 startloc++;
6487                         }
6488                         break;
6489                 case CTLESC:
6490                         startloc++;
6491                         length++;
6492
6493                         /*
6494                          * Quoted parameter expansion pattern: remove quote
6495                          * unless inside inner quotes or we have a literal
6496                          * backslash.
6497                          */
6498                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6499                             EXP_QPAT && *p != '\\')
6500                                 break;
6501
6502                         goto addquote;
6503                 case CTLVAR:
6504                         TRACE(("argstr: evalvar('%s')\n", p));
6505                         p = evalvar(p, flags | inquotes, var_str_list);
6506                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6507                         goto start;
6508                 case CTLBACKQ:
6509                         expbackq(argbackq->n, flags | inquotes);
6510                         argbackq = argbackq->next;
6511                         goto start;
6512 #if ENABLE_FEATURE_SH_MATH
6513                 case CTLENDARI:
6514                         p--;
6515                         expari(flags | inquotes);
6516                         goto start;
6517 #endif
6518                 }
6519         }
6520  breakloop: ;
6521 }
6522
6523 static char *
6524 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6525                 char *pattern, int quotes, int zero)
6526 {
6527         char *loc, *loc2;
6528         char c;
6529
6530         loc = startp;
6531         loc2 = rmesc;
6532         do {
6533                 int match;
6534                 const char *s = loc2;
6535
6536                 c = *loc2;
6537                 if (zero) {
6538                         *loc2 = '\0';
6539                         s = rmesc;
6540                 }
6541                 match = pmatch(pattern, s);
6542
6543                 *loc2 = c;
6544                 if (match)
6545                         return loc;
6546                 if (quotes && (unsigned char)*loc == CTLESC)
6547                         loc++;
6548                 loc++;
6549                 loc2++;
6550         } while (c);
6551         return NULL;
6552 }
6553
6554 static char *
6555 scanright(char *startp, char *rmesc, char *rmescend,
6556                 char *pattern, int quotes, int match_at_start)
6557 {
6558 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6559         int try2optimize = match_at_start;
6560 #endif
6561         int esc = 0;
6562         char *loc;
6563         char *loc2;
6564
6565         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6566          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6567          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6568          * Logic:
6569          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6570          * and on each iteration they go back two/one char until they reach the beginning.
6571          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6572          */
6573         /* TODO: document in what other circumstances we are called. */
6574
6575         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6576                 int match;
6577                 char c = *loc2;
6578                 const char *s = loc2;
6579                 if (match_at_start) {
6580                         *loc2 = '\0';
6581                         s = rmesc;
6582                 }
6583                 match = pmatch(pattern, s);
6584                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6585                 *loc2 = c;
6586                 if (match)
6587                         return loc;
6588 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6589                 if (try2optimize) {
6590                         /* Maybe we can optimize this:
6591                          * if pattern ends with unescaped *, we can avoid checking
6592                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6593                          * it won't match truncated "raw_value_of_" strings too.
6594                          */
6595                         unsigned plen = strlen(pattern);
6596                         /* Does it end with "*"? */
6597                         if (plen != 0 && pattern[--plen] == '*') {
6598                                 /* "xxxx*" is not escaped */
6599                                 /* "xxx\*" is escaped */
6600                                 /* "xx\\*" is not escaped */
6601                                 /* "x\\\*" is escaped */
6602                                 int slashes = 0;
6603                                 while (plen != 0 && pattern[--plen] == '\\')
6604                                         slashes++;
6605                                 if (!(slashes & 1))
6606                                         break; /* ends with unescaped "*" */
6607                         }
6608                         try2optimize = 0;
6609                 }
6610 #endif
6611                 loc--;
6612                 if (quotes) {
6613                         if (--esc < 0) {
6614                                 esc = esclen(startp, loc);
6615                         }
6616                         if (esc % 2) {
6617                                 esc--;
6618                                 loc--;
6619                         }
6620                 }
6621         }
6622         return NULL;
6623 }
6624
6625 static void varunset(const char *, const char *, const char *, int) NORETURN;
6626 static void
6627 varunset(const char *end, const char *var, const char *umsg, int varflags)
6628 {
6629         const char *msg;
6630         const char *tail;
6631
6632         tail = nullstr;
6633         msg = "parameter not set";
6634         if (umsg) {
6635                 if ((unsigned char)*end == CTLENDVAR) {
6636                         if (varflags & VSNUL)
6637                                 tail = " or null";
6638                 } else {
6639                         msg = umsg;
6640                 }
6641         }
6642         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6643 }
6644
6645 static const char *
6646 subevalvar(char *p, char *varname, int strloc, int subtype,
6647                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6648 {
6649         struct nodelist *saveargbackq = argbackq;
6650         int quotes = flag & QUOTES_ESC;
6651         char *startp;
6652         char *loc;
6653         char *rmesc, *rmescend;
6654         char *str;
6655         int amount, resetloc;
6656         IF_BASH_PATTERN_SUBST(int workloc;)
6657         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6658         int zero;
6659         char *(*scan)(char*, char*, char*, char*, int, int);
6660
6661         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6662         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6663
6664         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6665                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6666                         var_str_list);
6667         STPUTC('\0', expdest);
6668         argbackq = saveargbackq;
6669         startp = (char *)stackblock() + startloc;
6670
6671         switch (subtype) {
6672         case VSASSIGN:
6673                 setvar0(varname, startp);
6674                 amount = startp - expdest;
6675                 STADJUST(amount, expdest);
6676                 return startp;
6677
6678         case VSQUESTION:
6679                 varunset(p, varname, startp, varflags);
6680                 /* NOTREACHED */
6681
6682 #if BASH_SUBSTR
6683         case VSSUBSTR: {
6684                 int pos, len, orig_len;
6685                 char *colon;
6686
6687                 loc = str = stackblock() + strloc;
6688
6689 # if !ENABLE_FEATURE_SH_MATH
6690 #  define ash_arith number
6691 # endif
6692                 /* Read POS in ${var:POS:LEN} */
6693                 colon = strchr(loc, ':');
6694                 if (colon) *colon = '\0';
6695                 pos = ash_arith(loc);
6696                 if (colon) *colon = ':';
6697
6698                 /* Read LEN in ${var:POS:LEN} */
6699                 len = str - startp - 1;
6700                 /* *loc != '\0', guaranteed by parser */
6701                 if (quotes) {
6702                         char *ptr;
6703
6704                         /* Adjust the length by the number of escapes */
6705                         for (ptr = startp; ptr < (str - 1); ptr++) {
6706                                 if ((unsigned char)*ptr == CTLESC) {
6707                                         len--;
6708                                         ptr++;
6709                                 }
6710                         }
6711                 }
6712                 orig_len = len;
6713                 if (*loc++ == ':') {
6714                         /* ${var::LEN} */
6715                         len = ash_arith(loc);
6716                 } else {
6717                         /* Skip POS in ${var:POS:LEN} */
6718                         len = orig_len;
6719                         while (*loc && *loc != ':') {
6720                                 loc++;
6721                         }
6722                         if (*loc++ == ':') {
6723                                 len = ash_arith(loc);
6724                         }
6725                 }
6726 #  undef ash_arith
6727
6728                 if (pos < 0) {
6729                         /* ${VAR:$((-n)):l} starts n chars from the end */
6730                         pos = orig_len + pos;
6731                 }
6732                 if ((unsigned)pos >= orig_len) {
6733                         /* apart from obvious ${VAR:999999:l},
6734                          * covers ${VAR:$((-9999999)):l} - result is ""
6735                          * (bash compat)
6736                          */
6737                         pos = 0;
6738                         len = 0;
6739                 }
6740                 if (len < 0) {
6741                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6742                         len = (orig_len - pos) + len;
6743                 }
6744                 if ((unsigned)len > (orig_len - pos))
6745                         len = orig_len - pos;
6746
6747                 for (str = startp; pos; str++, pos--) {
6748                         if (quotes && (unsigned char)*str == CTLESC)
6749                                 str++;
6750                 }
6751                 for (loc = startp; len; len--) {
6752                         if (quotes && (unsigned char)*str == CTLESC)
6753                                 *loc++ = *str++;
6754                         *loc++ = *str++;
6755                 }
6756                 *loc = '\0';
6757                 amount = loc - expdest;
6758                 STADJUST(amount, expdest);
6759                 return loc;
6760         }
6761 #endif /* BASH_SUBSTR */
6762         }
6763
6764         resetloc = expdest - (char *)stackblock();
6765
6766 #if BASH_PATTERN_SUBST
6767         /* We'll comeback here if we grow the stack while handling
6768          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6769          * stack will need rebasing, and we'll need to remove our work
6770          * areas each time
6771          */
6772  restart:
6773 #endif
6774
6775         amount = expdest - ((char *)stackblock() + resetloc);
6776         STADJUST(-amount, expdest);
6777         startp = (char *)stackblock() + startloc;
6778
6779         rmesc = startp;
6780         rmescend = (char *)stackblock() + strloc;
6781         if (quotes) {
6782                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6783                 if (rmesc != startp) {
6784                         rmescend = expdest;
6785                         startp = (char *)stackblock() + startloc;
6786                 }
6787         }
6788         rmescend--;
6789         str = (char *)stackblock() + strloc;
6790         /*
6791          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6792          * The result is a_\_z_c (not a\_\_z_c)!
6793          *
6794          * The search pattern and replace string treat backslashes differently!
6795          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6796          * and string.  It's only used on the first call.
6797          */
6798         preglob(str, IF_BASH_PATTERN_SUBST(
6799                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6800                         RMESCAPE_SLASH : ) 0);
6801
6802 #if BASH_PATTERN_SUBST
6803         workloc = expdest - (char *)stackblock();
6804         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6805                 int len;
6806                 char *idx, *end;
6807
6808                 if (!repl) {
6809                         repl = strchr(str, CTLESC);
6810                         if (repl)
6811                                 *repl++ = '\0';
6812                         else
6813                                 repl = nullstr;
6814                 }
6815                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6816
6817                 /* If there's no pattern to match, return the expansion unmolested */
6818                 if (str[0] == '\0')
6819                         return NULL;
6820
6821                 len = 0;
6822                 idx = startp;
6823                 end = str - 1;
6824                 while (idx < end) {
6825  try_to_match:
6826                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6827                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6828                         if (!loc) {
6829                                 /* No match, advance */
6830                                 char *restart_detect = stackblock();
6831  skip_matching:
6832                                 STPUTC(*idx, expdest);
6833                                 if (quotes && (unsigned char)*idx == CTLESC) {
6834                                         idx++;
6835                                         len++;
6836                                         STPUTC(*idx, expdest);
6837                                 }
6838                                 if (stackblock() != restart_detect)
6839                                         goto restart;
6840                                 idx++;
6841                                 len++;
6842                                 rmesc++;
6843                                 /* continue; - prone to quadratic behavior, smarter code: */
6844                                 if (idx >= end)
6845                                         break;
6846                                 if (str[0] == '*') {
6847                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6848                                          * it would never match "ong_string" etc, no point in trying.
6849                                          */
6850                                         goto skip_matching;
6851                                 }
6852                                 goto try_to_match;
6853                         }
6854
6855                         if (subtype == VSREPLACEALL) {
6856                                 while (idx < loc) {
6857                                         if (quotes && (unsigned char)*idx == CTLESC)
6858                                                 idx++;
6859                                         idx++;
6860                                         rmesc++;
6861                                 }
6862                         } else {
6863                                 idx = loc;
6864                         }
6865
6866                         //bb_error_msg("repl:'%s'", repl);
6867                         for (loc = (char*)repl; *loc; loc++) {
6868                                 char *restart_detect = stackblock();
6869                                 if (quotes && *loc == '\\') {
6870                                         STPUTC(CTLESC, expdest);
6871                                         len++;
6872                                 }
6873                                 STPUTC(*loc, expdest);
6874                                 if (stackblock() != restart_detect)
6875                                         goto restart;
6876                                 len++;
6877                         }
6878
6879                         if (subtype == VSREPLACE) {
6880                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6881                                 while (*idx) {
6882                                         char *restart_detect = stackblock();
6883                                         STPUTC(*idx, expdest);
6884                                         if (stackblock() != restart_detect)
6885                                                 goto restart;
6886                                         len++;
6887                                         idx++;
6888                                 }
6889                                 break;
6890                         }
6891                 }
6892
6893                 /* We've put the replaced text into a buffer at workloc, now
6894                  * move it to the right place and adjust the stack.
6895                  */
6896                 STPUTC('\0', expdest);
6897                 startp = (char *)stackblock() + startloc;
6898                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6899                 //bb_error_msg("startp:'%s'", startp);
6900                 amount = expdest - (startp + len);
6901                 STADJUST(-amount, expdest);
6902                 return startp;
6903         }
6904 #endif /* BASH_PATTERN_SUBST */
6905
6906         subtype -= VSTRIMRIGHT;
6907 #if DEBUG
6908         if (subtype < 0 || subtype > 7)
6909                 abort();
6910 #endif
6911         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6912         zero = subtype >> 1;
6913         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6914         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6915
6916         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6917         if (loc) {
6918                 if (zero) {
6919                         memmove(startp, loc, str - loc);
6920                         loc = startp + (str - loc) - 1;
6921                 }
6922                 *loc = '\0';
6923                 amount = loc - expdest;
6924                 STADJUST(amount, expdest);
6925         }
6926         return loc;
6927 }
6928
6929 /*
6930  * Add the value of a specialized variable to the stack string.
6931  * name parameter (examples):
6932  * ash -c 'echo $1'      name:'1='
6933  * ash -c 'echo $qwe'    name:'qwe='
6934  * ash -c 'echo $$'      name:'$='
6935  * ash -c 'echo ${$}'    name:'$='
6936  * ash -c 'echo ${$##q}' name:'$=q'
6937  * ash -c 'echo ${#$}'   name:'$='
6938  * note: examples with bad shell syntax:
6939  * ash -c 'echo ${#$1}'  name:'$=1'
6940  * ash -c 'echo ${#1#}'  name:'1=#'
6941  */
6942 static NOINLINE ssize_t
6943 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6944 {
6945         const char *p;
6946         int num;
6947         int i;
6948         ssize_t len = 0;
6949         int sep;
6950         int quoted = *quotedp;
6951         int subtype = varflags & VSTYPE;
6952         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6953         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6954         int syntax;
6955
6956         sep = (flags & EXP_FULL) << CHAR_BIT;
6957         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6958
6959         switch (*name) {
6960         case '$':
6961                 num = rootpid;
6962                 goto numvar;
6963         case '?':
6964                 num = exitstatus;
6965                 goto numvar;
6966         case '#':
6967                 num = shellparam.nparam;
6968                 goto numvar;
6969         case '!':
6970                 num = backgndpid;
6971                 if (num == 0)
6972                         return -1;
6973  numvar:
6974                 len = cvtnum(num);
6975                 goto check_1char_name;
6976         case '-':
6977                 expdest = makestrspace(NOPTS, expdest);
6978                 for (i = NOPTS - 1; i >= 0; i--) {
6979                         if (optlist[i]) {
6980                                 USTPUTC(optletters(i), expdest);
6981                                 len++;
6982                         }
6983                 }
6984  check_1char_name:
6985 #if 0
6986                 /* handles cases similar to ${#$1} */
6987                 if (name[2] != '\0')
6988                         raise_error_syntax("bad substitution");
6989 #endif
6990                 break;
6991         case '@':
6992                 if (quoted && sep)
6993                         goto param;
6994                 /* fall through */
6995         case '*': {
6996                 char **ap;
6997                 char sepc;
6998
6999                 if (quoted)
7000                         sep = 0;
7001                 sep |= ifsset() ? ifsval()[0] : ' ';
7002  param:
7003                 sepc = sep;
7004                 *quotedp = !sepc;
7005                 ap = shellparam.p;
7006                 if (!ap)
7007                         return -1;
7008                 while ((p = *ap++) != NULL) {
7009                         len += strtodest(p, syntax, quotes);
7010
7011                         if (*ap && sep) {
7012                                 len++;
7013                                 memtodest(&sepc, 1, syntax, quotes);
7014                         }
7015                 }
7016                 break;
7017         } /* case '*' */
7018         case '0':
7019         case '1':
7020         case '2':
7021         case '3':
7022         case '4':
7023         case '5':
7024         case '6':
7025         case '7':
7026         case '8':
7027         case '9':
7028                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7029                 if (num < 0 || num > shellparam.nparam)
7030                         return -1;
7031                 p = num ? shellparam.p[num - 1] : arg0;
7032                 goto value;
7033         default:
7034                 /* NB: name has form "VAR=..." */
7035
7036                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
7037                  * which should be considered before we check variables. */
7038                 if (var_str_list) {
7039                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
7040                         p = NULL;
7041                         do {
7042                                 char *str, *eq;
7043                                 str = var_str_list->text;
7044                                 eq = strchr(str, '=');
7045                                 if (!eq) /* stop at first non-assignment */
7046                                         break;
7047                                 eq++;
7048                                 if (name_len == (unsigned)(eq - str)
7049                                  && strncmp(str, name, name_len) == 0
7050                                 ) {
7051                                         p = eq;
7052                                         /* goto value; - WRONG! */
7053                                         /* think "A=1 A=2 B=$A" */
7054                                 }
7055                                 var_str_list = var_str_list->next;
7056                         } while (var_str_list);
7057                         if (p)
7058                                 goto value;
7059                 }
7060                 p = lookupvar(name);
7061  value:
7062                 if (!p)
7063                         return -1;
7064
7065                 len = strtodest(p, syntax, quotes);
7066 #if ENABLE_UNICODE_SUPPORT
7067                 if (subtype == VSLENGTH && len > 0) {
7068                         reinit_unicode_for_ash();
7069                         if (unicode_status == UNICODE_ON) {
7070                                 STADJUST(-len, expdest);
7071                                 discard = 0;
7072                                 len = unicode_strlen(p);
7073                         }
7074                 }
7075 #endif
7076                 break;
7077         }
7078
7079         if (discard)
7080                 STADJUST(-len, expdest);
7081         return len;
7082 }
7083
7084 /*
7085  * Expand a variable, and return a pointer to the next character in the
7086  * input string.
7087  */
7088 static char *
7089 evalvar(char *p, int flag, struct strlist *var_str_list)
7090 {
7091         char varflags;
7092         char subtype;
7093         int quoted;
7094         char easy;
7095         char *var;
7096         int patloc;
7097         int startloc;
7098         ssize_t varlen;
7099
7100         varflags = (unsigned char) *p++;
7101         subtype = varflags & VSTYPE;
7102
7103         if (!subtype)
7104                 raise_error_syntax("bad substitution");
7105
7106         quoted = flag & EXP_QUOTED;
7107         var = p;
7108         easy = (!quoted || (*var == '@' && shellparam.nparam));
7109         startloc = expdest - (char *)stackblock();
7110         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7111
7112  again:
7113         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7114         if (varflags & VSNUL)
7115                 varlen--;
7116
7117         if (subtype == VSPLUS) {
7118                 varlen = -1 - varlen;
7119                 goto vsplus;
7120         }
7121
7122         if (subtype == VSMINUS) {
7123  vsplus:
7124                 if (varlen < 0) {
7125                         argstr(
7126                                 p,
7127                                 flag | EXP_TILDE | EXP_WORD,
7128                                 var_str_list
7129                         );
7130                         goto end;
7131                 }
7132                 goto record;
7133         }
7134
7135         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7136                 if (varlen >= 0)
7137                         goto record;
7138
7139                 subevalvar(p, var, 0, subtype, startloc, varflags,
7140                            flag & ~QUOTES_ESC, var_str_list);
7141                 varflags &= ~VSNUL;
7142                 /*
7143                  * Remove any recorded regions beyond
7144                  * start of variable
7145                  */
7146                 removerecordregions(startloc);
7147                 goto again;
7148         }
7149
7150         if (varlen < 0 && uflag)
7151                 varunset(p, var, 0, 0);
7152
7153         if (subtype == VSLENGTH) {
7154                 cvtnum(varlen > 0 ? varlen : 0);
7155                 goto record;
7156         }
7157
7158         if (subtype == VSNORMAL) {
7159  record:
7160                 if (!easy)
7161                         goto end;
7162                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7163                 goto end;
7164         }
7165
7166 #if DEBUG
7167         switch (subtype) {
7168         case VSTRIMLEFT:
7169         case VSTRIMLEFTMAX:
7170         case VSTRIMRIGHT:
7171         case VSTRIMRIGHTMAX:
7172 #if BASH_SUBSTR
7173         case VSSUBSTR:
7174 #endif
7175 #if BASH_PATTERN_SUBST
7176         case VSREPLACE:
7177         case VSREPLACEALL:
7178 #endif
7179                 break;
7180         default:
7181                 abort();
7182         }
7183 #endif
7184
7185         if (varlen >= 0) {
7186                 /*
7187                  * Terminate the string and start recording the pattern
7188                  * right after it
7189                  */
7190                 STPUTC('\0', expdest);
7191                 patloc = expdest - (char *)stackblock();
7192                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7193                                 startloc, varflags, flag, var_str_list)) {
7194                         int amount = expdest - (
7195                                 (char *)stackblock() + patloc - 1
7196                         );
7197                         STADJUST(-amount, expdest);
7198                 }
7199                 /* Remove any recorded regions beyond start of variable */
7200                 removerecordregions(startloc);
7201                 goto record;
7202         }
7203
7204  end:
7205         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7206                 int nesting = 1;
7207                 for (;;) {
7208                         unsigned char c = *p++;
7209                         if (c == CTLESC)
7210                                 p++;
7211                         else if (c == CTLBACKQ) {
7212                                 if (varlen >= 0)
7213                                         argbackq = argbackq->next;
7214                         } else if (c == CTLVAR) {
7215                                 if ((*p++ & VSTYPE) != VSNORMAL)
7216                                         nesting++;
7217                         } else if (c == CTLENDVAR) {
7218                                 if (--nesting == 0)
7219                                         break;
7220                         }
7221                 }
7222         }
7223         return p;
7224 }
7225
7226 /*
7227  * Add a file name to the list.
7228  */
7229 static void
7230 addfname(const char *name)
7231 {
7232         struct strlist *sp;
7233
7234         sp = stzalloc(sizeof(*sp));
7235         sp->text = sstrdup(name);
7236         *exparg.lastp = sp;
7237         exparg.lastp = &sp->next;
7238 }
7239
7240 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7241 static int
7242 hasmeta(const char *p)
7243 {
7244         static const char chars[] ALIGN1 = {
7245                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7246         };
7247
7248         for (;;) {
7249                 p = strpbrk(p, chars);
7250                 if (!p)
7251                         break;
7252                 switch ((unsigned char) *p) {
7253                 case CTLQUOTEMARK:
7254                         for (;;) {
7255                                 p++;
7256                                 if (*p == CTLQUOTEMARK)
7257                                         break;
7258                                 if (*p == CTLESC)
7259                                         p++;
7260                                 if (*p == '\0') /* huh? */
7261                                         return 0;
7262                         }
7263                         break;
7264                 case '\\':
7265                 case CTLESC:
7266                         p++;
7267                         if (*p == '\0')
7268                                 return 0;
7269                         break;
7270                 case '[':
7271                         if (!strchr(p + 1, ']')) {
7272                                 /* It's not a properly closed [] pattern,
7273                                  * but other metas may follow. Continue checking.
7274                                  * my[file* _is_ globbed by bash
7275                                  * and matches filenames like "my[file1".
7276                                  */
7277                                 break;
7278                         }
7279                         /* fallthrough */
7280                 default:
7281                 /* case '*': */
7282                 /* case '?': */
7283                         return 1;
7284                 }
7285                 p++;
7286         }
7287
7288         return 0;
7289 }
7290
7291 /* If we want to use glob() from libc... */
7292 #if !ENABLE_ASH_INTERNAL_GLOB
7293
7294 /* Add the result of glob() to the list */
7295 static void
7296 addglob(const glob_t *pglob)
7297 {
7298         char **p = pglob->gl_pathv;
7299
7300         do {
7301                 addfname(*p);
7302         } while (*++p);
7303 }
7304 static void
7305 expandmeta(struct strlist *str /*, int flag*/)
7306 {
7307         /* TODO - EXP_REDIR */
7308
7309         while (str) {
7310                 char *p;
7311                 glob_t pglob;
7312                 int i;
7313
7314                 if (fflag)
7315                         goto nometa;
7316
7317                 if (!hasmeta(str->text))
7318                         goto nometa;
7319
7320                 INT_OFF;
7321                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7322 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7323 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7324 //
7325 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7326 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7327 // Which means you need to unescape the string, right? Not so fast:
7328 // if there _is_ a file named "file\?" (with backslash), it is returned
7329 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7330 // You DON'T KNOW by looking at the result whether you need to unescape it.
7331 //
7332 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7333 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7334 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7335 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7336 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7337 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7338                 i = glob(p, 0, NULL, &pglob);
7339                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7340                 if (p != str->text)
7341                         free(p);
7342                 switch (i) {
7343                 case 0:
7344 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7345                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7346                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7347                                 goto nometa2;
7348 #endif
7349                         addglob(&pglob);
7350                         globfree(&pglob);
7351                         INT_ON;
7352                         break;
7353                 case GLOB_NOMATCH:
7354  //nometa2:
7355                         globfree(&pglob);
7356                         INT_ON;
7357  nometa:
7358                         *exparg.lastp = str;
7359                         rmescapes(str->text, 0);
7360                         exparg.lastp = &str->next;
7361                         break;
7362                 default:        /* GLOB_NOSPACE */
7363                         globfree(&pglob);
7364                         INT_ON;
7365                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7366                 }
7367                 str = str->next;
7368         }
7369 }
7370
7371 #else
7372 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7373
7374 /*
7375  * Do metacharacter (i.e. *, ?, [...]) expansion.
7376  */
7377 static void
7378 expmeta(char *expdir, char *enddir, char *name)
7379 {
7380         char *p;
7381         const char *cp;
7382         char *start;
7383         char *endname;
7384         int metaflag;
7385         struct stat statb;
7386         DIR *dirp;
7387         struct dirent *dp;
7388         int atend;
7389         int matchdot;
7390         int esc;
7391
7392         metaflag = 0;
7393         start = name;
7394         for (p = name; esc = 0, *p; p += esc + 1) {
7395                 if (*p == '*' || *p == '?')
7396                         metaflag = 1;
7397                 else if (*p == '[') {
7398                         char *q = p + 1;
7399                         if (*q == '!')
7400                                 q++;
7401                         for (;;) {
7402                                 if (*q == '\\')
7403                                         q++;
7404                                 if (*q == '/' || *q == '\0')
7405                                         break;
7406                                 if (*++q == ']') {
7407                                         metaflag = 1;
7408                                         break;
7409                                 }
7410                         }
7411                 } else {
7412                         if (*p == '\\')
7413                                 esc++;
7414                         if (p[esc] == '/') {
7415                                 if (metaflag)
7416                                         break;
7417                                 start = p + esc + 1;
7418                         }
7419                 }
7420         }
7421         if (metaflag == 0) {    /* we've reached the end of the file name */
7422                 if (enddir != expdir)
7423                         metaflag++;
7424                 p = name;
7425                 do {
7426                         if (*p == '\\')
7427                                 p++;
7428                         *enddir++ = *p;
7429                 } while (*p++);
7430                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7431                         addfname(expdir);
7432                 return;
7433         }
7434         endname = p;
7435         if (name < start) {
7436                 p = name;
7437                 do {
7438                         if (*p == '\\')
7439                                 p++;
7440                         *enddir++ = *p++;
7441                 } while (p < start);
7442         }
7443         if (enddir == expdir) {
7444                 cp = ".";
7445         } else if (enddir == expdir + 1 && *expdir == '/') {
7446                 cp = "/";
7447         } else {
7448                 cp = expdir;
7449                 enddir[-1] = '\0';
7450         }
7451         dirp = opendir(cp);
7452         if (dirp == NULL)
7453                 return;
7454         if (enddir != expdir)
7455                 enddir[-1] = '/';
7456         if (*endname == 0) {
7457                 atend = 1;
7458         } else {
7459                 atend = 0;
7460                 *endname = '\0';
7461                 endname += esc + 1;
7462         }
7463         matchdot = 0;
7464         p = start;
7465         if (*p == '\\')
7466                 p++;
7467         if (*p == '.')
7468                 matchdot++;
7469         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7470                 if (dp->d_name[0] == '.' && !matchdot)
7471                         continue;
7472                 if (pmatch(start, dp->d_name)) {
7473                         if (atend) {
7474                                 strcpy(enddir, dp->d_name);
7475                                 addfname(expdir);
7476                         } else {
7477                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7478                                         continue;
7479                                 p[-1] = '/';
7480                                 expmeta(expdir, p, endname);
7481                         }
7482                 }
7483         }
7484         closedir(dirp);
7485         if (!atend)
7486                 endname[-esc - 1] = esc ? '\\' : '/';
7487 }
7488
7489 static struct strlist *
7490 msort(struct strlist *list, int len)
7491 {
7492         struct strlist *p, *q = NULL;
7493         struct strlist **lpp;
7494         int half;
7495         int n;
7496
7497         if (len <= 1)
7498                 return list;
7499         half = len >> 1;
7500         p = list;
7501         for (n = half; --n >= 0;) {
7502                 q = p;
7503                 p = p->next;
7504         }
7505         q->next = NULL;                 /* terminate first half of list */
7506         q = msort(list, half);          /* sort first half of list */
7507         p = msort(p, len - half);               /* sort second half */
7508         lpp = &list;
7509         for (;;) {
7510 #if ENABLE_LOCALE_SUPPORT
7511                 if (strcoll(p->text, q->text) < 0)
7512 #else
7513                 if (strcmp(p->text, q->text) < 0)
7514 #endif
7515                                                 {
7516                         *lpp = p;
7517                         lpp = &p->next;
7518                         p = *lpp;
7519                         if (p == NULL) {
7520                                 *lpp = q;
7521                                 break;
7522                         }
7523                 } else {
7524                         *lpp = q;
7525                         lpp = &q->next;
7526                         q = *lpp;
7527                         if (q == NULL) {
7528                                 *lpp = p;
7529                                 break;
7530                         }
7531                 }
7532         }
7533         return list;
7534 }
7535
7536 /*
7537  * Sort the results of file name expansion.  It calculates the number of
7538  * strings to sort and then calls msort (short for merge sort) to do the
7539  * work.
7540  */
7541 static struct strlist *
7542 expsort(struct strlist *str)
7543 {
7544         int len;
7545         struct strlist *sp;
7546
7547         len = 0;
7548         for (sp = str; sp; sp = sp->next)
7549                 len++;
7550         return msort(str, len);
7551 }
7552
7553 static void
7554 expandmeta(struct strlist *str /*, int flag*/)
7555 {
7556         /* TODO - EXP_REDIR */
7557
7558         while (str) {
7559                 char *expdir;
7560                 struct strlist **savelastp;
7561                 struct strlist *sp;
7562                 char *p;
7563
7564                 if (fflag)
7565                         goto nometa;
7566                 if (!hasmeta(str->text))
7567                         goto nometa;
7568                 savelastp = exparg.lastp;
7569
7570                 INT_OFF;
7571                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7572                 {
7573                         int i = strlen(str->text);
7574 //BUGGY estimation of how long expanded name can be
7575                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7576                 }
7577                 expmeta(expdir, expdir, p);
7578                 free(expdir);
7579                 if (p != str->text)
7580                         free(p);
7581                 INT_ON;
7582                 if (exparg.lastp == savelastp) {
7583                         /*
7584                          * no matches
7585                          */
7586  nometa:
7587                         *exparg.lastp = str;
7588                         rmescapes(str->text, 0);
7589                         exparg.lastp = &str->next;
7590                 } else {
7591                         *exparg.lastp = NULL;
7592                         *savelastp = sp = expsort(*savelastp);
7593                         while (sp->next != NULL)
7594                                 sp = sp->next;
7595                         exparg.lastp = &sp->next;
7596                 }
7597                 str = str->next;
7598         }
7599 }
7600 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7601
7602 /*
7603  * Perform variable substitution and command substitution on an argument,
7604  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7605  * perform splitting and file name expansion.  When arglist is NULL, perform
7606  * here document expansion.
7607  */
7608 static void
7609 expandarg(union node *arg, struct arglist *arglist, int flag)
7610 {
7611         struct strlist *sp;
7612         char *p;
7613
7614         argbackq = arg->narg.backquote;
7615         STARTSTACKSTR(expdest);
7616         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7617         argstr(arg->narg.text, flag,
7618                         /* var_str_list: */ arglist ? arglist->list : NULL);
7619         p = _STPUTC('\0', expdest);
7620         expdest = p - 1;
7621         if (arglist == NULL) {
7622                 /* here document expanded */
7623                 goto out;
7624         }
7625         p = grabstackstr(p);
7626         TRACE(("expandarg: p:'%s'\n", p));
7627         exparg.lastp = &exparg.list;
7628         /*
7629          * TODO - EXP_REDIR
7630          */
7631         if (flag & EXP_FULL) {
7632                 ifsbreakup(p, &exparg);
7633                 *exparg.lastp = NULL;
7634                 exparg.lastp = &exparg.list;
7635                 expandmeta(exparg.list /*, flag*/);
7636         } else {
7637                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7638                         rmescapes(p, 0);
7639                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7640                 }
7641                 sp = stzalloc(sizeof(*sp));
7642                 sp->text = p;
7643                 *exparg.lastp = sp;
7644                 exparg.lastp = &sp->next;
7645         }
7646         *exparg.lastp = NULL;
7647         if (exparg.list) {
7648                 *arglist->lastp = exparg.list;
7649                 arglist->lastp = exparg.lastp;
7650         }
7651
7652  out:
7653         ifsfree();
7654 }
7655
7656 /*
7657  * Expand shell variables and backquotes inside a here document.
7658  */
7659 static void
7660 expandhere(union node *arg, int fd)
7661 {
7662         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7663         full_write(fd, stackblock(), expdest - (char *)stackblock());
7664 }
7665
7666 /*
7667  * Returns true if the pattern matches the string.
7668  */
7669 static int
7670 patmatch(char *pattern, const char *string)
7671 {
7672         char *p = preglob(pattern, 0);
7673         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7674         return pmatch(p, string);
7675 }
7676
7677 /*
7678  * See if a pattern matches in a case statement.
7679  */
7680 static int
7681 casematch(union node *pattern, char *val)
7682 {
7683         struct stackmark smark;
7684         int result;
7685
7686         setstackmark(&smark);
7687         argbackq = pattern->narg.backquote;
7688         STARTSTACKSTR(expdest);
7689         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7690                         /* var_str_list: */ NULL);
7691         STACKSTRNUL(expdest);
7692         ifsfree();
7693         result = patmatch(stackblock(), val);
7694         popstackmark(&smark);
7695         return result;
7696 }
7697
7698
7699 /* ============ find_command */
7700
7701 struct builtincmd {
7702         const char *name;
7703         int (*builtin)(int, char **) FAST_FUNC;
7704         /* unsigned flags; */
7705 };
7706 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7707 /* "regular" builtins always take precedence over commands,
7708  * regardless of PATH=....%builtin... position */
7709 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7710 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7711
7712 struct cmdentry {
7713         smallint cmdtype;       /* CMDxxx */
7714         union param {
7715                 int index;
7716                 /* index >= 0 for commands without path (slashes) */
7717                 /* (TODO: what exactly does the value mean? PATH position?) */
7718                 /* index == -1 for commands with slashes */
7719                 /* index == (-2 - applet_no) for NOFORK applets */
7720                 const struct builtincmd *cmd;
7721                 struct funcnode *func;
7722         } u;
7723 };
7724 /* values of cmdtype */
7725 #define CMDUNKNOWN      -1      /* no entry in table for command */
7726 #define CMDNORMAL       0       /* command is an executable program */
7727 #define CMDFUNCTION     1       /* command is a shell function */
7728 #define CMDBUILTIN      2       /* command is a shell builtin */
7729
7730 /* action to find_command() */
7731 #define DO_ERR          0x01    /* prints errors */
7732 #define DO_ABS          0x02    /* checks absolute paths */
7733 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7734 #define DO_ALTPATH      0x08    /* using alternate path */
7735 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7736
7737 static void find_command(char *, struct cmdentry *, int, const char *);
7738
7739
7740 /* ============ Hashing commands */
7741
7742 /*
7743  * When commands are first encountered, they are entered in a hash table.
7744  * This ensures that a full path search will not have to be done for them
7745  * on each invocation.
7746  *
7747  * We should investigate converting to a linear search, even though that
7748  * would make the command name "hash" a misnomer.
7749  */
7750
7751 struct tblentry {
7752         struct tblentry *next;  /* next entry in hash chain */
7753         union param param;      /* definition of builtin function */
7754         smallint cmdtype;       /* CMDxxx */
7755         char rehash;            /* if set, cd done since entry created */
7756         char cmdname[1];        /* name of command */
7757 };
7758
7759 static struct tblentry **cmdtable;
7760 #define INIT_G_cmdtable() do { \
7761         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7762 } while (0)
7763
7764 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7765
7766
7767 static void
7768 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7769 {
7770 #if ENABLE_FEATURE_SH_STANDALONE
7771         if (applet_no >= 0) {
7772                 if (APPLET_IS_NOEXEC(applet_no)) {
7773                         clearenv();
7774                         while (*envp)
7775                                 putenv(*envp++);
7776                         run_applet_no_and_exit(applet_no, cmd, argv);
7777                 }
7778                 /* re-exec ourselves with the new arguments */
7779                 execve(bb_busybox_exec_path, argv, envp);
7780                 /* If they called chroot or otherwise made the binary no longer
7781                  * executable, fall through */
7782         }
7783 #endif
7784
7785  repeat:
7786 #ifdef SYSV
7787         do {
7788                 execve(cmd, argv, envp);
7789         } while (errno == EINTR);
7790 #else
7791         execve(cmd, argv, envp);
7792 #endif
7793         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7794                 /* Run "cmd" as a shell script:
7795                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7796                  * "If the execve() function fails with ENOEXEC, the shell
7797                  * shall execute a command equivalent to having a shell invoked
7798                  * with the command name as its first operand,
7799                  * with any remaining arguments passed to the new shell"
7800                  *
7801                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7802                  * just call ourselves.
7803                  *
7804                  * Note that bash reads ~80 chars of the file, and if it sees
7805                  * a zero byte before it sees newline, it doesn't try to
7806                  * interpret it, but fails with "cannot execute binary file"
7807                  * message and exit code 126. For one, this prevents attempts
7808                  * to interpret foreign ELF binaries as shell scripts.
7809                  */
7810                 argv[0] = cmd;
7811                 cmd = (char*) bb_busybox_exec_path;
7812                 /* NB: this is only possible because all callers of shellexec()
7813                  * ensure that the argv[-1] slot exists!
7814                  */
7815                 argv--;
7816                 argv[0] = (char*) "ash";
7817                 goto repeat;
7818         }
7819 }
7820
7821 /*
7822  * Exec a program.  Never returns.  If you change this routine, you may
7823  * have to change the find_command routine as well.
7824  * argv[-1] must exist and be writable! See tryexec() for why.
7825  */
7826 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7827 static void shellexec(char *prog, char **argv, const char *path, int idx)
7828 {
7829         char *cmdname;
7830         int e;
7831         char **envp;
7832         int exerrno;
7833         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7834
7835         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7836         if (strchr(prog, '/') != NULL
7837 #if ENABLE_FEATURE_SH_STANDALONE
7838          || (applet_no = find_applet_by_name(prog)) >= 0
7839 #endif
7840         ) {
7841                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7842                 if (applet_no >= 0) {
7843                         /* We tried execing ourself, but it didn't work.
7844                          * Maybe /proc/self/exe doesn't exist?
7845                          * Try $PATH search.
7846                          */
7847                         goto try_PATH;
7848                 }
7849                 e = errno;
7850         } else {
7851  try_PATH:
7852                 e = ENOENT;
7853                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7854                         if (--idx < 0 && pathopt == NULL) {
7855                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7856                                 if (errno != ENOENT && errno != ENOTDIR)
7857                                         e = errno;
7858                         }
7859                         stunalloc(cmdname);
7860                 }
7861         }
7862
7863         /* Map to POSIX errors */
7864         switch (e) {
7865         case EACCES:
7866                 exerrno = 126;
7867                 break;
7868         case ENOENT:
7869                 exerrno = 127;
7870                 break;
7871         default:
7872                 exerrno = 2;
7873                 break;
7874         }
7875         exitstatus = exerrno;
7876         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7877                 prog, e, suppress_int));
7878         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7879         /* NOTREACHED */
7880 }
7881
7882 static void
7883 printentry(struct tblentry *cmdp)
7884 {
7885         int idx;
7886         const char *path;
7887         char *name;
7888
7889         idx = cmdp->param.index;
7890         path = pathval();
7891         do {
7892                 name = path_advance(&path, cmdp->cmdname);
7893                 stunalloc(name);
7894         } while (--idx >= 0);
7895         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7896 }
7897
7898 /*
7899  * Clear out command entries.  The argument specifies the first entry in
7900  * PATH which has changed.
7901  */
7902 static void
7903 clearcmdentry(int firstchange)
7904 {
7905         struct tblentry **tblp;
7906         struct tblentry **pp;
7907         struct tblentry *cmdp;
7908
7909         INT_OFF;
7910         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7911                 pp = tblp;
7912                 while ((cmdp = *pp) != NULL) {
7913                         if ((cmdp->cmdtype == CMDNORMAL &&
7914                              cmdp->param.index >= firstchange)
7915                          || (cmdp->cmdtype == CMDBUILTIN &&
7916                              builtinloc >= firstchange)
7917                         ) {
7918                                 *pp = cmdp->next;
7919                                 free(cmdp);
7920                         } else {
7921                                 pp = &cmdp->next;
7922                         }
7923                 }
7924         }
7925         INT_ON;
7926 }
7927
7928 /*
7929  * Locate a command in the command hash table.  If "add" is nonzero,
7930  * add the command to the table if it is not already present.  The
7931  * variable "lastcmdentry" is set to point to the address of the link
7932  * pointing to the entry, so that delete_cmd_entry can delete the
7933  * entry.
7934  *
7935  * Interrupts must be off if called with add != 0.
7936  */
7937 static struct tblentry **lastcmdentry;
7938
7939 static struct tblentry *
7940 cmdlookup(const char *name, int add)
7941 {
7942         unsigned int hashval;
7943         const char *p;
7944         struct tblentry *cmdp;
7945         struct tblentry **pp;
7946
7947         p = name;
7948         hashval = (unsigned char)*p << 4;
7949         while (*p)
7950                 hashval += (unsigned char)*p++;
7951         hashval &= 0x7FFF;
7952         pp = &cmdtable[hashval % CMDTABLESIZE];
7953         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7954                 if (strcmp(cmdp->cmdname, name) == 0)
7955                         break;
7956                 pp = &cmdp->next;
7957         }
7958         if (add && cmdp == NULL) {
7959                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7960                                 + strlen(name)
7961                                 /* + 1 - already done because
7962                                  * tblentry::cmdname is char[1] */);
7963                 /*cmdp->next = NULL; - ckzalloc did it */
7964                 cmdp->cmdtype = CMDUNKNOWN;
7965                 strcpy(cmdp->cmdname, name);
7966         }
7967         lastcmdentry = pp;
7968         return cmdp;
7969 }
7970
7971 /*
7972  * Delete the command entry returned on the last lookup.
7973  */
7974 static void
7975 delete_cmd_entry(void)
7976 {
7977         struct tblentry *cmdp;
7978
7979         INT_OFF;
7980         cmdp = *lastcmdentry;
7981         *lastcmdentry = cmdp->next;
7982         if (cmdp->cmdtype == CMDFUNCTION)
7983                 freefunc(cmdp->param.func);
7984         free(cmdp);
7985         INT_ON;
7986 }
7987
7988 /*
7989  * Add a new command entry, replacing any existing command entry for
7990  * the same name - except special builtins.
7991  */
7992 static void
7993 addcmdentry(char *name, struct cmdentry *entry)
7994 {
7995         struct tblentry *cmdp;
7996
7997         cmdp = cmdlookup(name, 1);
7998         if (cmdp->cmdtype == CMDFUNCTION) {
7999                 freefunc(cmdp->param.func);
8000         }
8001         cmdp->cmdtype = entry->cmdtype;
8002         cmdp->param = entry->u;
8003         cmdp->rehash = 0;
8004 }
8005
8006 static int FAST_FUNC
8007 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8008 {
8009         struct tblentry **pp;
8010         struct tblentry *cmdp;
8011         int c;
8012         struct cmdentry entry;
8013         char *name;
8014
8015         if (nextopt("r") != '\0') {
8016                 clearcmdentry(0);
8017                 return 0;
8018         }
8019
8020         if (*argptr == NULL) {
8021                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8022                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8023                                 if (cmdp->cmdtype == CMDNORMAL)
8024                                         printentry(cmdp);
8025                         }
8026                 }
8027                 return 0;
8028         }
8029
8030         c = 0;
8031         while ((name = *argptr) != NULL) {
8032                 cmdp = cmdlookup(name, 0);
8033                 if (cmdp != NULL
8034                  && (cmdp->cmdtype == CMDNORMAL
8035                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8036                 ) {
8037                         delete_cmd_entry();
8038                 }
8039                 find_command(name, &entry, DO_ERR, pathval());
8040                 if (entry.cmdtype == CMDUNKNOWN)
8041                         c = 1;
8042                 argptr++;
8043         }
8044         return c;
8045 }
8046
8047 /*
8048  * Called when a cd is done.  Marks all commands so the next time they
8049  * are executed they will be rehashed.
8050  */
8051 static void
8052 hashcd(void)
8053 {
8054         struct tblentry **pp;
8055         struct tblentry *cmdp;
8056
8057         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8058                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8059                         if (cmdp->cmdtype == CMDNORMAL
8060                          || (cmdp->cmdtype == CMDBUILTIN
8061                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8062                              && builtinloc > 0)
8063                         ) {
8064                                 cmdp->rehash = 1;
8065                         }
8066                 }
8067         }
8068 }
8069
8070 /*
8071  * Fix command hash table when PATH changed.
8072  * Called before PATH is changed.  The argument is the new value of PATH;
8073  * pathval() still returns the old value at this point.
8074  * Called with interrupts off.
8075  */
8076 static void FAST_FUNC
8077 changepath(const char *new)
8078 {
8079         const char *old;
8080         int firstchange;
8081         int idx;
8082         int idx_bltin;
8083
8084         old = pathval();
8085         firstchange = 9999;     /* assume no change */
8086         idx = 0;
8087         idx_bltin = -1;
8088         for (;;) {
8089                 if (*old != *new) {
8090                         firstchange = idx;
8091                         if ((*old == '\0' && *new == ':')
8092                          || (*old == ':' && *new == '\0')
8093                         ) {
8094                                 firstchange++;
8095                         }
8096                         old = new;      /* ignore subsequent differences */
8097                 }
8098                 if (*new == '\0')
8099                         break;
8100                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8101                         idx_bltin = idx;
8102                 if (*new == ':')
8103                         idx++;
8104                 new++;
8105                 old++;
8106         }
8107         if (builtinloc < 0 && idx_bltin >= 0)
8108                 builtinloc = idx_bltin;             /* zap builtins */
8109         if (builtinloc >= 0 && idx_bltin < 0)
8110                 firstchange = 0;
8111         clearcmdentry(firstchange);
8112         builtinloc = idx_bltin;
8113 }
8114 enum {
8115         TEOF,
8116         TNL,
8117         TREDIR,
8118         TWORD,
8119         TSEMI,
8120         TBACKGND,
8121         TAND,
8122         TOR,
8123         TPIPE,
8124         TLP,
8125         TRP,
8126         TENDCASE,
8127         TENDBQUOTE,
8128         TNOT,
8129         TCASE,
8130         TDO,
8131         TDONE,
8132         TELIF,
8133         TELSE,
8134         TESAC,
8135         TFI,
8136         TFOR,
8137 #if BASH_FUNCTION
8138         TFUNCTION,
8139 #endif
8140         TIF,
8141         TIN,
8142         TTHEN,
8143         TUNTIL,
8144         TWHILE,
8145         TBEGIN,
8146         TEND
8147 };
8148 typedef smallint token_id_t;
8149
8150 /* Nth bit indicates if token marks the end of a list */
8151 enum {
8152         tokendlist = 0
8153         /*  0 */ | (1u << TEOF)
8154         /*  1 */ | (0u << TNL)
8155         /*  2 */ | (0u << TREDIR)
8156         /*  3 */ | (0u << TWORD)
8157         /*  4 */ | (0u << TSEMI)
8158         /*  5 */ | (0u << TBACKGND)
8159         /*  6 */ | (0u << TAND)
8160         /*  7 */ | (0u << TOR)
8161         /*  8 */ | (0u << TPIPE)
8162         /*  9 */ | (0u << TLP)
8163         /* 10 */ | (1u << TRP)
8164         /* 11 */ | (1u << TENDCASE)
8165         /* 12 */ | (1u << TENDBQUOTE)
8166         /* 13 */ | (0u << TNOT)
8167         /* 14 */ | (0u << TCASE)
8168         /* 15 */ | (1u << TDO)
8169         /* 16 */ | (1u << TDONE)
8170         /* 17 */ | (1u << TELIF)
8171         /* 18 */ | (1u << TELSE)
8172         /* 19 */ | (1u << TESAC)
8173         /* 20 */ | (1u << TFI)
8174         /* 21 */ | (0u << TFOR)
8175 #if BASH_FUNCTION
8176         /* 22 */ | (0u << TFUNCTION)
8177 #endif
8178         /* 23 */ | (0u << TIF)
8179         /* 24 */ | (0u << TIN)
8180         /* 25 */ | (1u << TTHEN)
8181         /* 26 */ | (0u << TUNTIL)
8182         /* 27 */ | (0u << TWHILE)
8183         /* 28 */ | (0u << TBEGIN)
8184         /* 29 */ | (1u << TEND)
8185         , /* thus far 29 bits used */
8186 };
8187
8188 static const char *const tokname_array[] = {
8189         "end of file",
8190         "newline",
8191         "redirection",
8192         "word",
8193         ";",
8194         "&",
8195         "&&",
8196         "||",
8197         "|",
8198         "(",
8199         ")",
8200         ";;",
8201         "`",
8202 #define KWDOFFSET 13
8203         /* the following are keywords */
8204         "!",
8205         "case",
8206         "do",
8207         "done",
8208         "elif",
8209         "else",
8210         "esac",
8211         "fi",
8212         "for",
8213 #if BASH_FUNCTION
8214         "function",
8215 #endif
8216         "if",
8217         "in",
8218         "then",
8219         "until",
8220         "while",
8221         "{",
8222         "}",
8223 };
8224
8225 /* Wrapper around strcmp for qsort/bsearch/... */
8226 static int
8227 pstrcmp(const void *a, const void *b)
8228 {
8229         return strcmp((char*)a, *(char**)b);
8230 }
8231
8232 static const char *const *
8233 findkwd(const char *s)
8234 {
8235         return bsearch(s, tokname_array + KWDOFFSET,
8236                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8237                         sizeof(tokname_array[0]), pstrcmp);
8238 }
8239
8240 /*
8241  * Locate and print what a word is...
8242  */
8243 static int
8244 describe_command(char *command, const char *path, int describe_command_verbose)
8245 {
8246         struct cmdentry entry;
8247 #if ENABLE_ASH_ALIAS
8248         const struct alias *ap;
8249 #endif
8250
8251         path = path ? path : pathval();
8252
8253         if (describe_command_verbose) {
8254                 out1str(command);
8255         }
8256
8257         /* First look at the keywords */
8258         if (findkwd(command)) {
8259                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8260                 goto out;
8261         }
8262
8263 #if ENABLE_ASH_ALIAS
8264         /* Then look at the aliases */
8265         ap = lookupalias(command, 0);
8266         if (ap != NULL) {
8267                 if (!describe_command_verbose) {
8268                         out1str("alias ");
8269                         printalias(ap);
8270                         return 0;
8271                 }
8272                 out1fmt(" is an alias for %s", ap->val);
8273                 goto out;
8274         }
8275 #endif
8276         /* Brute force */
8277         find_command(command, &entry, DO_ABS, path);
8278
8279         switch (entry.cmdtype) {
8280         case CMDNORMAL: {
8281                 int j = entry.u.index;
8282                 char *p;
8283                 if (j < 0) {
8284                         p = command;
8285                 } else {
8286                         do {
8287                                 p = path_advance(&path, command);
8288                                 stunalloc(p);
8289                         } while (--j >= 0);
8290                 }
8291                 if (describe_command_verbose) {
8292                         out1fmt(" is %s", p);
8293                 } else {
8294                         out1str(p);
8295                 }
8296                 break;
8297         }
8298
8299         case CMDFUNCTION:
8300                 if (describe_command_verbose) {
8301                         out1str(" is a shell function");
8302                 } else {
8303                         out1str(command);
8304                 }
8305                 break;
8306
8307         case CMDBUILTIN:
8308                 if (describe_command_verbose) {
8309                         out1fmt(" is a %sshell builtin",
8310                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8311                                         "special " : nullstr
8312                         );
8313                 } else {
8314                         out1str(command);
8315                 }
8316                 break;
8317
8318         default:
8319                 if (describe_command_verbose) {
8320                         out1str(": not found\n");
8321                 }
8322                 return 127;
8323         }
8324  out:
8325         out1str("\n");
8326         return 0;
8327 }
8328
8329 static int FAST_FUNC
8330 typecmd(int argc UNUSED_PARAM, char **argv)
8331 {
8332         int i = 1;
8333         int err = 0;
8334         int verbose = 1;
8335
8336         /* type -p ... ? (we don't bother checking for 'p') */
8337         if (argv[1] && argv[1][0] == '-') {
8338                 i++;
8339                 verbose = 0;
8340         }
8341         while (argv[i]) {
8342                 err |= describe_command(argv[i++], NULL, verbose);
8343         }
8344         return err;
8345 }
8346
8347 #if ENABLE_ASH_CMDCMD
8348 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8349 static char **
8350 parse_command_args(char **argv, const char **path)
8351 {
8352         char *cp, c;
8353
8354         for (;;) {
8355                 cp = *++argv;
8356                 if (!cp)
8357                         return NULL;
8358                 if (*cp++ != '-')
8359                         break;
8360                 c = *cp++;
8361                 if (!c)
8362                         break;
8363                 if (c == '-' && !*cp) {
8364                         if (!*++argv)
8365                                 return NULL;
8366                         break;
8367                 }
8368                 do {
8369                         switch (c) {
8370                         case 'p':
8371                                 *path = bb_default_path;
8372                                 break;
8373                         default:
8374                                 /* run 'typecmd' for other options */
8375                                 return NULL;
8376                         }
8377                         c = *cp++;
8378                 } while (c);
8379         }
8380         return argv;
8381 }
8382
8383 static int FAST_FUNC
8384 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8385 {
8386         char *cmd;
8387         int c;
8388         enum {
8389                 VERIFY_BRIEF = 1,
8390                 VERIFY_VERBOSE = 2,
8391         } verify = 0;
8392         const char *path = NULL;
8393
8394         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8395          * never reaches this function.
8396          */
8397
8398         while ((c = nextopt("pvV")) != '\0')
8399                 if (c == 'V')
8400                         verify |= VERIFY_VERBOSE;
8401                 else if (c == 'v')
8402                         /*verify |= VERIFY_BRIEF*/;
8403 #if DEBUG
8404                 else if (c != 'p')
8405                         abort();
8406 #endif
8407                 else
8408                         path = bb_default_path;
8409
8410         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8411         cmd = *argptr;
8412         if (/*verify && */ cmd)
8413                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8414
8415         return 0;
8416 }
8417 #endif
8418
8419
8420 /*static int funcblocksize;     // size of structures in function */
8421 /*static int funcstringsize;    // size of strings in node */
8422 static void *funcblock;         /* block to allocate function from */
8423 static char *funcstring_end;    /* end of block to allocate strings from */
8424
8425 /* flags in argument to evaltree */
8426 #define EV_EXIT    01           /* exit after evaluating tree */
8427 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8428
8429 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8430         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8431         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8432         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8433         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8434         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8435         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8436         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8437         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8438         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8439         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8440         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8441         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8442         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8443         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8444         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8445         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8446         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8447 #if BASH_REDIR_OUTPUT
8448         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8449 #endif
8450         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8451         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8452         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8453         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8454         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8455         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8456         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8457         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8458         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8459 };
8460
8461 static int calcsize(int funcblocksize, union node *n);
8462
8463 static int
8464 sizenodelist(int funcblocksize, struct nodelist *lp)
8465 {
8466         while (lp) {
8467                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8468                 funcblocksize = calcsize(funcblocksize, lp->n);
8469                 lp = lp->next;
8470         }
8471         return funcblocksize;
8472 }
8473
8474 static int
8475 calcsize(int funcblocksize, union node *n)
8476 {
8477         if (n == NULL)
8478                 return funcblocksize;
8479         funcblocksize += nodesize[n->type];
8480         switch (n->type) {
8481         case NCMD:
8482                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8483                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8484                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8485                 break;
8486         case NPIPE:
8487                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8488                 break;
8489         case NREDIR:
8490         case NBACKGND:
8491         case NSUBSHELL:
8492                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8493                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8494                 break;
8495         case NAND:
8496         case NOR:
8497         case NSEMI:
8498         case NWHILE:
8499         case NUNTIL:
8500                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8501                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8502                 break;
8503         case NIF:
8504                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8505                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8506                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8507                 break;
8508         case NFOR:
8509                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8510                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8511                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8512                 break;
8513         case NCASE:
8514                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8515                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8516                 break;
8517         case NCLIST:
8518                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8519                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8520                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8521                 break;
8522         case NDEFUN:
8523         case NARG:
8524                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8525                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8526                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8527                 break;
8528         case NTO:
8529 #if BASH_REDIR_OUTPUT
8530         case NTO2:
8531 #endif
8532         case NCLOBBER:
8533         case NFROM:
8534         case NFROMTO:
8535         case NAPPEND:
8536                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8537                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8538                 break;
8539         case NTOFD:
8540         case NFROMFD:
8541                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8542                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8543         break;
8544         case NHERE:
8545         case NXHERE:
8546                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8547                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8548                 break;
8549         case NNOT:
8550                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8551                 break;
8552         };
8553         return funcblocksize;
8554 }
8555
8556 static char *
8557 nodeckstrdup(char *s)
8558 {
8559         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8560         return strcpy(funcstring_end, s);
8561 }
8562
8563 static union node *copynode(union node *);
8564
8565 static struct nodelist *
8566 copynodelist(struct nodelist *lp)
8567 {
8568         struct nodelist *start;
8569         struct nodelist **lpp;
8570
8571         lpp = &start;
8572         while (lp) {
8573                 *lpp = funcblock;
8574                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8575                 (*lpp)->n = copynode(lp->n);
8576                 lp = lp->next;
8577                 lpp = &(*lpp)->next;
8578         }
8579         *lpp = NULL;
8580         return start;
8581 }
8582
8583 static union node *
8584 copynode(union node *n)
8585 {
8586         union node *new;
8587
8588         if (n == NULL)
8589                 return NULL;
8590         new = funcblock;
8591         funcblock = (char *) funcblock + nodesize[n->type];
8592
8593         switch (n->type) {
8594         case NCMD:
8595                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8596                 new->ncmd.args = copynode(n->ncmd.args);
8597                 new->ncmd.assign = copynode(n->ncmd.assign);
8598                 break;
8599         case NPIPE:
8600                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8601                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8602                 break;
8603         case NREDIR:
8604         case NBACKGND:
8605         case NSUBSHELL:
8606                 new->nredir.redirect = copynode(n->nredir.redirect);
8607                 new->nredir.n = copynode(n->nredir.n);
8608                 break;
8609         case NAND:
8610         case NOR:
8611         case NSEMI:
8612         case NWHILE:
8613         case NUNTIL:
8614                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8615                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8616                 break;
8617         case NIF:
8618                 new->nif.elsepart = copynode(n->nif.elsepart);
8619                 new->nif.ifpart = copynode(n->nif.ifpart);
8620                 new->nif.test = copynode(n->nif.test);
8621                 break;
8622         case NFOR:
8623                 new->nfor.var = nodeckstrdup(n->nfor.var);
8624                 new->nfor.body = copynode(n->nfor.body);
8625                 new->nfor.args = copynode(n->nfor.args);
8626                 break;
8627         case NCASE:
8628                 new->ncase.cases = copynode(n->ncase.cases);
8629                 new->ncase.expr = copynode(n->ncase.expr);
8630                 break;
8631         case NCLIST:
8632                 new->nclist.body = copynode(n->nclist.body);
8633                 new->nclist.pattern = copynode(n->nclist.pattern);
8634                 new->nclist.next = copynode(n->nclist.next);
8635                 break;
8636         case NDEFUN:
8637         case NARG:
8638                 new->narg.backquote = copynodelist(n->narg.backquote);
8639                 new->narg.text = nodeckstrdup(n->narg.text);
8640                 new->narg.next = copynode(n->narg.next);
8641                 break;
8642         case NTO:
8643 #if BASH_REDIR_OUTPUT
8644         case NTO2:
8645 #endif
8646         case NCLOBBER:
8647         case NFROM:
8648         case NFROMTO:
8649         case NAPPEND:
8650                 new->nfile.fname = copynode(n->nfile.fname);
8651                 new->nfile.fd = n->nfile.fd;
8652                 new->nfile.next = copynode(n->nfile.next);
8653                 break;
8654         case NTOFD:
8655         case NFROMFD:
8656                 new->ndup.vname = copynode(n->ndup.vname);
8657                 new->ndup.dupfd = n->ndup.dupfd;
8658                 new->ndup.fd = n->ndup.fd;
8659                 new->ndup.next = copynode(n->ndup.next);
8660                 break;
8661         case NHERE:
8662         case NXHERE:
8663                 new->nhere.doc = copynode(n->nhere.doc);
8664                 new->nhere.fd = n->nhere.fd;
8665                 new->nhere.next = copynode(n->nhere.next);
8666                 break;
8667         case NNOT:
8668                 new->nnot.com = copynode(n->nnot.com);
8669                 break;
8670         };
8671         new->type = n->type;
8672         return new;
8673 }
8674
8675 /*
8676  * Make a copy of a parse tree.
8677  */
8678 static struct funcnode *
8679 copyfunc(union node *n)
8680 {
8681         struct funcnode *f;
8682         size_t blocksize;
8683
8684         /*funcstringsize = 0;*/
8685         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8686         f = ckzalloc(blocksize /* + funcstringsize */);
8687         funcblock = (char *) f + offsetof(struct funcnode, n);
8688         funcstring_end = (char *) f + blocksize;
8689         copynode(n);
8690         /* f->count = 0; - ckzalloc did it */
8691         return f;
8692 }
8693
8694 /*
8695  * Define a shell function.
8696  */
8697 static void
8698 defun(union node *func)
8699 {
8700         struct cmdentry entry;
8701
8702         INT_OFF;
8703         entry.cmdtype = CMDFUNCTION;
8704         entry.u.func = copyfunc(func);
8705         addcmdentry(func->narg.text, &entry);
8706         INT_ON;
8707 }
8708
8709 /* Reasons for skipping commands (see comment on breakcmd routine) */
8710 #define SKIPBREAK      (1 << 0)
8711 #define SKIPCONT       (1 << 1)
8712 #define SKIPFUNC       (1 << 2)
8713 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8714 static int skipcount;           /* number of levels to skip */
8715 static int funcnest;            /* depth of function calls */
8716 static int loopnest;            /* current loop nesting level */
8717
8718 /* Forward decl way out to parsing code - dotrap needs it */
8719 static int evalstring(char *s, int flags);
8720
8721 /* Called to execute a trap.
8722  * Single callsite - at the end of evaltree().
8723  * If we return non-zero, evaltree raises EXEXIT exception.
8724  *
8725  * Perhaps we should avoid entering new trap handlers
8726  * while we are executing a trap handler. [is it a TODO?]
8727  */
8728 static void
8729 dotrap(void)
8730 {
8731         uint8_t *g;
8732         int sig;
8733         uint8_t last_status;
8734
8735         if (!pending_sig)
8736                 return;
8737
8738         last_status = exitstatus;
8739         pending_sig = 0;
8740         barrier();
8741
8742         TRACE(("dotrap entered\n"));
8743         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8744                 char *p;
8745
8746                 if (!*g)
8747                         continue;
8748
8749                 if (evalskip) {
8750                         pending_sig = sig;
8751                         break;
8752                 }
8753
8754                 p = trap[sig];
8755                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8756                  * don't upset it by resetting gotsig[SIGINT-1] */
8757                 if (sig == SIGINT && !p)
8758                         continue;
8759
8760                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8761                 *g = 0;
8762                 if (!p)
8763                         continue;
8764                 evalstring(p, 0);
8765         }
8766         exitstatus = last_status;
8767         TRACE(("dotrap returns\n"));
8768 }
8769
8770 /* forward declarations - evaluation is fairly recursive business... */
8771 static int evalloop(union node *, int);
8772 static int evalfor(union node *, int);
8773 static int evalcase(union node *, int);
8774 static int evalsubshell(union node *, int);
8775 static void expredir(union node *);
8776 static int evalpipe(union node *, int);
8777 static int evalcommand(union node *, int);
8778 static int evalbltin(const struct builtincmd *, int, char **, int);
8779 static void prehash(union node *);
8780
8781 /*
8782  * Evaluate a parse tree.  The value is left in the global variable
8783  * exitstatus.
8784  */
8785 static int
8786 evaltree(union node *n, int flags)
8787 {
8788         int checkexit = 0;
8789         int (*evalfn)(union node *, int);
8790         int status = 0;
8791
8792         if (n == NULL) {
8793                 TRACE(("evaltree(NULL) called\n"));
8794                 goto out;
8795         }
8796         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8797
8798         dotrap();
8799
8800         switch (n->type) {
8801         default:
8802 #if DEBUG
8803                 out1fmt("Node type = %d\n", n->type);
8804                 fflush_all();
8805                 break;
8806 #endif
8807         case NNOT:
8808                 status = !evaltree(n->nnot.com, EV_TESTED);
8809                 goto setstatus;
8810         case NREDIR:
8811                 expredir(n->nredir.redirect);
8812                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8813                 if (!status) {
8814                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8815                 }
8816                 if (n->nredir.redirect)
8817                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8818                 goto setstatus;
8819         case NCMD:
8820                 evalfn = evalcommand;
8821  checkexit:
8822                 if (eflag && !(flags & EV_TESTED))
8823                         checkexit = ~0;
8824                 goto calleval;
8825         case NFOR:
8826                 evalfn = evalfor;
8827                 goto calleval;
8828         case NWHILE:
8829         case NUNTIL:
8830                 evalfn = evalloop;
8831                 goto calleval;
8832         case NSUBSHELL:
8833         case NBACKGND:
8834                 evalfn = evalsubshell;
8835                 goto checkexit;
8836         case NPIPE:
8837                 evalfn = evalpipe;
8838                 goto checkexit;
8839         case NCASE:
8840                 evalfn = evalcase;
8841                 goto calleval;
8842         case NAND:
8843         case NOR:
8844         case NSEMI: {
8845
8846 #if NAND + 1 != NOR
8847 #error NAND + 1 != NOR
8848 #endif
8849 #if NOR + 1 != NSEMI
8850 #error NOR + 1 != NSEMI
8851 #endif
8852                 unsigned is_or = n->type - NAND;
8853                 status = evaltree(
8854                         n->nbinary.ch1,
8855                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8856                 );
8857                 if ((!status) == is_or || evalskip)
8858                         break;
8859                 n = n->nbinary.ch2;
8860  evaln:
8861                 evalfn = evaltree;
8862  calleval:
8863                 status = evalfn(n, flags);
8864                 goto setstatus;
8865         }
8866         case NIF:
8867                 status = evaltree(n->nif.test, EV_TESTED);
8868                 if (evalskip)
8869                         break;
8870                 if (!status) {
8871                         n = n->nif.ifpart;
8872                         goto evaln;
8873                 }
8874                 if (n->nif.elsepart) {
8875                         n = n->nif.elsepart;
8876                         goto evaln;
8877                 }
8878                 status = 0;
8879                 goto setstatus;
8880         case NDEFUN:
8881                 defun(n);
8882                 /* Not necessary. To test it:
8883                  * "false; f() { qwerty; }; echo $?" should print 0.
8884                  */
8885                 /* status = 0; */
8886  setstatus:
8887                 exitstatus = status;
8888                 break;
8889         }
8890  out:
8891         /* Order of checks below is important:
8892          * signal handlers trigger before exit caused by "set -e".
8893          */
8894         dotrap();
8895
8896         if (checkexit & status)
8897                 raise_exception(EXEXIT);
8898         if (flags & EV_EXIT)
8899                 raise_exception(EXEXIT);
8900
8901         TRACE(("leaving evaltree (no interrupts)\n"));
8902         return exitstatus;
8903 }
8904
8905 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8906 static
8907 #endif
8908 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8909
8910 static int
8911 skiploop(void)
8912 {
8913         int skip = evalskip;
8914
8915         switch (skip) {
8916         case 0:
8917                 break;
8918         case SKIPBREAK:
8919         case SKIPCONT:
8920                 if (--skipcount <= 0) {
8921                         evalskip = 0;
8922                         break;
8923                 }
8924                 skip = SKIPBREAK;
8925                 break;
8926         }
8927         return skip;
8928 }
8929
8930 static int
8931 evalloop(union node *n, int flags)
8932 {
8933         int skip;
8934         int status;
8935
8936         loopnest++;
8937         status = 0;
8938         flags &= EV_TESTED;
8939         do {
8940                 int i;
8941
8942                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8943                 skip = skiploop();
8944                 if (skip == SKIPFUNC)
8945                         status = i;
8946                 if (skip)
8947                         continue;
8948                 if (n->type != NWHILE)
8949                         i = !i;
8950                 if (i != 0)
8951                         break;
8952                 status = evaltree(n->nbinary.ch2, flags);
8953                 skip = skiploop();
8954         } while (!(skip & ~SKIPCONT));
8955         loopnest--;
8956
8957         return status;
8958 }
8959
8960 static int
8961 evalfor(union node *n, int flags)
8962 {
8963         struct arglist arglist;
8964         union node *argp;
8965         struct strlist *sp;
8966         struct stackmark smark;
8967         int status = 0;
8968
8969         setstackmark(&smark);
8970         arglist.list = NULL;
8971         arglist.lastp = &arglist.list;
8972         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8973                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8974         }
8975         *arglist.lastp = NULL;
8976
8977         loopnest++;
8978         flags &= EV_TESTED;
8979         for (sp = arglist.list; sp; sp = sp->next) {
8980                 setvar0(n->nfor.var, sp->text);
8981                 status = evaltree(n->nfor.body, flags);
8982                 if (skiploop() & ~SKIPCONT)
8983                         break;
8984         }
8985         loopnest--;
8986         popstackmark(&smark);
8987
8988         return status;
8989 }
8990
8991 static int
8992 evalcase(union node *n, int flags)
8993 {
8994         union node *cp;
8995         union node *patp;
8996         struct arglist arglist;
8997         struct stackmark smark;
8998         int status = 0;
8999
9000         setstackmark(&smark);
9001         arglist.list = NULL;
9002         arglist.lastp = &arglist.list;
9003         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9004         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9005                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9006                         if (casematch(patp, arglist.list->text)) {
9007                                 /* Ensure body is non-empty as otherwise
9008                                  * EV_EXIT may prevent us from setting the
9009                                  * exit status.
9010                                  */
9011                                 if (evalskip == 0 && cp->nclist.body) {
9012                                         status = evaltree(cp->nclist.body, flags);
9013                                 }
9014                                 goto out;
9015                         }
9016                 }
9017         }
9018  out:
9019         popstackmark(&smark);
9020
9021         return status;
9022 }
9023
9024 /*
9025  * Kick off a subshell to evaluate a tree.
9026  */
9027 static int
9028 evalsubshell(union node *n, int flags)
9029 {
9030         struct job *jp;
9031         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9032         int status;
9033
9034         expredir(n->nredir.redirect);
9035         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9036                 goto nofork;
9037         INT_OFF;
9038         if (backgnd == FORK_FG)
9039                 get_tty_state();
9040         jp = makejob(/*n,*/ 1);
9041         if (forkshell(jp, n, backgnd) == 0) {
9042                 /* child */
9043                 INT_ON;
9044                 flags |= EV_EXIT;
9045                 if (backgnd)
9046                         flags &= ~EV_TESTED;
9047  nofork:
9048                 redirect(n->nredir.redirect, 0);
9049                 evaltreenr(n->nredir.n, flags);
9050                 /* never returns */
9051         }
9052         /* parent */
9053         status = 0;
9054         if (backgnd == FORK_FG)
9055                 status = waitforjob(jp);
9056         INT_ON;
9057         return status;
9058 }
9059
9060 /*
9061  * Compute the names of the files in a redirection list.
9062  */
9063 static void fixredir(union node *, const char *, int);
9064 static void
9065 expredir(union node *n)
9066 {
9067         union node *redir;
9068
9069         for (redir = n; redir; redir = redir->nfile.next) {
9070                 struct arglist fn;
9071
9072                 fn.list = NULL;
9073                 fn.lastp = &fn.list;
9074                 switch (redir->type) {
9075                 case NFROMTO:
9076                 case NFROM:
9077                 case NTO:
9078 #if BASH_REDIR_OUTPUT
9079                 case NTO2:
9080 #endif
9081                 case NCLOBBER:
9082                 case NAPPEND:
9083                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9084                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9085 #if BASH_REDIR_OUTPUT
9086  store_expfname:
9087 #endif
9088 #if 0
9089 // By the design of stack allocator, the loop of this kind:
9090 //      while true; do while true; do break; done </dev/null; done
9091 // will look like a memory leak: ash plans to free expfname's
9092 // of "/dev/null" as soon as it finishes running the loop
9093 // (in this case, never).
9094 // This "fix" is wrong:
9095                         if (redir->nfile.expfname)
9096                                 stunalloc(redir->nfile.expfname);
9097 // It results in corrupted state of stacked allocations.
9098 #endif
9099                         redir->nfile.expfname = fn.list->text;
9100                         break;
9101                 case NFROMFD:
9102                 case NTOFD: /* >& */
9103                         if (redir->ndup.vname) {
9104                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9105                                 if (fn.list == NULL)
9106                                         ash_msg_and_raise_error("redir error");
9107 #if BASH_REDIR_OUTPUT
9108 //FIXME: we used expandarg with different args!
9109                                 if (!isdigit_str9(fn.list->text)) {
9110                                         /* >&file, not >&fd */
9111                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9112                                                 ash_msg_and_raise_error("redir error");
9113                                         redir->type = NTO2;
9114                                         goto store_expfname;
9115                                 }
9116 #endif
9117                                 fixredir(redir, fn.list->text, 1);
9118                         }
9119                         break;
9120                 }
9121         }
9122 }
9123
9124 /*
9125  * Evaluate a pipeline.  All the processes in the pipeline are children
9126  * of the process creating the pipeline.  (This differs from some versions
9127  * of the shell, which make the last process in a pipeline the parent
9128  * of all the rest.)
9129  */
9130 static int
9131 evalpipe(union node *n, int flags)
9132 {
9133         struct job *jp;
9134         struct nodelist *lp;
9135         int pipelen;
9136         int prevfd;
9137         int pip[2];
9138         int status = 0;
9139
9140         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9141         pipelen = 0;
9142         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9143                 pipelen++;
9144         flags |= EV_EXIT;
9145         INT_OFF;
9146         if (n->npipe.pipe_backgnd == 0)
9147                 get_tty_state();
9148         jp = makejob(/*n,*/ pipelen);
9149         prevfd = -1;
9150         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9151                 prehash(lp->n);
9152                 pip[1] = -1;
9153                 if (lp->next) {
9154                         if (pipe(pip) < 0) {
9155                                 close(prevfd);
9156                                 ash_msg_and_raise_error("pipe call failed");
9157                         }
9158                 }
9159                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9160                         /* child */
9161                         INT_ON;
9162                         if (pip[1] >= 0) {
9163                                 close(pip[0]);
9164                         }
9165                         if (prevfd > 0) {
9166                                 dup2(prevfd, 0);
9167                                 close(prevfd);
9168                         }
9169                         if (pip[1] > 1) {
9170                                 dup2(pip[1], 1);
9171                                 close(pip[1]);
9172                         }
9173                         evaltreenr(lp->n, flags);
9174                         /* never returns */
9175                 }
9176                 /* parent */
9177                 if (prevfd >= 0)
9178                         close(prevfd);
9179                 prevfd = pip[0];
9180                 /* Don't want to trigger debugging */
9181                 if (pip[1] != -1)
9182                         close(pip[1]);
9183         }
9184         if (n->npipe.pipe_backgnd == 0) {
9185                 status = waitforjob(jp);
9186                 TRACE(("evalpipe:  job done exit status %d\n", status));
9187         }
9188         INT_ON;
9189
9190         return status;
9191 }
9192
9193 /*
9194  * Controls whether the shell is interactive or not.
9195  */
9196 static void
9197 setinteractive(int on)
9198 {
9199         static smallint is_interactive;
9200
9201         if (++on == is_interactive)
9202                 return;
9203         is_interactive = on;
9204         setsignal(SIGINT);
9205         setsignal(SIGQUIT);
9206         setsignal(SIGTERM);
9207 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9208         if (is_interactive > 1) {
9209                 /* Looks like they want an interactive shell */
9210                 static smallint did_banner;
9211
9212                 if (!did_banner) {
9213                         /* note: ash and hush share this string */
9214                         out1fmt("\n\n%s %s\n"
9215                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9216                                 "\n",
9217                                 bb_banner,
9218                                 "built-in shell (ash)"
9219                         );
9220                         did_banner = 1;
9221                 }
9222         }
9223 #endif
9224 }
9225
9226 static void
9227 optschanged(void)
9228 {
9229 #if DEBUG
9230         opentrace();
9231 #endif
9232         setinteractive(iflag);
9233         setjobctl(mflag);
9234 #if ENABLE_FEATURE_EDITING_VI
9235         if (viflag)
9236                 line_input_state->flags |= VI_MODE;
9237         else
9238                 line_input_state->flags &= ~VI_MODE;
9239 #else
9240         viflag = 0; /* forcibly keep the option off */
9241 #endif
9242 }
9243
9244 static struct localvar *localvars;
9245
9246 /*
9247  * Called after a function returns.
9248  * Interrupts must be off.
9249  */
9250 static void
9251 poplocalvars(void)
9252 {
9253         struct localvar *lvp;
9254         struct var *vp;
9255
9256         while ((lvp = localvars) != NULL) {
9257                 localvars = lvp->next;
9258                 vp = lvp->vp;
9259                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9260                 if (vp == NULL) {       /* $- saved */
9261                         memcpy(optlist, lvp->text, sizeof(optlist));
9262                         free((char*)lvp->text);
9263                         optschanged();
9264                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9265                         unsetvar(vp->var_text);
9266                 } else {
9267                         if (vp->var_func)
9268                                 vp->var_func(var_end(lvp->text));
9269                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9270                                 free((char*)vp->var_text);
9271                         vp->flags = lvp->flags;
9272                         vp->var_text = lvp->text;
9273                 }
9274                 free(lvp);
9275         }
9276 }
9277
9278 static int
9279 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9280 {
9281         volatile struct shparam saveparam;
9282         struct localvar *volatile savelocalvars;
9283         struct jmploc *volatile savehandler;
9284         struct jmploc jmploc;
9285         int e;
9286
9287         saveparam = shellparam;
9288         savelocalvars = localvars;
9289         savehandler = exception_handler;
9290         e = setjmp(jmploc.loc);
9291         if (e) {
9292                 goto funcdone;
9293         }
9294         INT_OFF;
9295         exception_handler = &jmploc;
9296         localvars = NULL;
9297         shellparam.malloced = 0;
9298         func->count++;
9299         funcnest++;
9300         INT_ON;
9301         shellparam.nparam = argc - 1;
9302         shellparam.p = argv + 1;
9303 #if ENABLE_ASH_GETOPTS
9304         shellparam.optind = 1;
9305         shellparam.optoff = -1;
9306 #endif
9307         evaltree(func->n.narg.next, flags & EV_TESTED);
9308  funcdone:
9309         INT_OFF;
9310         funcnest--;
9311         freefunc(func);
9312         poplocalvars();
9313         localvars = savelocalvars;
9314         freeparam(&shellparam);
9315         shellparam = saveparam;
9316         exception_handler = savehandler;
9317         INT_ON;
9318         evalskip &= ~SKIPFUNC;
9319         return e;
9320 }
9321
9322 /*
9323  * Make a variable a local variable.  When a variable is made local, it's
9324  * value and flags are saved in a localvar structure.  The saved values
9325  * will be restored when the shell function returns.  We handle the name
9326  * "-" as a special case: it makes changes to "set +-options" local
9327  * (options will be restored on return from the function).
9328  */
9329 static void
9330 mklocal(char *name)
9331 {
9332         struct localvar *lvp;
9333         struct var **vpp;
9334         struct var *vp;
9335         char *eq = strchr(name, '=');
9336
9337         INT_OFF;
9338         /* Cater for duplicate "local". Examples:
9339          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9340          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9341          */
9342         lvp = localvars;
9343         while (lvp) {
9344                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9345                         if (eq)
9346                                 setvareq(name, 0);
9347                         /* else:
9348                          * it's a duplicate "local VAR" declaration, do nothing
9349                          */
9350                         goto ret;
9351                 }
9352                 lvp = lvp->next;
9353         }
9354
9355         lvp = ckzalloc(sizeof(*lvp));
9356         if (LONE_DASH(name)) {
9357                 char *p;
9358                 p = ckmalloc(sizeof(optlist));
9359                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9360                 vp = NULL;
9361         } else {
9362                 vpp = hashvar(name);
9363                 vp = *findvar(vpp, name);
9364                 if (vp == NULL) {
9365                         /* variable did not exist yet */
9366                         if (eq)
9367                                 setvareq(name, VSTRFIXED);
9368                         else
9369                                 setvar(name, NULL, VSTRFIXED);
9370                         vp = *vpp;      /* the new variable */
9371                         lvp->flags = VUNSET;
9372                 } else {
9373                         lvp->text = vp->var_text;
9374                         lvp->flags = vp->flags;
9375                         /* make sure neither "struct var" nor string gets freed
9376                          * during (un)setting:
9377                          */
9378                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9379                         if (eq)
9380                                 setvareq(name, 0);
9381                         else
9382                                 /* "local VAR" unsets VAR: */
9383                                 setvar0(name, NULL);
9384                 }
9385         }
9386         lvp->vp = vp;
9387         lvp->next = localvars;
9388         localvars = lvp;
9389  ret:
9390         INT_ON;
9391 }
9392
9393 /*
9394  * The "local" command.
9395  */
9396 static int FAST_FUNC
9397 localcmd(int argc UNUSED_PARAM, char **argv)
9398 {
9399         char *name;
9400
9401         if (!funcnest)
9402                 ash_msg_and_raise_error("not in a function");
9403
9404         argv = argptr;
9405         while ((name = *argv++) != NULL) {
9406                 mklocal(name);
9407         }
9408         return 0;
9409 }
9410
9411 static int FAST_FUNC
9412 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9413 {
9414         return 1;
9415 }
9416
9417 static int FAST_FUNC
9418 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9419 {
9420         return 0;
9421 }
9422
9423 static int FAST_FUNC
9424 execcmd(int argc UNUSED_PARAM, char **argv)
9425 {
9426         optionarg = NULL;
9427         while (nextopt("a:") != '\0')
9428                 /* nextopt() sets optionarg to "-a ARGV0" */;
9429
9430         argv = argptr;
9431         if (argv[0]) {
9432                 char *prog;
9433
9434                 iflag = 0;              /* exit on error */
9435                 mflag = 0;
9436                 optschanged();
9437                 /* We should set up signals for "exec CMD"
9438                  * the same way as for "CMD" without "exec".
9439                  * But optschanged->setinteractive->setsignal
9440                  * still thought we are a root shell. Therefore, for example,
9441                  * SIGQUIT is still set to IGN. Fix it:
9442                  */
9443                 shlvl++;
9444                 setsignal(SIGQUIT);
9445                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9446                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9447                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9448
9449                 prog = argv[0];
9450                 if (optionarg)
9451                         argv[0] = optionarg;
9452                 shellexec(prog, argv, pathval(), 0);
9453                 /* NOTREACHED */
9454         }
9455         return 0;
9456 }
9457
9458 /*
9459  * The return command.
9460  */
9461 static int FAST_FUNC
9462 returncmd(int argc UNUSED_PARAM, char **argv)
9463 {
9464         /*
9465          * If called outside a function, do what ksh does;
9466          * skip the rest of the file.
9467          */
9468         evalskip = SKIPFUNC;
9469         return argv[1] ? number(argv[1]) : exitstatus;
9470 }
9471
9472 /* Forward declarations for builtintab[] */
9473 static int breakcmd(int, char **) FAST_FUNC;
9474 static int dotcmd(int, char **) FAST_FUNC;
9475 static int evalcmd(int, char **, int) FAST_FUNC;
9476 static int exitcmd(int, char **) FAST_FUNC;
9477 static int exportcmd(int, char **) FAST_FUNC;
9478 #if ENABLE_ASH_GETOPTS
9479 static int getoptscmd(int, char **) FAST_FUNC;
9480 #endif
9481 #if ENABLE_ASH_HELP
9482 static int helpcmd(int, char **) FAST_FUNC;
9483 #endif
9484 #if MAX_HISTORY
9485 static int historycmd(int, char **) FAST_FUNC;
9486 #endif
9487 #if ENABLE_FEATURE_SH_MATH
9488 static int letcmd(int, char **) FAST_FUNC;
9489 #endif
9490 static int readcmd(int, char **) FAST_FUNC;
9491 static int setcmd(int, char **) FAST_FUNC;
9492 static int shiftcmd(int, char **) FAST_FUNC;
9493 static int timescmd(int, char **) FAST_FUNC;
9494 static int trapcmd(int, char **) FAST_FUNC;
9495 static int umaskcmd(int, char **) FAST_FUNC;
9496 static int unsetcmd(int, char **) FAST_FUNC;
9497 static int ulimitcmd(int, char **) FAST_FUNC;
9498
9499 #define BUILTIN_NOSPEC          "0"
9500 #define BUILTIN_SPECIAL         "1"
9501 #define BUILTIN_REGULAR         "2"
9502 #define BUILTIN_SPEC_REG        "3"
9503 #define BUILTIN_ASSIGN          "4"
9504 #define BUILTIN_SPEC_ASSG       "5"
9505 #define BUILTIN_REG_ASSG        "6"
9506 #define BUILTIN_SPEC_REG_ASSG   "7"
9507
9508 /* Stubs for calling non-FAST_FUNC's */
9509 #if ENABLE_ASH_ECHO
9510 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9511 #endif
9512 #if ENABLE_ASH_PRINTF
9513 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9514 #endif
9515 #if ENABLE_ASH_TEST || BASH_TEST2
9516 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9517 #endif
9518
9519 /* Keep these in proper order since it is searched via bsearch() */
9520 static const struct builtincmd builtintab[] = {
9521         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9522         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9523 #if ENABLE_ASH_TEST
9524         { BUILTIN_REGULAR       "["       , testcmd    },
9525 #endif
9526 #if BASH_TEST2
9527         { BUILTIN_REGULAR       "[["      , testcmd    },
9528 #endif
9529 #if ENABLE_ASH_ALIAS
9530         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9531 #endif
9532 #if JOBS
9533         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9534 #endif
9535         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9536         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9537         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9538 #if ENABLE_ASH_CMDCMD
9539         { BUILTIN_REGULAR       "command" , commandcmd },
9540 #endif
9541         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9542 #if ENABLE_ASH_ECHO
9543         { BUILTIN_REGULAR       "echo"    , echocmd    },
9544 #endif
9545         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9546         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9547         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9548         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9549         { BUILTIN_REGULAR       "false"   , falsecmd   },
9550 #if JOBS
9551         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9552 #endif
9553 #if ENABLE_ASH_GETOPTS
9554         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9555 #endif
9556         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9557 #if ENABLE_ASH_HELP
9558         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9559 #endif
9560 #if MAX_HISTORY
9561         { BUILTIN_NOSPEC        "history" , historycmd },
9562 #endif
9563 #if JOBS
9564         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9565         { BUILTIN_REGULAR       "kill"    , killcmd    },
9566 #endif
9567 #if ENABLE_FEATURE_SH_MATH
9568         { BUILTIN_NOSPEC        "let"     , letcmd     },
9569 #endif
9570         { BUILTIN_ASSIGN        "local"   , localcmd   },
9571 #if ENABLE_ASH_PRINTF
9572         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9573 #endif
9574         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9575         { BUILTIN_REGULAR       "read"    , readcmd    },
9576         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9577         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9578         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9579         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9580 #if BASH_SOURCE
9581         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9582 #endif
9583 #if ENABLE_ASH_TEST
9584         { BUILTIN_REGULAR       "test"    , testcmd    },
9585 #endif
9586         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9587         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9588         { BUILTIN_REGULAR       "true"    , truecmd    },
9589         { BUILTIN_NOSPEC        "type"    , typecmd    },
9590         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9591         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9592 #if ENABLE_ASH_ALIAS
9593         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9594 #endif
9595         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9596         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9597 };
9598
9599 /* Should match the above table! */
9600 #define COMMANDCMD (builtintab + \
9601         /* . : */       2 + \
9602         /* [ */         1 * ENABLE_ASH_TEST + \
9603         /* [[ */        1 * BASH_TEST2 + \
9604         /* alias */     1 * ENABLE_ASH_ALIAS + \
9605         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9606         /* break cd cddir  */   3)
9607 #define EVALCMD (COMMANDCMD + \
9608         /* command */   1 * ENABLE_ASH_CMDCMD + \
9609         /* continue */  1 + \
9610         /* echo */      1 * ENABLE_ASH_ECHO + \
9611         0)
9612 #define EXECCMD (EVALCMD + \
9613         /* eval */      1)
9614
9615 /*
9616  * Search the table of builtin commands.
9617  */
9618 static int
9619 pstrcmp1(const void *a, const void *b)
9620 {
9621         return strcmp((char*)a, *(char**)b + 1);
9622 }
9623 static struct builtincmd *
9624 find_builtin(const char *name)
9625 {
9626         struct builtincmd *bp;
9627
9628         bp = bsearch(
9629                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9630                 pstrcmp1
9631         );
9632         return bp;
9633 }
9634
9635 /*
9636  * Execute a simple command.
9637  */
9638 static int
9639 isassignment(const char *p)
9640 {
9641         const char *q = endofname(p);
9642         if (p == q)
9643                 return 0;
9644         return *q == '=';
9645 }
9646 static int FAST_FUNC
9647 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9648 {
9649         /* Preserve exitstatus of a previous possible redirection
9650          * as POSIX mandates */
9651         return back_exitstatus;
9652 }
9653 static int
9654 evalcommand(union node *cmd, int flags)
9655 {
9656         static const struct builtincmd null_bltin = {
9657                 "\0\0", bltincmd /* why three NULs? */
9658         };
9659         struct stackmark smark;
9660         union node *argp;
9661         struct arglist arglist;
9662         struct arglist varlist;
9663         char **argv;
9664         int argc;
9665         const struct strlist *sp;
9666         struct cmdentry cmdentry;
9667         struct job *jp;
9668         char *lastarg;
9669         const char *path;
9670         int spclbltin;
9671         int status;
9672         char **nargv;
9673         struct builtincmd *bcmd;
9674         smallint cmd_is_exec;
9675         smallint pseudovarflag = 0;
9676
9677         /* First expand the arguments. */
9678         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9679         setstackmark(&smark);
9680         back_exitstatus = 0;
9681
9682         cmdentry.cmdtype = CMDBUILTIN;
9683         cmdentry.u.cmd = &null_bltin;
9684         varlist.lastp = &varlist.list;
9685         *varlist.lastp = NULL;
9686         arglist.lastp = &arglist.list;
9687         *arglist.lastp = NULL;
9688
9689         argc = 0;
9690         if (cmd->ncmd.args) {
9691                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9692                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9693         }
9694
9695         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9696                 struct strlist **spp;
9697
9698                 spp = arglist.lastp;
9699                 if (pseudovarflag && isassignment(argp->narg.text))
9700                         expandarg(argp, &arglist, EXP_VARTILDE);
9701                 else
9702                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9703
9704                 for (sp = *spp; sp; sp = sp->next)
9705                         argc++;
9706         }
9707
9708         /* Reserve one extra spot at the front for shellexec. */
9709         nargv = stalloc(sizeof(char *) * (argc + 2));
9710         argv = ++nargv;
9711         for (sp = arglist.list; sp; sp = sp->next) {
9712                 TRACE(("evalcommand arg: %s\n", sp->text));
9713                 *nargv++ = sp->text;
9714         }
9715         *nargv = NULL;
9716
9717         lastarg = NULL;
9718         if (iflag && funcnest == 0 && argc > 0)
9719                 lastarg = nargv[-1];
9720
9721         preverrout_fd = 2;
9722         expredir(cmd->ncmd.redirect);
9723         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9724
9725         path = vpath.var_text;
9726         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9727                 struct strlist **spp;
9728                 char *p;
9729
9730                 spp = varlist.lastp;
9731                 expandarg(argp, &varlist, EXP_VARTILDE);
9732
9733                 /*
9734                  * Modify the command lookup path, if a PATH= assignment
9735                  * is present
9736                  */
9737                 p = (*spp)->text;
9738                 if (varcmp(p, path) == 0)
9739                         path = p;
9740         }
9741
9742         /* Print the command if xflag is set. */
9743         if (xflag) {
9744                 const char *pfx = "";
9745
9746                 fdprintf(preverrout_fd, "%s", expandstr(ps4val()));
9747
9748                 sp = varlist.list;
9749                 while (sp) {
9750                         char *varval = sp->text;
9751                         char *eq = strchrnul(varval, '=');
9752                         if (*eq)
9753                                 eq++;
9754                         fdprintf(preverrout_fd, "%s%.*s%s",
9755                                 pfx,
9756                                 (int)(eq - varval), varval,
9757                                 maybe_single_quote(eq)
9758                         );
9759                         sp = sp->next;
9760                         pfx = " ";
9761                 }
9762
9763                 sp = arglist.list;
9764                 while (sp) {
9765                         fdprintf(preverrout_fd, "%s%s",
9766                                 pfx,
9767                                 /* always quote if matches reserved word: */
9768                                 findkwd(sp->text)
9769                                 ? single_quote(sp->text)
9770                                 : maybe_single_quote(sp->text)
9771                         );
9772                         sp = sp->next;
9773                         pfx = " ";
9774                 }
9775                 safe_write(preverrout_fd, "\n", 1);
9776         }
9777
9778         cmd_is_exec = 0;
9779         spclbltin = -1;
9780
9781         /* Now locate the command. */
9782         if (argc) {
9783                 int cmd_flag = DO_ERR;
9784 #if ENABLE_ASH_CMDCMD
9785                 const char *oldpath = path + 5;
9786 #endif
9787                 path += 5;
9788                 for (;;) {
9789                         find_command(argv[0], &cmdentry, cmd_flag, path);
9790                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9791                                 flush_stdout_stderr();
9792                                 status = 127;
9793                                 goto bail;
9794                         }
9795
9796                         /* implement bltin and command here */
9797                         if (cmdentry.cmdtype != CMDBUILTIN)
9798                                 break;
9799                         if (spclbltin < 0)
9800                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9801                         if (cmdentry.u.cmd == EXECCMD)
9802                                 cmd_is_exec = 1;
9803 #if ENABLE_ASH_CMDCMD
9804                         if (cmdentry.u.cmd == COMMANDCMD) {
9805                                 path = oldpath;
9806                                 nargv = parse_command_args(argv, &path);
9807                                 if (!nargv)
9808                                         break;
9809                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9810                                  * nargv => "PROG". path is updated if -p.
9811                                  */
9812                                 argc -= nargv - argv;
9813                                 argv = nargv;
9814                                 cmd_flag |= DO_NOFUNC;
9815                         } else
9816 #endif
9817                                 break;
9818                 }
9819         }
9820
9821         if (status) {
9822  bail:
9823                 exitstatus = status;
9824
9825                 /* We have a redirection error. */
9826                 if (spclbltin > 0)
9827                         raise_exception(EXERROR);
9828
9829                 goto out;
9830         }
9831
9832         /* Execute the command. */
9833         switch (cmdentry.cmdtype) {
9834         default: {
9835
9836 #if ENABLE_FEATURE_SH_NOFORK
9837 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9838  *     around run_nofork_applet() call.
9839  * (2) Should this check also be done in forkshell()?
9840  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9841  */
9842                 /* find_command() encodes applet_no as (-2 - applet_no) */
9843                 int applet_no = (- cmdentry.u.index - 2);
9844                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9845                         listsetvar(varlist.list, VEXPORT|VSTACK);
9846                         /* run <applet>_main() */
9847                         status = run_nofork_applet(applet_no, argv);
9848                         break;
9849                 }
9850 #endif
9851                 /* Can we avoid forking off? For example, very last command
9852                  * in a script or a subshell does not need forking,
9853                  * we can just exec it.
9854                  */
9855                 if (!(flags & EV_EXIT) || may_have_traps) {
9856                         /* No, forking off a child is necessary */
9857                         INT_OFF;
9858                         get_tty_state();
9859                         jp = makejob(/*cmd,*/ 1);
9860                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9861                                 /* parent */
9862                                 status = waitforjob(jp);
9863                                 INT_ON;
9864                                 TRACE(("forked child exited with %d\n", status));
9865                                 break;
9866                         }
9867                         /* child */
9868                         FORCE_INT_ON;
9869                         /* fall through to exec'ing external program */
9870                 }
9871                 listsetvar(varlist.list, VEXPORT|VSTACK);
9872                 shellexec(argv[0], argv, path, cmdentry.u.index);
9873                 /* NOTREACHED */
9874         } /* default */
9875         case CMDBUILTIN:
9876                 cmdenviron = varlist.list;
9877                 if (cmdenviron) {
9878                         struct strlist *list = cmdenviron;
9879                         int i = VNOSET;
9880                         if (spclbltin > 0 || argc == 0) {
9881                                 i = 0;
9882                                 if (cmd_is_exec && argc > 1)
9883                                         i = VEXPORT;
9884                         }
9885                         listsetvar(list, i);
9886                 }
9887                 /* Tight loop with builtins only:
9888                  * "while kill -0 $child; do true; done"
9889                  * will never exit even if $child died, unless we do this
9890                  * to reap the zombie and make kill detect that it's gone: */
9891                 dowait(DOWAIT_NONBLOCK, NULL);
9892
9893                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9894                         if (exception_type == EXERROR && spclbltin <= 0) {
9895                                 FORCE_INT_ON;
9896                                 goto readstatus;
9897                         }
9898  raise:
9899                         longjmp(exception_handler->loc, 1);
9900                 }
9901                 goto readstatus;
9902
9903         case CMDFUNCTION:
9904                 listsetvar(varlist.list, 0);
9905                 /* See above for the rationale */
9906                 dowait(DOWAIT_NONBLOCK, NULL);
9907                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9908                         goto raise;
9909  readstatus:
9910                 status = exitstatus;
9911                 break;
9912         } /* switch */
9913
9914  out:
9915         if (cmd->ncmd.redirect)
9916                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9917         if (lastarg) {
9918                 /* dsl: I think this is intended to be used to support
9919                  * '_' in 'vi' command mode during line editing...
9920                  * However I implemented that within libedit itself.
9921                  */
9922                 setvar0("_", lastarg);
9923         }
9924         popstackmark(&smark);
9925
9926         return status;
9927 }
9928
9929 static int
9930 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9931 {
9932         char *volatile savecmdname;
9933         struct jmploc *volatile savehandler;
9934         struct jmploc jmploc;
9935         int status;
9936         int i;
9937
9938         savecmdname = commandname;
9939         savehandler = exception_handler;
9940         i = setjmp(jmploc.loc);
9941         if (i)
9942                 goto cmddone;
9943         exception_handler = &jmploc;
9944         commandname = argv[0];
9945         argptr = argv + 1;
9946         optptr = NULL;                  /* initialize nextopt */
9947         if (cmd == EVALCMD)
9948                 status = evalcmd(argc, argv, flags);
9949         else
9950                 status = (*cmd->builtin)(argc, argv);
9951         flush_stdout_stderr();
9952         status |= ferror(stdout);
9953         exitstatus = status;
9954  cmddone:
9955         clearerr(stdout);
9956         commandname = savecmdname;
9957         exception_handler = savehandler;
9958
9959         return i;
9960 }
9961
9962 static int
9963 goodname(const char *p)
9964 {
9965         return endofname(p)[0] == '\0';
9966 }
9967
9968
9969 /*
9970  * Search for a command.  This is called before we fork so that the
9971  * location of the command will be available in the parent as well as
9972  * the child.  The check for "goodname" is an overly conservative
9973  * check that the name will not be subject to expansion.
9974  */
9975 static void
9976 prehash(union node *n)
9977 {
9978         struct cmdentry entry;
9979
9980         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9981                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9982 }
9983
9984
9985 /* ============ Builtin commands
9986  *
9987  * Builtin commands whose functions are closely tied to evaluation
9988  * are implemented here.
9989  */
9990
9991 /*
9992  * Handle break and continue commands.  Break, continue, and return are
9993  * all handled by setting the evalskip flag.  The evaluation routines
9994  * above all check this flag, and if it is set they start skipping
9995  * commands rather than executing them.  The variable skipcount is
9996  * the number of loops to break/continue, or the number of function
9997  * levels to return.  (The latter is always 1.)  It should probably
9998  * be an error to break out of more loops than exist, but it isn't
9999  * in the standard shell so we don't make it one here.
10000  */
10001 static int FAST_FUNC
10002 breakcmd(int argc UNUSED_PARAM, char **argv)
10003 {
10004         int n = argv[1] ? number(argv[1]) : 1;
10005
10006         if (n <= 0)
10007                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10008         if (n > loopnest)
10009                 n = loopnest;
10010         if (n > 0) {
10011                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10012                 skipcount = n;
10013         }
10014         return 0;
10015 }
10016
10017
10018 /*
10019  * This implements the input routines used by the parser.
10020  */
10021
10022 enum {
10023         INPUT_PUSH_FILE = 1,
10024         INPUT_NOFILE_OK = 2,
10025 };
10026
10027 static smallint checkkwd;
10028 /* values of checkkwd variable */
10029 #define CHKALIAS        0x1
10030 #define CHKKWD          0x2
10031 #define CHKNL           0x4
10032
10033 /*
10034  * Push a string back onto the input at this current parsefile level.
10035  * We handle aliases this way.
10036  */
10037 #if !ENABLE_ASH_ALIAS
10038 #define pushstring(s, ap) pushstring(s)
10039 #endif
10040 static void
10041 pushstring(char *s, struct alias *ap)
10042 {
10043         struct strpush *sp;
10044         int len;
10045
10046         len = strlen(s);
10047         INT_OFF;
10048         if (g_parsefile->strpush) {
10049                 sp = ckzalloc(sizeof(*sp));
10050                 sp->prev = g_parsefile->strpush;
10051         } else {
10052                 sp = &(g_parsefile->basestrpush);
10053         }
10054         g_parsefile->strpush = sp;
10055         sp->prev_string = g_parsefile->next_to_pgetc;
10056         sp->prev_left_in_line = g_parsefile->left_in_line;
10057         sp->unget = g_parsefile->unget;
10058         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10059 #if ENABLE_ASH_ALIAS
10060         sp->ap = ap;
10061         if (ap) {
10062                 ap->flag |= ALIASINUSE;
10063                 sp->string = s;
10064         }
10065 #endif
10066         g_parsefile->next_to_pgetc = s;
10067         g_parsefile->left_in_line = len;
10068         g_parsefile->unget = 0;
10069         INT_ON;
10070 }
10071
10072 static void
10073 popstring(void)
10074 {
10075         struct strpush *sp = g_parsefile->strpush;
10076
10077         INT_OFF;
10078 #if ENABLE_ASH_ALIAS
10079         if (sp->ap) {
10080                 if (g_parsefile->next_to_pgetc[-1] == ' '
10081                  || g_parsefile->next_to_pgetc[-1] == '\t'
10082                 ) {
10083                         checkkwd |= CHKALIAS;
10084                 }
10085                 if (sp->string != sp->ap->val) {
10086                         free(sp->string);
10087                 }
10088                 sp->ap->flag &= ~ALIASINUSE;
10089                 if (sp->ap->flag & ALIASDEAD) {
10090                         unalias(sp->ap->name);
10091                 }
10092         }
10093 #endif
10094         g_parsefile->next_to_pgetc = sp->prev_string;
10095         g_parsefile->left_in_line = sp->prev_left_in_line;
10096         g_parsefile->unget = sp->unget;
10097         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10098         g_parsefile->strpush = sp->prev;
10099         if (sp != &(g_parsefile->basestrpush))
10100                 free(sp);
10101         INT_ON;
10102 }
10103
10104 static int
10105 preadfd(void)
10106 {
10107         int nr;
10108         char *buf = g_parsefile->buf;
10109
10110         g_parsefile->next_to_pgetc = buf;
10111 #if ENABLE_FEATURE_EDITING
10112  retry:
10113         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10114                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10115         else {
10116                 int timeout = -1;
10117 # if ENABLE_ASH_IDLE_TIMEOUT
10118                 if (iflag) {
10119                         const char *tmout_var = lookupvar("TMOUT");
10120                         if (tmout_var) {
10121                                 timeout = atoi(tmout_var) * 1000;
10122                                 if (timeout <= 0)
10123                                         timeout = -1;
10124                         }
10125                 }
10126 # endif
10127 # if ENABLE_FEATURE_TAB_COMPLETION
10128                 line_input_state->path_lookup = pathval();
10129 # endif
10130                 reinit_unicode_for_ash();
10131                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10132                 if (nr == 0) {
10133                         /* ^C pressed, "convert" to SIGINT */
10134                         write(STDOUT_FILENO, "^C", 2);
10135                         if (trap[SIGINT]) {
10136                                 buf[0] = '\n';
10137                                 buf[1] = '\0';
10138                                 raise(SIGINT);
10139                                 return 1;
10140                         }
10141                         exitstatus = 128 + SIGINT;
10142                         bb_putchar('\n');
10143                         goto retry;
10144                 }
10145                 if (nr < 0) {
10146                         if (errno == 0) {
10147                                 /* Ctrl+D pressed */
10148                                 nr = 0;
10149                         }
10150 # if ENABLE_ASH_IDLE_TIMEOUT
10151                         else if (errno == EAGAIN && timeout > 0) {
10152                                 puts("\007timed out waiting for input: auto-logout");
10153                                 exitshell();
10154                         }
10155 # endif
10156                 }
10157         }
10158 #else
10159         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10160 #endif
10161
10162 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10163         if (nr < 0) {
10164                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10165                         int flags = fcntl(0, F_GETFL);
10166                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10167                                 flags &= ~O_NONBLOCK;
10168                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10169                                         out2str("sh: turning off NDELAY mode\n");
10170                                         goto retry;
10171                                 }
10172                         }
10173                 }
10174         }
10175 #endif
10176         return nr;
10177 }
10178
10179 /*
10180  * Refill the input buffer and return the next input character:
10181  *
10182  * 1) If a string was pushed back on the input, pop it;
10183  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10184  *    or we are reading from a string so we can't refill the buffer,
10185  *    return EOF.
10186  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10187  * 4) Process input up to the next newline, deleting nul characters.
10188  */
10189 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10190 #define pgetc_debug(...) ((void)0)
10191 static int pgetc(void);
10192 static int
10193 preadbuffer(void)
10194 {
10195         char *q;
10196         int more;
10197
10198         if (g_parsefile->strpush) {
10199 #if ENABLE_ASH_ALIAS
10200                 if (g_parsefile->left_in_line == -1
10201                  && g_parsefile->strpush->ap
10202                  && g_parsefile->next_to_pgetc[-1] != ' '
10203                  && g_parsefile->next_to_pgetc[-1] != '\t'
10204                 ) {
10205                         pgetc_debug("preadbuffer PEOA");
10206                         return PEOA;
10207                 }
10208 #endif
10209                 popstring();
10210                 return pgetc();
10211         }
10212         /* on both branches above g_parsefile->left_in_line < 0.
10213          * "pgetc" needs refilling.
10214          */
10215
10216         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10217          * pungetc() may increment it a few times.
10218          * Assuming it won't increment it to less than -90.
10219          */
10220         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10221                 pgetc_debug("preadbuffer PEOF1");
10222                 /* even in failure keep left_in_line and next_to_pgetc
10223                  * in lock step, for correct multi-layer pungetc.
10224                  * left_in_line was decremented before preadbuffer(),
10225                  * must inc next_to_pgetc: */
10226                 g_parsefile->next_to_pgetc++;
10227                 return PEOF;
10228         }
10229
10230         more = g_parsefile->left_in_buffer;
10231         if (more <= 0) {
10232                 flush_stdout_stderr();
10233  again:
10234                 more = preadfd();
10235                 if (more <= 0) {
10236                         /* don't try reading again */
10237                         g_parsefile->left_in_line = -99;
10238                         pgetc_debug("preadbuffer PEOF2");
10239                         g_parsefile->next_to_pgetc++;
10240                         return PEOF;
10241                 }
10242         }
10243
10244         /* Find out where's the end of line.
10245          * Set g_parsefile->left_in_line
10246          * and g_parsefile->left_in_buffer acordingly.
10247          * NUL chars are deleted.
10248          */
10249         q = g_parsefile->next_to_pgetc;
10250         for (;;) {
10251                 char c;
10252
10253                 more--;
10254
10255                 c = *q;
10256                 if (c == '\0') {
10257                         memmove(q, q + 1, more);
10258                 } else {
10259                         q++;
10260                         if (c == '\n') {
10261                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10262                                 break;
10263                         }
10264                 }
10265
10266                 if (more <= 0) {
10267                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10268                         if (g_parsefile->left_in_line < 0)
10269                                 goto again;
10270                         break;
10271                 }
10272         }
10273         g_parsefile->left_in_buffer = more;
10274
10275         if (vflag) {
10276                 char save = *q;
10277                 *q = '\0';
10278                 out2str(g_parsefile->next_to_pgetc);
10279                 *q = save;
10280         }
10281
10282         pgetc_debug("preadbuffer at %d:%p'%s'",
10283                         g_parsefile->left_in_line,
10284                         g_parsefile->next_to_pgetc,
10285                         g_parsefile->next_to_pgetc);
10286         return (unsigned char)*g_parsefile->next_to_pgetc++;
10287 }
10288
10289 static void
10290 nlprompt(void)
10291 {
10292         g_parsefile->linno++;
10293         setprompt_if(doprompt, 2);
10294 }
10295 static void
10296 nlnoprompt(void)
10297 {
10298         g_parsefile->linno++;
10299         needprompt = doprompt;
10300 }
10301
10302 static int
10303 pgetc(void)
10304 {
10305         int c;
10306
10307         pgetc_debug("pgetc at %d:%p'%s'",
10308                         g_parsefile->left_in_line,
10309                         g_parsefile->next_to_pgetc,
10310                         g_parsefile->next_to_pgetc);
10311         if (g_parsefile->unget)
10312                 return g_parsefile->lastc[--g_parsefile->unget];
10313
10314         if (--g_parsefile->left_in_line >= 0)
10315                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10316         else
10317                 c = preadbuffer();
10318
10319         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10320         g_parsefile->lastc[0] = c;
10321
10322         return c;
10323 }
10324
10325 #if ENABLE_ASH_ALIAS
10326 static int
10327 pgetc_without_PEOA(void)
10328 {
10329         int c;
10330         do {
10331                 pgetc_debug("pgetc at %d:%p'%s'",
10332                                 g_parsefile->left_in_line,
10333                                 g_parsefile->next_to_pgetc,
10334                                 g_parsefile->next_to_pgetc);
10335                 c = pgetc();
10336         } while (c == PEOA);
10337         return c;
10338 }
10339 #else
10340 # define pgetc_without_PEOA() pgetc()
10341 #endif
10342
10343 /*
10344  * Read a line from the script.
10345  */
10346 static char *
10347 pfgets(char *line, int len)
10348 {
10349         char *p = line;
10350         int nleft = len;
10351         int c;
10352
10353         while (--nleft > 0) {
10354                 c = pgetc_without_PEOA();
10355                 if (c == PEOF) {
10356                         if (p == line)
10357                                 return NULL;
10358                         break;
10359                 }
10360                 *p++ = c;
10361                 if (c == '\n')
10362                         break;
10363         }
10364         *p = '\0';
10365         return line;
10366 }
10367
10368 /*
10369  * Undo a call to pgetc.  Only two characters may be pushed back.
10370  * PEOF may be pushed back.
10371  */
10372 static void
10373 pungetc(void)
10374 {
10375         g_parsefile->unget++;
10376 }
10377
10378 /* This one eats backslash+newline */
10379 static int
10380 pgetc_eatbnl(void)
10381 {
10382         int c;
10383
10384         while ((c = pgetc()) == '\\') {
10385                 if (pgetc() != '\n') {
10386                         pungetc();
10387                         break;
10388                 }
10389
10390                 nlprompt();
10391         }
10392
10393         return c;
10394 }
10395
10396 /*
10397  * To handle the "." command, a stack of input files is used.  Pushfile
10398  * adds a new entry to the stack and popfile restores the previous level.
10399  */
10400 static void
10401 pushfile(void)
10402 {
10403         struct parsefile *pf;
10404
10405         pf = ckzalloc(sizeof(*pf));
10406         pf->prev = g_parsefile;
10407         pf->pf_fd = -1;
10408         /*pf->strpush = NULL; - ckzalloc did it */
10409         /*pf->basestrpush.prev = NULL;*/
10410         /*pf->unget = 0;*/
10411         g_parsefile = pf;
10412 }
10413
10414 static void
10415 popfile(void)
10416 {
10417         struct parsefile *pf = g_parsefile;
10418
10419         if (pf == &basepf)
10420                 return;
10421
10422         INT_OFF;
10423         if (pf->pf_fd >= 0)
10424                 close(pf->pf_fd);
10425         free(pf->buf);
10426         while (pf->strpush)
10427                 popstring();
10428         g_parsefile = pf->prev;
10429         free(pf);
10430         INT_ON;
10431 }
10432
10433 /*
10434  * Return to top level.
10435  */
10436 static void
10437 popallfiles(void)
10438 {
10439         while (g_parsefile != &basepf)
10440                 popfile();
10441 }
10442
10443 /*
10444  * Close the file(s) that the shell is reading commands from.  Called
10445  * after a fork is done.
10446  */
10447 static void
10448 closescript(void)
10449 {
10450         popallfiles();
10451         if (g_parsefile->pf_fd > 0) {
10452                 close(g_parsefile->pf_fd);
10453                 g_parsefile->pf_fd = 0;
10454         }
10455 }
10456
10457 /*
10458  * Like setinputfile, but takes an open file descriptor.  Call this with
10459  * interrupts off.
10460  */
10461 static void
10462 setinputfd(int fd, int push)
10463 {
10464         if (push) {
10465                 pushfile();
10466                 g_parsefile->buf = NULL;
10467         }
10468         g_parsefile->pf_fd = fd;
10469         if (g_parsefile->buf == NULL)
10470                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10471         g_parsefile->left_in_buffer = 0;
10472         g_parsefile->left_in_line = 0;
10473         g_parsefile->linno = 1;
10474 }
10475
10476 /*
10477  * Set the input to take input from a file.  If push is set, push the
10478  * old input onto the stack first.
10479  */
10480 static int
10481 setinputfile(const char *fname, int flags)
10482 {
10483         int fd;
10484
10485         INT_OFF;
10486         fd = open(fname, O_RDONLY);
10487         if (fd < 0) {
10488                 if (flags & INPUT_NOFILE_OK)
10489                         goto out;
10490                 exitstatus = 127;
10491                 ash_msg_and_raise_error("can't open '%s'", fname);
10492         }
10493         if (fd < 10)
10494                 fd = savefd(fd);
10495         else
10496                 close_on_exec_on(fd);
10497         setinputfd(fd, flags & INPUT_PUSH_FILE);
10498  out:
10499         INT_ON;
10500         return fd;
10501 }
10502
10503 /*
10504  * Like setinputfile, but takes input from a string.
10505  */
10506 static void
10507 setinputstring(char *string)
10508 {
10509         INT_OFF;
10510         pushfile();
10511         g_parsefile->next_to_pgetc = string;
10512         g_parsefile->left_in_line = strlen(string);
10513         g_parsefile->buf = NULL;
10514         g_parsefile->linno = 1;
10515         INT_ON;
10516 }
10517
10518
10519 /*
10520  * Routines to check for mail.
10521  */
10522
10523 #if ENABLE_ASH_MAIL
10524
10525 /* Hash of mtimes of mailboxes */
10526 static unsigned mailtime_hash;
10527 /* Set if MAIL or MAILPATH is changed. */
10528 static smallint mail_var_path_changed;
10529
10530 /*
10531  * Print appropriate message(s) if mail has arrived.
10532  * If mail_var_path_changed is set,
10533  * then the value of MAIL has mail_var_path_changed,
10534  * so we just update the values.
10535  */
10536 static void
10537 chkmail(void)
10538 {
10539         const char *mpath;
10540         char *p;
10541         char *q;
10542         unsigned new_hash;
10543         struct stackmark smark;
10544         struct stat statb;
10545
10546         setstackmark(&smark);
10547         mpath = mpathset() ? mpathval() : mailval();
10548         new_hash = 0;
10549         for (;;) {
10550                 p = path_advance(&mpath, nullstr);
10551                 if (p == NULL)
10552                         break;
10553                 if (*p == '\0')
10554                         continue;
10555                 for (q = p; *q; q++)
10556                         continue;
10557 #if DEBUG
10558                 if (q[-1] != '/')
10559                         abort();
10560 #endif
10561                 q[-1] = '\0';                   /* delete trailing '/' */
10562                 if (stat(p, &statb) < 0) {
10563                         continue;
10564                 }
10565                 /* Very simplistic "hash": just a sum of all mtimes */
10566                 new_hash += (unsigned)statb.st_mtime;
10567         }
10568         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10569                 if (mailtime_hash != 0)
10570                         out2str("you have mail\n");
10571                 mailtime_hash = new_hash;
10572         }
10573         mail_var_path_changed = 0;
10574         popstackmark(&smark);
10575 }
10576
10577 static void FAST_FUNC
10578 changemail(const char *val UNUSED_PARAM)
10579 {
10580         mail_var_path_changed = 1;
10581 }
10582
10583 #endif /* ASH_MAIL */
10584
10585
10586 /* ============ ??? */
10587
10588 /*
10589  * Set the shell parameters.
10590  */
10591 static void
10592 setparam(char **argv)
10593 {
10594         char **newparam;
10595         char **ap;
10596         int nparam;
10597
10598         for (nparam = 0; argv[nparam]; nparam++)
10599                 continue;
10600         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10601         while (*argv) {
10602                 *ap++ = ckstrdup(*argv++);
10603         }
10604         *ap = NULL;
10605         freeparam(&shellparam);
10606         shellparam.malloced = 1;
10607         shellparam.nparam = nparam;
10608         shellparam.p = newparam;
10609 #if ENABLE_ASH_GETOPTS
10610         shellparam.optind = 1;
10611         shellparam.optoff = -1;
10612 #endif
10613 }
10614
10615 /*
10616  * Process shell options.  The global variable argptr contains a pointer
10617  * to the argument list; we advance it past the options.
10618  *
10619  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10620  * For a non-interactive shell, an error condition encountered
10621  * by a special built-in ... shall cause the shell to write a diagnostic message
10622  * to standard error and exit as shown in the following table:
10623  * Error                                           Special Built-In
10624  * ...
10625  * Utility syntax error (option or operand error)  Shall exit
10626  * ...
10627  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10628  * we see that bash does not do that (set "finishes" with error code 1 instead,
10629  * and shell continues), and people rely on this behavior!
10630  * Testcase:
10631  * set -o barfoo 2>/dev/null
10632  * echo $?
10633  *
10634  * Oh well. Let's mimic that.
10635  */
10636 static int
10637 plus_minus_o(char *name, int val)
10638 {
10639         int i;
10640
10641         if (name) {
10642                 for (i = 0; i < NOPTS; i++) {
10643                         if (strcmp(name, optnames(i)) == 0) {
10644                                 optlist[i] = val;
10645                                 return 0;
10646                         }
10647                 }
10648                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10649                 return 1;
10650         }
10651         for (i = 0; i < NOPTS; i++) {
10652                 if (val) {
10653                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10654                 } else {
10655                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10656                 }
10657         }
10658         return 0;
10659 }
10660 static void
10661 setoption(int flag, int val)
10662 {
10663         int i;
10664
10665         for (i = 0; i < NOPTS; i++) {
10666                 if (optletters(i) == flag) {
10667                         optlist[i] = val;
10668                         return;
10669                 }
10670         }
10671         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10672         /* NOTREACHED */
10673 }
10674 static int
10675 options(int cmdline)
10676 {
10677         char *p;
10678         int val;
10679         int c;
10680
10681         if (cmdline)
10682                 minusc = NULL;
10683         while ((p = *argptr) != NULL) {
10684                 c = *p++;
10685                 if (c != '-' && c != '+')
10686                         break;
10687                 argptr++;
10688                 val = 0; /* val = 0 if c == '+' */
10689                 if (c == '-') {
10690                         val = 1;
10691                         if (p[0] == '\0' || LONE_DASH(p)) {
10692                                 if (!cmdline) {
10693                                         /* "-" means turn off -x and -v */
10694                                         if (p[0] == '\0')
10695                                                 xflag = vflag = 0;
10696                                         /* "--" means reset params */
10697                                         else if (*argptr == NULL)
10698                                                 setparam(argptr);
10699                                 }
10700                                 break;    /* "-" or "--" terminates options */
10701                         }
10702                 }
10703                 /* first char was + or - */
10704                 while ((c = *p++) != '\0') {
10705                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10706                         if (c == 'c' && cmdline) {
10707                                 minusc = p;     /* command is after shell args */
10708                         } else if (c == 'o') {
10709                                 if (plus_minus_o(*argptr, val)) {
10710                                         /* it already printed err message */
10711                                         return 1; /* error */
10712                                 }
10713                                 if (*argptr)
10714                                         argptr++;
10715                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10716                                 isloginsh = 1;
10717                         /* bash does not accept +-login, we also won't */
10718                         } else if (cmdline && val && (c == '-')) { /* long options */
10719                                 if (strcmp(p, "login") == 0)
10720                                         isloginsh = 1;
10721                                 break;
10722                         } else {
10723                                 setoption(c, val);
10724                         }
10725                 }
10726         }
10727         return 0;
10728 }
10729
10730 /*
10731  * The shift builtin command.
10732  */
10733 static int FAST_FUNC
10734 shiftcmd(int argc UNUSED_PARAM, char **argv)
10735 {
10736         int n;
10737         char **ap1, **ap2;
10738
10739         n = 1;
10740         if (argv[1])
10741                 n = number(argv[1]);
10742         if (n > shellparam.nparam)
10743                 n = 0; /* bash compat, was = shellparam.nparam; */
10744         INT_OFF;
10745         shellparam.nparam -= n;
10746         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10747                 if (shellparam.malloced)
10748                         free(*ap1);
10749         }
10750         ap2 = shellparam.p;
10751         while ((*ap2++ = *ap1++) != NULL)
10752                 continue;
10753 #if ENABLE_ASH_GETOPTS
10754         shellparam.optind = 1;
10755         shellparam.optoff = -1;
10756 #endif
10757         INT_ON;
10758         return 0;
10759 }
10760
10761 /*
10762  * POSIX requires that 'set' (but not export or readonly) output the
10763  * variables in lexicographic order - by the locale's collating order (sigh).
10764  * Maybe we could keep them in an ordered balanced binary tree
10765  * instead of hashed lists.
10766  * For now just roll 'em through qsort for printing...
10767  */
10768 static int
10769 showvars(const char *sep_prefix, int on, int off)
10770 {
10771         const char *sep;
10772         char **ep, **epend;
10773
10774         ep = listvars(on, off, &epend);
10775         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10776
10777         sep = *sep_prefix ? " " : sep_prefix;
10778
10779         for (; ep < epend; ep++) {
10780                 const char *p;
10781                 const char *q;
10782
10783                 p = strchrnul(*ep, '=');
10784                 q = nullstr;
10785                 if (*p)
10786                         q = single_quote(++p);
10787                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10788         }
10789         return 0;
10790 }
10791
10792 /*
10793  * The set command builtin.
10794  */
10795 static int FAST_FUNC
10796 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10797 {
10798         int retval;
10799
10800         if (!argv[1])
10801                 return showvars(nullstr, 0, VUNSET);
10802
10803         INT_OFF;
10804         retval = options(/*cmdline:*/ 0);
10805         if (retval == 0) { /* if no parse error... */
10806                 optschanged();
10807                 if (*argptr != NULL) {
10808                         setparam(argptr);
10809                 }
10810         }
10811         INT_ON;
10812         return retval;
10813 }
10814
10815 #if ENABLE_ASH_RANDOM_SUPPORT
10816 static void FAST_FUNC
10817 change_random(const char *value)
10818 {
10819         uint32_t t;
10820
10821         if (value == NULL) {
10822                 /* "get", generate */
10823                 t = next_random(&random_gen);
10824                 /* set without recursion */
10825                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10826                 vrandom.flags &= ~VNOFUNC;
10827         } else {
10828                 /* set/reset */
10829                 t = strtoul(value, NULL, 10);
10830                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10831         }
10832 }
10833 #endif
10834
10835 #if ENABLE_ASH_GETOPTS
10836 static int
10837 getopts(char *optstr, char *optvar, char **optfirst)
10838 {
10839         char *p, *q;
10840         char c = '?';
10841         int done = 0;
10842         char sbuf[2];
10843         char **optnext;
10844         int ind = shellparam.optind;
10845         int off = shellparam.optoff;
10846
10847         sbuf[1] = '\0';
10848
10849         shellparam.optind = -1;
10850         optnext = optfirst + ind - 1;
10851
10852         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10853                 p = NULL;
10854         else
10855                 p = optnext[-1] + off;
10856         if (p == NULL || *p == '\0') {
10857                 /* Current word is done, advance */
10858                 p = *optnext;
10859                 if (p == NULL || *p != '-' || *++p == '\0') {
10860  atend:
10861                         p = NULL;
10862                         done = 1;
10863                         goto out;
10864                 }
10865                 optnext++;
10866                 if (LONE_DASH(p))        /* check for "--" */
10867                         goto atend;
10868         }
10869
10870         c = *p++;
10871         for (q = optstr; *q != c;) {
10872                 if (*q == '\0') {
10873                         if (optstr[0] == ':') {
10874                                 sbuf[0] = c;
10875                                 /*sbuf[1] = '\0'; - already is */
10876                                 setvar0("OPTARG", sbuf);
10877                         } else {
10878                                 fprintf(stderr, "Illegal option -%c\n", c);
10879                                 unsetvar("OPTARG");
10880                         }
10881                         c = '?';
10882                         goto out;
10883                 }
10884                 if (*++q == ':')
10885                         q++;
10886         }
10887
10888         if (*++q == ':') {
10889                 if (*p == '\0' && (p = *optnext) == NULL) {
10890                         if (optstr[0] == ':') {
10891                                 sbuf[0] = c;
10892                                 /*sbuf[1] = '\0'; - already is */
10893                                 setvar0("OPTARG", sbuf);
10894                                 c = ':';
10895                         } else {
10896                                 fprintf(stderr, "No arg for -%c option\n", c);
10897                                 unsetvar("OPTARG");
10898                                 c = '?';
10899                         }
10900                         goto out;
10901                 }
10902
10903                 if (p == *optnext)
10904                         optnext++;
10905                 setvar0("OPTARG", p);
10906                 p = NULL;
10907         } else
10908                 setvar0("OPTARG", nullstr);
10909  out:
10910         ind = optnext - optfirst + 1;
10911         setvar("OPTIND", itoa(ind), VNOFUNC);
10912         sbuf[0] = c;
10913         /*sbuf[1] = '\0'; - already is */
10914         setvar0(optvar, sbuf);
10915
10916         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10917         shellparam.optind = ind;
10918
10919         return done;
10920 }
10921
10922 /*
10923  * The getopts builtin.  Shellparam.optnext points to the next argument
10924  * to be processed.  Shellparam.optptr points to the next character to
10925  * be processed in the current argument.  If shellparam.optnext is NULL,
10926  * then it's the first time getopts has been called.
10927  */
10928 static int FAST_FUNC
10929 getoptscmd(int argc, char **argv)
10930 {
10931         char **optbase;
10932
10933         if (argc < 3)
10934                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10935         if (argc == 3) {
10936                 optbase = shellparam.p;
10937                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10938                         shellparam.optind = 1;
10939                         shellparam.optoff = -1;
10940                 }
10941         } else {
10942                 optbase = &argv[3];
10943                 if ((unsigned)shellparam.optind > argc - 2) {
10944                         shellparam.optind = 1;
10945                         shellparam.optoff = -1;
10946                 }
10947         }
10948
10949         return getopts(argv[1], argv[2], optbase);
10950 }
10951 #endif /* ASH_GETOPTS */
10952
10953
10954 /* ============ Shell parser */
10955
10956 struct heredoc {
10957         struct heredoc *next;   /* next here document in list */
10958         union node *here;       /* redirection node */
10959         char *eofmark;          /* string indicating end of input */
10960         smallint striptabs;     /* if set, strip leading tabs */
10961 };
10962
10963 static smallint tokpushback;           /* last token pushed back */
10964 static smallint quoteflag;             /* set if (part of) last token was quoted */
10965 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10966 static struct heredoc *heredoclist;    /* list of here documents to read */
10967 static char *wordtext;                 /* text of last word returned by readtoken */
10968 static struct nodelist *backquotelist;
10969 static union node *redirnode;
10970 static struct heredoc *heredoc;
10971
10972 static const char *
10973 tokname(char *buf, int tok)
10974 {
10975         if (tok < TSEMI)
10976                 return tokname_array[tok];
10977         sprintf(buf, "\"%s\"", tokname_array[tok]);
10978         return buf;
10979 }
10980
10981 /* raise_error_unexpected_syntax:
10982  * Called when an unexpected token is read during the parse.  The argument
10983  * is the token that is expected, or -1 if more than one type of token can
10984  * occur at this point.
10985  */
10986 static void raise_error_unexpected_syntax(int) NORETURN;
10987 static void
10988 raise_error_unexpected_syntax(int token)
10989 {
10990         char msg[64];
10991         char buf[16];
10992         int l;
10993
10994         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10995         if (token >= 0)
10996                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10997         raise_error_syntax(msg);
10998         /* NOTREACHED */
10999 }
11000
11001 #define EOFMARKLEN 79
11002
11003 /* parsing is heavily cross-recursive, need these forward decls */
11004 static union node *andor(void);
11005 static union node *pipeline(void);
11006 static union node *parse_command(void);
11007 static void parseheredoc(void);
11008 static int peektoken(void);
11009 static int readtoken(void);
11010
11011 static union node *
11012 list(int nlflag)
11013 {
11014         union node *n1, *n2, *n3;
11015         int tok;
11016
11017         n1 = NULL;
11018         for (;;) {
11019                 switch (peektoken()) {
11020                 case TNL:
11021                         if (!(nlflag & 1))
11022                                 break;
11023                         parseheredoc();
11024                         return n1;
11025
11026                 case TEOF:
11027                         if (!n1 && (nlflag & 1))
11028                                 n1 = NODE_EOF;
11029                         parseheredoc();
11030                         return n1;
11031                 }
11032
11033                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11034                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11035                         return n1;
11036                 nlflag |= 2;
11037
11038                 n2 = andor();
11039                 tok = readtoken();
11040                 if (tok == TBACKGND) {
11041                         if (n2->type == NPIPE) {
11042                                 n2->npipe.pipe_backgnd = 1;
11043                         } else {
11044                                 if (n2->type != NREDIR) {
11045                                         n3 = stzalloc(sizeof(struct nredir));
11046                                         n3->nredir.n = n2;
11047                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11048                                         n2 = n3;
11049                                 }
11050                                 n2->type = NBACKGND;
11051                         }
11052                 }
11053                 if (n1 == NULL) {
11054                         n1 = n2;
11055                 } else {
11056                         n3 = stzalloc(sizeof(struct nbinary));
11057                         n3->type = NSEMI;
11058                         n3->nbinary.ch1 = n1;
11059                         n3->nbinary.ch2 = n2;
11060                         n1 = n3;
11061                 }
11062                 switch (tok) {
11063                 case TNL:
11064                 case TEOF:
11065                         tokpushback = 1;
11066                         /* fall through */
11067                 case TBACKGND:
11068                 case TSEMI:
11069                         break;
11070                 default:
11071                         if ((nlflag & 1))
11072                                 raise_error_unexpected_syntax(-1);
11073                         tokpushback = 1;
11074                         return n1;
11075                 }
11076         }
11077 }
11078
11079 static union node *
11080 andor(void)
11081 {
11082         union node *n1, *n2, *n3;
11083         int t;
11084
11085         n1 = pipeline();
11086         for (;;) {
11087                 t = readtoken();
11088                 if (t == TAND) {
11089                         t = NAND;
11090                 } else if (t == TOR) {
11091                         t = NOR;
11092                 } else {
11093                         tokpushback = 1;
11094                         return n1;
11095                 }
11096                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11097                 n2 = pipeline();
11098                 n3 = stzalloc(sizeof(struct nbinary));
11099                 n3->type = t;
11100                 n3->nbinary.ch1 = n1;
11101                 n3->nbinary.ch2 = n2;
11102                 n1 = n3;
11103         }
11104 }
11105
11106 static union node *
11107 pipeline(void)
11108 {
11109         union node *n1, *n2, *pipenode;
11110         struct nodelist *lp, *prev;
11111         int negate;
11112
11113         negate = 0;
11114         TRACE(("pipeline: entered\n"));
11115         if (readtoken() == TNOT) {
11116                 negate = !negate;
11117                 checkkwd = CHKKWD | CHKALIAS;
11118         } else
11119                 tokpushback = 1;
11120         n1 = parse_command();
11121         if (readtoken() == TPIPE) {
11122                 pipenode = stzalloc(sizeof(struct npipe));
11123                 pipenode->type = NPIPE;
11124                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11125                 lp = stzalloc(sizeof(struct nodelist));
11126                 pipenode->npipe.cmdlist = lp;
11127                 lp->n = n1;
11128                 do {
11129                         prev = lp;
11130                         lp = stzalloc(sizeof(struct nodelist));
11131                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11132                         lp->n = parse_command();
11133                         prev->next = lp;
11134                 } while (readtoken() == TPIPE);
11135                 lp->next = NULL;
11136                 n1 = pipenode;
11137         }
11138         tokpushback = 1;
11139         if (negate) {
11140                 n2 = stzalloc(sizeof(struct nnot));
11141                 n2->type = NNOT;
11142                 n2->nnot.com = n1;
11143                 return n2;
11144         }
11145         return n1;
11146 }
11147
11148 static union node *
11149 makename(void)
11150 {
11151         union node *n;
11152
11153         n = stzalloc(sizeof(struct narg));
11154         n->type = NARG;
11155         /*n->narg.next = NULL; - stzalloc did it */
11156         n->narg.text = wordtext;
11157         n->narg.backquote = backquotelist;
11158         return n;
11159 }
11160
11161 static void
11162 fixredir(union node *n, const char *text, int err)
11163 {
11164         int fd;
11165
11166         TRACE(("Fix redir %s %d\n", text, err));
11167         if (!err)
11168                 n->ndup.vname = NULL;
11169
11170         fd = bb_strtou(text, NULL, 10);
11171         if (!errno && fd >= 0)
11172                 n->ndup.dupfd = fd;
11173         else if (LONE_DASH(text))
11174                 n->ndup.dupfd = -1;
11175         else {
11176                 if (err)
11177                         raise_error_syntax("bad fd number");
11178                 n->ndup.vname = makename();
11179         }
11180 }
11181
11182 /*
11183  * Returns true if the text contains nothing to expand (no dollar signs
11184  * or backquotes).
11185  */
11186 static int
11187 noexpand(const char *text)
11188 {
11189         unsigned char c;
11190
11191         while ((c = *text++) != '\0') {
11192                 if (c == CTLQUOTEMARK)
11193                         continue;
11194                 if (c == CTLESC)
11195                         text++;
11196                 else if (SIT(c, BASESYNTAX) == CCTL)
11197                         return 0;
11198         }
11199         return 1;
11200 }
11201
11202 static void
11203 parsefname(void)
11204 {
11205         union node *n = redirnode;
11206
11207         if (readtoken() != TWORD)
11208                 raise_error_unexpected_syntax(-1);
11209         if (n->type == NHERE) {
11210                 struct heredoc *here = heredoc;
11211                 struct heredoc *p;
11212                 int i;
11213
11214                 if (quoteflag == 0)
11215                         n->type = NXHERE;
11216                 TRACE(("Here document %d\n", n->type));
11217                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11218                         raise_error_syntax("illegal eof marker for << redirection");
11219                 rmescapes(wordtext, 0);
11220                 here->eofmark = wordtext;
11221                 here->next = NULL;
11222                 if (heredoclist == NULL)
11223                         heredoclist = here;
11224                 else {
11225                         for (p = heredoclist; p->next; p = p->next)
11226                                 continue;
11227                         p->next = here;
11228                 }
11229         } else if (n->type == NTOFD || n->type == NFROMFD) {
11230                 fixredir(n, wordtext, 0);
11231         } else {
11232                 n->nfile.fname = makename();
11233         }
11234 }
11235
11236 static union node *
11237 simplecmd(void)
11238 {
11239         union node *args, **app;
11240         union node *n = NULL;
11241         union node *vars, **vpp;
11242         union node **rpp, *redir;
11243         int savecheckkwd;
11244 #if BASH_TEST2
11245         smallint double_brackets_flag = 0;
11246 #endif
11247         IF_BASH_FUNCTION(smallint function_flag = 0;)
11248
11249         args = NULL;
11250         app = &args;
11251         vars = NULL;
11252         vpp = &vars;
11253         redir = NULL;
11254         rpp = &redir;
11255
11256         savecheckkwd = CHKALIAS;
11257         for (;;) {
11258                 int t;
11259                 checkkwd = savecheckkwd;
11260                 t = readtoken();
11261                 switch (t) {
11262 #if BASH_FUNCTION
11263                 case TFUNCTION:
11264                         if (peektoken() != TWORD)
11265                                 raise_error_unexpected_syntax(TWORD);
11266                         function_flag = 1;
11267                         break;
11268 #endif
11269 #if BASH_TEST2
11270                 case TAND: /* "&&" */
11271                 case TOR: /* "||" */
11272                         if (!double_brackets_flag) {
11273                                 tokpushback = 1;
11274                                 goto out;
11275                         }
11276                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11277 #endif
11278                 case TWORD:
11279                         n = stzalloc(sizeof(struct narg));
11280                         n->type = NARG;
11281                         /*n->narg.next = NULL; - stzalloc did it */
11282                         n->narg.text = wordtext;
11283 #if BASH_TEST2
11284                         if (strcmp("[[", wordtext) == 0)
11285                                 double_brackets_flag = 1;
11286                         else if (strcmp("]]", wordtext) == 0)
11287                                 double_brackets_flag = 0;
11288 #endif
11289                         n->narg.backquote = backquotelist;
11290                         if (savecheckkwd && isassignment(wordtext)) {
11291                                 *vpp = n;
11292                                 vpp = &n->narg.next;
11293                         } else {
11294                                 *app = n;
11295                                 app = &n->narg.next;
11296                                 savecheckkwd = 0;
11297                         }
11298 #if BASH_FUNCTION
11299                         if (function_flag) {
11300                                 checkkwd = CHKNL | CHKKWD;
11301                                 switch (peektoken()) {
11302                                 case TBEGIN:
11303                                 case TIF:
11304                                 case TCASE:
11305                                 case TUNTIL:
11306                                 case TWHILE:
11307                                 case TFOR:
11308                                         goto do_func;
11309                                 case TLP:
11310                                         function_flag = 0;
11311                                         break;
11312                                 case TWORD:
11313                                         if (strcmp("[[", wordtext) == 0)
11314                                                 goto do_func;
11315                                         /* fall through */
11316                                 default:
11317                                         raise_error_unexpected_syntax(-1);
11318                                 }
11319                         }
11320 #endif
11321                         break;
11322                 case TREDIR:
11323                         *rpp = n = redirnode;
11324                         rpp = &n->nfile.next;
11325                         parsefname();   /* read name of redirection file */
11326                         break;
11327                 case TLP:
11328  IF_BASH_FUNCTION(do_func:)
11329                         if (args && app == &args->narg.next
11330                          && !vars && !redir
11331                         ) {
11332                                 struct builtincmd *bcmd;
11333                                 const char *name;
11334
11335                                 /* We have a function */
11336                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11337                                         raise_error_unexpected_syntax(TRP);
11338                                 name = n->narg.text;
11339                                 if (!goodname(name)
11340                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11341                                 ) {
11342                                         raise_error_syntax("bad function name");
11343                                 }
11344                                 n->type = NDEFUN;
11345                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11346                                 n->narg.next = parse_command();
11347                                 return n;
11348                         }
11349                         IF_BASH_FUNCTION(function_flag = 0;)
11350                         /* fall through */
11351                 default:
11352                         tokpushback = 1;
11353                         goto out;
11354                 }
11355         }
11356  out:
11357         *app = NULL;
11358         *vpp = NULL;
11359         *rpp = NULL;
11360         n = stzalloc(sizeof(struct ncmd));
11361         n->type = NCMD;
11362         n->ncmd.args = args;
11363         n->ncmd.assign = vars;
11364         n->ncmd.redirect = redir;
11365         return n;
11366 }
11367
11368 static union node *
11369 parse_command(void)
11370 {
11371         union node *n1, *n2;
11372         union node *ap, **app;
11373         union node *cp, **cpp;
11374         union node *redir, **rpp;
11375         union node **rpp2;
11376         int t;
11377
11378         redir = NULL;
11379         rpp2 = &redir;
11380
11381         switch (readtoken()) {
11382         default:
11383                 raise_error_unexpected_syntax(-1);
11384                 /* NOTREACHED */
11385         case TIF:
11386                 n1 = stzalloc(sizeof(struct nif));
11387                 n1->type = NIF;
11388                 n1->nif.test = list(0);
11389                 if (readtoken() != TTHEN)
11390                         raise_error_unexpected_syntax(TTHEN);
11391                 n1->nif.ifpart = list(0);
11392                 n2 = n1;
11393                 while (readtoken() == TELIF) {
11394                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11395                         n2 = n2->nif.elsepart;
11396                         n2->type = NIF;
11397                         n2->nif.test = list(0);
11398                         if (readtoken() != TTHEN)
11399                                 raise_error_unexpected_syntax(TTHEN);
11400                         n2->nif.ifpart = list(0);
11401                 }
11402                 if (lasttoken == TELSE)
11403                         n2->nif.elsepart = list(0);
11404                 else {
11405                         n2->nif.elsepart = NULL;
11406                         tokpushback = 1;
11407                 }
11408                 t = TFI;
11409                 break;
11410         case TWHILE:
11411         case TUNTIL: {
11412                 int got;
11413                 n1 = stzalloc(sizeof(struct nbinary));
11414                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11415                 n1->nbinary.ch1 = list(0);
11416                 got = readtoken();
11417                 if (got != TDO) {
11418                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11419                                         got == TWORD ? wordtext : ""));
11420                         raise_error_unexpected_syntax(TDO);
11421                 }
11422                 n1->nbinary.ch2 = list(0);
11423                 t = TDONE;
11424                 break;
11425         }
11426         case TFOR:
11427                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11428                         raise_error_syntax("bad for loop variable");
11429                 n1 = stzalloc(sizeof(struct nfor));
11430                 n1->type = NFOR;
11431                 n1->nfor.var = wordtext;
11432                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11433                 if (readtoken() == TIN) {
11434                         app = &ap;
11435                         while (readtoken() == TWORD) {
11436                                 n2 = stzalloc(sizeof(struct narg));
11437                                 n2->type = NARG;
11438                                 /*n2->narg.next = NULL; - stzalloc did it */
11439                                 n2->narg.text = wordtext;
11440                                 n2->narg.backquote = backquotelist;
11441                                 *app = n2;
11442                                 app = &n2->narg.next;
11443                         }
11444                         *app = NULL;
11445                         n1->nfor.args = ap;
11446                         if (lasttoken != TNL && lasttoken != TSEMI)
11447                                 raise_error_unexpected_syntax(-1);
11448                 } else {
11449                         n2 = stzalloc(sizeof(struct narg));
11450                         n2->type = NARG;
11451                         /*n2->narg.next = NULL; - stzalloc did it */
11452                         n2->narg.text = (char *)dolatstr;
11453                         /*n2->narg.backquote = NULL;*/
11454                         n1->nfor.args = n2;
11455                         /*
11456                          * Newline or semicolon here is optional (but note
11457                          * that the original Bourne shell only allowed NL).
11458                          */
11459                         if (lasttoken != TSEMI)
11460                                 tokpushback = 1;
11461                 }
11462                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11463                 if (readtoken() != TDO)
11464                         raise_error_unexpected_syntax(TDO);
11465                 n1->nfor.body = list(0);
11466                 t = TDONE;
11467                 break;
11468         case TCASE:
11469                 n1 = stzalloc(sizeof(struct ncase));
11470                 n1->type = NCASE;
11471                 if (readtoken() != TWORD)
11472                         raise_error_unexpected_syntax(TWORD);
11473                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11474                 n2->type = NARG;
11475                 /*n2->narg.next = NULL; - stzalloc did it */
11476                 n2->narg.text = wordtext;
11477                 n2->narg.backquote = backquotelist;
11478                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11479                 if (readtoken() != TIN)
11480                         raise_error_unexpected_syntax(TIN);
11481                 cpp = &n1->ncase.cases;
11482  next_case:
11483                 checkkwd = CHKNL | CHKKWD;
11484                 t = readtoken();
11485                 while (t != TESAC) {
11486                         if (lasttoken == TLP)
11487                                 readtoken();
11488                         *cpp = cp = stzalloc(sizeof(struct nclist));
11489                         cp->type = NCLIST;
11490                         app = &cp->nclist.pattern;
11491                         for (;;) {
11492                                 *app = ap = stzalloc(sizeof(struct narg));
11493                                 ap->type = NARG;
11494                                 /*ap->narg.next = NULL; - stzalloc did it */
11495                                 ap->narg.text = wordtext;
11496                                 ap->narg.backquote = backquotelist;
11497                                 if (readtoken() != TPIPE)
11498                                         break;
11499                                 app = &ap->narg.next;
11500                                 readtoken();
11501                         }
11502                         //ap->narg.next = NULL;
11503                         if (lasttoken != TRP)
11504                                 raise_error_unexpected_syntax(TRP);
11505                         cp->nclist.body = list(2);
11506
11507                         cpp = &cp->nclist.next;
11508
11509                         checkkwd = CHKNL | CHKKWD;
11510                         t = readtoken();
11511                         if (t != TESAC) {
11512                                 if (t != TENDCASE)
11513                                         raise_error_unexpected_syntax(TENDCASE);
11514                                 goto next_case;
11515                         }
11516                 }
11517                 *cpp = NULL;
11518                 goto redir;
11519         case TLP:
11520                 n1 = stzalloc(sizeof(struct nredir));
11521                 n1->type = NSUBSHELL;
11522                 n1->nredir.n = list(0);
11523                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11524                 t = TRP;
11525                 break;
11526         case TBEGIN:
11527                 n1 = list(0);
11528                 t = TEND;
11529                 break;
11530         IF_BASH_FUNCTION(case TFUNCTION:)
11531         case TWORD:
11532         case TREDIR:
11533                 tokpushback = 1;
11534                 return simplecmd();
11535         }
11536
11537         if (readtoken() != t)
11538                 raise_error_unexpected_syntax(t);
11539
11540  redir:
11541         /* Now check for redirection which may follow command */
11542         checkkwd = CHKKWD | CHKALIAS;
11543         rpp = rpp2;
11544         while (readtoken() == TREDIR) {
11545                 *rpp = n2 = redirnode;
11546                 rpp = &n2->nfile.next;
11547                 parsefname();
11548         }
11549         tokpushback = 1;
11550         *rpp = NULL;
11551         if (redir) {
11552                 if (n1->type != NSUBSHELL) {
11553                         n2 = stzalloc(sizeof(struct nredir));
11554                         n2->type = NREDIR;
11555                         n2->nredir.n = n1;
11556                         n1 = n2;
11557                 }
11558                 n1->nredir.redirect = redir;
11559         }
11560         return n1;
11561 }
11562
11563 #if BASH_DOLLAR_SQUOTE
11564 static int
11565 decode_dollar_squote(void)
11566 {
11567         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11568         int c, cnt;
11569         char *p;
11570         char buf[4];
11571
11572         c = pgetc();
11573         p = strchr(C_escapes, c);
11574         if (p) {
11575                 buf[0] = c;
11576                 p = buf;
11577                 cnt = 3;
11578                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11579                         do {
11580                                 c = pgetc();
11581                                 *++p = c;
11582                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11583                         pungetc();
11584                 } else if (c == 'x') { /* \xHH */
11585                         do {
11586                                 c = pgetc();
11587                                 *++p = c;
11588                         } while (isxdigit(c) && --cnt);
11589                         pungetc();
11590                         if (cnt == 3) { /* \x but next char is "bad" */
11591                                 c = 'x';
11592                                 goto unrecognized;
11593                         }
11594                 } else { /* simple seq like \\ or \t */
11595                         p++;
11596                 }
11597                 *p = '\0';
11598                 p = buf;
11599                 c = bb_process_escape_sequence((void*)&p);
11600         } else { /* unrecognized "\z": print both chars unless ' or " */
11601                 if (c != '\'' && c != '"') {
11602  unrecognized:
11603                         c |= 0x100; /* "please encode \, then me" */
11604                 }
11605         }
11606         return c;
11607 }
11608 #endif
11609
11610 /*
11611  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11612  * is not NULL, read a here document.  In the latter case, eofmark is the
11613  * word which marks the end of the document and striptabs is true if
11614  * leading tabs should be stripped from the document.  The argument c
11615  * is the first character of the input token or document.
11616  *
11617  * Because C does not have internal subroutines, I have simulated them
11618  * using goto's to implement the subroutine linkage.  The following macros
11619  * will run code that appears at the end of readtoken1.
11620  */
11621 #define CHECKEND()      {goto checkend; checkend_return:;}
11622 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11623 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11624 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11625 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11626 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11627 static int
11628 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11629 {
11630         /* NB: syntax parameter fits into smallint */
11631         /* c parameter is an unsigned char or PEOF or PEOA */
11632         char *out;
11633         size_t len;
11634         char line[EOFMARKLEN + 1];
11635         struct nodelist *bqlist;
11636         smallint quotef;
11637         smallint dblquote;
11638         smallint oldstyle;
11639         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11640         smallint pssyntax;   /* we are expanding a prompt string */
11641         int varnest;         /* levels of variables expansion */
11642         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11643         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11644         int dqvarnest;       /* levels of variables expansion within double quotes */
11645
11646         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11647
11648         startlinno = g_parsefile->linno;
11649         bqlist = NULL;
11650         quotef = 0;
11651         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11652         pssyntax = (syntax == PSSYNTAX);
11653         if (pssyntax)
11654                 syntax = DQSYNTAX;
11655         dblquote = (syntax == DQSYNTAX);
11656         varnest = 0;
11657         IF_FEATURE_SH_MATH(arinest = 0;)
11658         IF_FEATURE_SH_MATH(parenlevel = 0;)
11659         dqvarnest = 0;
11660
11661         STARTSTACKSTR(out);
11662  loop:
11663         /* For each line, until end of word */
11664         CHECKEND();     /* set c to PEOF if at end of here document */
11665         for (;;) {      /* until end of line or end of word */
11666                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11667                 switch (SIT(c, syntax)) {
11668                 case CNL:       /* '\n' */
11669                         if (syntax == BASESYNTAX)
11670                                 goto endword;   /* exit outer loop */
11671                         USTPUTC(c, out);
11672                         nlprompt();
11673                         c = pgetc();
11674                         goto loop;              /* continue outer loop */
11675                 case CWORD:
11676                         USTPUTC(c, out);
11677                         break;
11678                 case CCTL:
11679 #if BASH_DOLLAR_SQUOTE
11680                         if (c == '\\' && bash_dollar_squote) {
11681                                 c = decode_dollar_squote();
11682                                 if (c == '\0') {
11683                                         /* skip $'\000', $'\x00' (like bash) */
11684                                         break;
11685                                 }
11686                                 if (c & 0x100) {
11687                                         /* Unknown escape. Encode as '\z' */
11688                                         c = (unsigned char)c;
11689                                         if (eofmark == NULL || dblquote)
11690                                                 USTPUTC(CTLESC, out);
11691                                         USTPUTC('\\', out);
11692                                 }
11693                         }
11694 #endif
11695                         if (eofmark == NULL || dblquote)
11696                                 USTPUTC(CTLESC, out);
11697                         USTPUTC(c, out);
11698                         break;
11699                 case CBACK:     /* backslash */
11700                         c = pgetc_without_PEOA();
11701                         if (c == PEOF) {
11702                                 USTPUTC(CTLESC, out);
11703                                 USTPUTC('\\', out);
11704                                 pungetc();
11705                         } else if (c == '\n') {
11706                                 nlprompt();
11707                         } else {
11708                                 if (c == '$' && pssyntax) {
11709                                         USTPUTC(CTLESC, out);
11710                                         USTPUTC('\\', out);
11711                                 }
11712                                 /* Backslash is retained if we are in "str" and next char isn't special */
11713                                 if (dblquote
11714                                  && c != '\\'
11715                                  && c != '`'
11716                                  && c != '$'
11717                                  && (c != '"' || eofmark != NULL)
11718                                 ) {
11719                                         USTPUTC('\\', out);
11720                                 }
11721                                 USTPUTC(CTLESC, out);
11722                                 USTPUTC(c, out);
11723                                 quotef = 1;
11724                         }
11725                         break;
11726                 case CSQUOTE:
11727                         syntax = SQSYNTAX;
11728  quotemark:
11729                         if (eofmark == NULL) {
11730                                 USTPUTC(CTLQUOTEMARK, out);
11731                         }
11732                         break;
11733                 case CDQUOTE:
11734                         syntax = DQSYNTAX;
11735                         dblquote = 1;
11736                         goto quotemark;
11737                 case CENDQUOTE:
11738                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11739                         if (eofmark != NULL && varnest == 0) {
11740                                 USTPUTC(c, out);
11741                         } else {
11742                                 if (dqvarnest == 0) {
11743                                         syntax = BASESYNTAX;
11744                                         dblquote = 0;
11745                                 }
11746                                 quotef = 1;
11747                                 goto quotemark;
11748                         }
11749                         break;
11750                 case CVAR:      /* '$' */
11751                         PARSESUB();             /* parse substitution */
11752                         break;
11753                 case CENDVAR:   /* '}' */
11754                         if (varnest > 0) {
11755                                 varnest--;
11756                                 if (dqvarnest > 0) {
11757                                         dqvarnest--;
11758                                 }
11759                                 c = CTLENDVAR;
11760                         }
11761                         USTPUTC(c, out);
11762                         break;
11763 #if ENABLE_FEATURE_SH_MATH
11764                 case CLP:       /* '(' in arithmetic */
11765                         parenlevel++;
11766                         USTPUTC(c, out);
11767                         break;
11768                 case CRP:       /* ')' in arithmetic */
11769                         if (parenlevel > 0) {
11770                                 parenlevel--;
11771                         } else {
11772                                 if (pgetc_eatbnl() == ')') {
11773                                         c = CTLENDARI;
11774                                         if (--arinest == 0) {
11775                                                 syntax = prevsyntax;
11776                                         }
11777                                 } else {
11778                                         /*
11779                                          * unbalanced parens
11780                                          * (don't 2nd guess - no error)
11781                                          */
11782                                         pungetc();
11783                                 }
11784                         }
11785                         USTPUTC(c, out);
11786                         break;
11787 #endif
11788                 case CBQUOTE:   /* '`' */
11789                         PARSEBACKQOLD();
11790                         break;
11791                 case CENDFILE:
11792                         goto endword;           /* exit outer loop */
11793                 case CIGN:
11794                         break;
11795                 default:
11796                         if (varnest == 0) {
11797 #if BASH_REDIR_OUTPUT
11798                                 if (c == '&') {
11799 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11800                                         if (pgetc() == '>')
11801                                                 c = 0x100 + '>'; /* flag &> */
11802                                         pungetc();
11803                                 }
11804 #endif
11805                                 goto endword;   /* exit outer loop */
11806                         }
11807                         IF_ASH_ALIAS(if (c != PEOA))
11808                                 USTPUTC(c, out);
11809                 }
11810                 c = pgetc();
11811         } /* for (;;) */
11812  endword:
11813
11814 #if ENABLE_FEATURE_SH_MATH
11815         if (syntax == ARISYNTAX)
11816                 raise_error_syntax("missing '))'");
11817 #endif
11818         if (syntax != BASESYNTAX && eofmark == NULL)
11819                 raise_error_syntax("unterminated quoted string");
11820         if (varnest != 0) {
11821                 startlinno = g_parsefile->linno;
11822                 /* { */
11823                 raise_error_syntax("missing '}'");
11824         }
11825         USTPUTC('\0', out);
11826         len = out - (char *)stackblock();
11827         out = stackblock();
11828         if (eofmark == NULL) {
11829                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11830                  && quotef == 0
11831                 ) {
11832                         if (isdigit_str9(out)) {
11833                                 PARSEREDIR(); /* passed as params: out, c */
11834                                 lasttoken = TREDIR;
11835                                 return lasttoken;
11836                         }
11837                         /* else: non-number X seen, interpret it
11838                          * as "NNNX>file" = "NNNX >file" */
11839                 }
11840                 pungetc();
11841         }
11842         quoteflag = quotef;
11843         backquotelist = bqlist;
11844         grabstackblock(len);
11845         wordtext = out;
11846         lasttoken = TWORD;
11847         return lasttoken;
11848 /* end of readtoken routine */
11849
11850 /*
11851  * Check to see whether we are at the end of the here document.  When this
11852  * is called, c is set to the first character of the next input line.  If
11853  * we are at the end of the here document, this routine sets the c to PEOF.
11854  */
11855 checkend: {
11856         if (eofmark) {
11857 #if ENABLE_ASH_ALIAS
11858                 if (c == PEOA)
11859                         c = pgetc_without_PEOA();
11860 #endif
11861                 if (striptabs) {
11862                         while (c == '\t') {
11863                                 c = pgetc_without_PEOA();
11864                         }
11865                 }
11866                 if (c == *eofmark) {
11867                         if (pfgets(line, sizeof(line)) != NULL) {
11868                                 char *p, *q;
11869                                 int cc;
11870
11871                                 p = line;
11872                                 for (q = eofmark + 1;; p++, q++) {
11873                                         cc = *p;
11874                                         if (cc == '\n')
11875                                                 cc = 0;
11876                                         if (!*q || cc != *q)
11877                                                 break;
11878                                 }
11879                                 if (cc == *q) {
11880                                         c = PEOF;
11881                                         nlnoprompt();
11882                                 } else {
11883                                         pushstring(line, NULL);
11884                                 }
11885                         }
11886                 }
11887         }
11888         goto checkend_return;
11889 }
11890
11891 /*
11892  * Parse a redirection operator.  The variable "out" points to a string
11893  * specifying the fd to be redirected.  The variable "c" contains the
11894  * first character of the redirection operator.
11895  */
11896 parseredir: {
11897         /* out is already checked to be a valid number or "" */
11898         int fd = (*out == '\0' ? -1 : atoi(out));
11899         union node *np;
11900
11901         np = stzalloc(sizeof(struct nfile));
11902         if (c == '>') {
11903                 np->nfile.fd = 1;
11904                 c = pgetc();
11905                 if (c == '>')
11906                         np->type = NAPPEND;
11907                 else if (c == '|')
11908                         np->type = NCLOBBER;
11909                 else if (c == '&')
11910                         np->type = NTOFD;
11911                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11912                 else {
11913                         np->type = NTO;
11914                         pungetc();
11915                 }
11916         }
11917 #if BASH_REDIR_OUTPUT
11918         else if (c == 0x100 + '>') { /* this flags &> redirection */
11919                 np->nfile.fd = 1;
11920                 pgetc(); /* this is '>', no need to check */
11921                 np->type = NTO2;
11922         }
11923 #endif
11924         else { /* c == '<' */
11925                 /*np->nfile.fd = 0; - stzalloc did it */
11926                 c = pgetc();
11927                 switch (c) {
11928                 case '<':
11929                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11930                                 np = stzalloc(sizeof(struct nhere));
11931                                 /*np->nfile.fd = 0; - stzalloc did it */
11932                         }
11933                         np->type = NHERE;
11934                         heredoc = stzalloc(sizeof(struct heredoc));
11935                         heredoc->here = np;
11936                         c = pgetc();
11937                         if (c == '-') {
11938                                 heredoc->striptabs = 1;
11939                         } else {
11940                                 /*heredoc->striptabs = 0; - stzalloc did it */
11941                                 pungetc();
11942                         }
11943                         break;
11944
11945                 case '&':
11946                         np->type = NFROMFD;
11947                         break;
11948
11949                 case '>':
11950                         np->type = NFROMTO;
11951                         break;
11952
11953                 default:
11954                         np->type = NFROM;
11955                         pungetc();
11956                         break;
11957                 }
11958         }
11959         if (fd >= 0)
11960                 np->nfile.fd = fd;
11961         redirnode = np;
11962         goto parseredir_return;
11963 }
11964
11965 /*
11966  * Parse a substitution.  At this point, we have read the dollar sign
11967  * and nothing else.
11968  */
11969
11970 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11971  * (assuming ascii char codes, as the original implementation did) */
11972 #define is_special(c) \
11973         (((unsigned)(c) - 33 < 32) \
11974                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11975 parsesub: {
11976         unsigned char subtype;
11977         int typeloc;
11978
11979         c = pgetc_eatbnl();
11980         if (c > 255 /* PEOA or PEOF */
11981          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11982         ) {
11983 #if BASH_DOLLAR_SQUOTE
11984                 if (syntax != DQSYNTAX && c == '\'')
11985                         bash_dollar_squote = 1;
11986                 else
11987 #endif
11988                         USTPUTC('$', out);
11989                 pungetc();
11990         } else if (c == '(') {
11991                 /* $(command) or $((arith)) */
11992                 if (pgetc_eatbnl() == '(') {
11993 #if ENABLE_FEATURE_SH_MATH
11994                         PARSEARITH();
11995 #else
11996                         raise_error_syntax("support for $((arith)) is disabled");
11997 #endif
11998                 } else {
11999                         pungetc();
12000                         PARSEBACKQNEW();
12001                 }
12002         } else {
12003                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12004                 USTPUTC(CTLVAR, out);
12005                 typeloc = out - (char *)stackblock();
12006                 STADJUST(1, out);
12007                 subtype = VSNORMAL;
12008                 if (c == '{') {
12009                         c = pgetc_eatbnl();
12010                         subtype = 0;
12011                 }
12012  varname:
12013                 if (is_name(c)) {
12014                         /* $[{[#]]NAME[}] */
12015                         do {
12016                                 STPUTC(c, out);
12017                                 c = pgetc_eatbnl();
12018                         } while (is_in_name(c));
12019                 } else if (isdigit(c)) {
12020                         /* $[{[#]]NUM[}] */
12021                         do {
12022                                 STPUTC(c, out);
12023                                 c = pgetc_eatbnl();
12024                         } while (isdigit(c));
12025                 } else if (is_special(c)) {
12026                         /* $[{[#]]<specialchar>[}] */
12027                         int cc = c;
12028
12029                         c = pgetc_eatbnl();
12030                         if (!subtype && cc == '#') {
12031                                 subtype = VSLENGTH;
12032                                 if (c == '_' || isalnum(c))
12033                                         goto varname;
12034                                 cc = c;
12035                                 c = pgetc_eatbnl();
12036                                 if (cc == '}' || c != '}') {
12037                                         pungetc();
12038                                         subtype = 0;
12039                                         c = cc;
12040                                         cc = '#';
12041                                 }
12042                         }
12043                         USTPUTC(cc, out);
12044                 } else {
12045                         goto badsub;
12046                 }
12047                 if (c != '}' && subtype == VSLENGTH) {
12048                         /* ${#VAR didn't end with } */
12049                         goto badsub;
12050                 }
12051
12052                 if (subtype == 0) {
12053                         static const char types[] ALIGN1 = "}-+?=";
12054                         /* ${VAR...} but not $VAR or ${#VAR} */
12055                         /* c == first char after VAR */
12056                         switch (c) {
12057                         case ':':
12058                                 c = pgetc_eatbnl();
12059 #if BASH_SUBSTR
12060                                 /* This check is only needed to not misinterpret
12061                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12062                                  * constructs.
12063                                  */
12064                                 if (!strchr(types, c)) {
12065                                         subtype = VSSUBSTR;
12066                                         pungetc();
12067                                         break; /* "goto badsub" is bigger (!) */
12068                                 }
12069 #endif
12070                                 subtype = VSNUL;
12071                                 /*FALLTHROUGH*/
12072                         default: {
12073                                 const char *p = strchr(types, c);
12074                                 if (p == NULL)
12075                                         break;
12076                                 subtype |= p - types + VSNORMAL;
12077                                 break;
12078                         }
12079                         case '%':
12080                         case '#': {
12081                                 int cc = c;
12082                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12083                                 c = pgetc_eatbnl();
12084                                 if (c != cc)
12085                                         goto badsub;
12086                                 subtype++;
12087                                 break;
12088                         }
12089 #if BASH_PATTERN_SUBST
12090                         case '/':
12091                                 /* ${v/[/]pattern/repl} */
12092 //TODO: encode pattern and repl separately.
12093 // Currently ${v/$var_with_slash/repl} is horribly broken
12094                                 subtype = VSREPLACE;
12095                                 c = pgetc_eatbnl();
12096                                 if (c != '/')
12097                                         goto badsub;
12098                                 subtype++; /* VSREPLACEALL */
12099                                 break;
12100 #endif
12101                         }
12102                 } else {
12103  badsub:
12104                         pungetc();
12105                 }
12106                 ((unsigned char *)stackblock())[typeloc] = subtype;
12107                 if (subtype != VSNORMAL) {
12108                         varnest++;
12109                         if (dblquote)
12110                                 dqvarnest++;
12111                 }
12112                 STPUTC('=', out);
12113         }
12114         goto parsesub_return;
12115 }
12116
12117 /*
12118  * Called to parse command substitutions.  Newstyle is set if the command
12119  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12120  * list of commands (passed by reference), and savelen is the number of
12121  * characters on the top of the stack which must be preserved.
12122  */
12123 parsebackq: {
12124         struct nodelist **nlpp;
12125         union node *n;
12126         char *str;
12127         size_t savelen;
12128         smallint saveprompt = 0;
12129
12130         str = NULL;
12131         savelen = out - (char *)stackblock();
12132         if (savelen > 0) {
12133                 /*
12134                  * FIXME: this can allocate very large block on stack and SEGV.
12135                  * Example:
12136                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12137                  * allocates 100kb for every command subst. With about
12138                  * a hundred command substitutions stack overflows.
12139                  * With larger prepended string, SEGV happens sooner.
12140                  */
12141                 str = alloca(savelen);
12142                 memcpy(str, stackblock(), savelen);
12143         }
12144
12145         if (oldstyle) {
12146                 /* We must read until the closing backquote, giving special
12147                  * treatment to some slashes, and then push the string and
12148                  * reread it as input, interpreting it normally.
12149                  */
12150                 char *pout;
12151                 size_t psavelen;
12152                 char *pstr;
12153
12154                 STARTSTACKSTR(pout);
12155                 for (;;) {
12156                         int pc;
12157
12158                         setprompt_if(needprompt, 2);
12159                         pc = pgetc();
12160                         switch (pc) {
12161                         case '`':
12162                                 goto done;
12163
12164                         case '\\':
12165                                 pc = pgetc();
12166                                 if (pc == '\n') {
12167                                         nlprompt();
12168                                         /*
12169                                          * If eating a newline, avoid putting
12170                                          * the newline into the new character
12171                                          * stream (via the STPUTC after the
12172                                          * switch).
12173                                          */
12174                                         continue;
12175                                 }
12176                                 if (pc != '\\' && pc != '`' && pc != '$'
12177                                  && (!dblquote || pc != '"')
12178                                 ) {
12179                                         STPUTC('\\', pout);
12180                                 }
12181                                 if (pc <= 255 /* not PEOA or PEOF */) {
12182                                         break;
12183                                 }
12184                                 /* fall through */
12185
12186                         case PEOF:
12187                         IF_ASH_ALIAS(case PEOA:)
12188                                 startlinno = g_parsefile->linno;
12189                                 raise_error_syntax("EOF in backquote substitution");
12190
12191                         case '\n':
12192                                 nlnoprompt();
12193                                 break;
12194
12195                         default:
12196                                 break;
12197                         }
12198                         STPUTC(pc, pout);
12199                 }
12200  done:
12201                 STPUTC('\0', pout);
12202                 psavelen = pout - (char *)stackblock();
12203                 if (psavelen > 0) {
12204                         pstr = grabstackstr(pout);
12205                         setinputstring(pstr);
12206                 }
12207         }
12208         nlpp = &bqlist;
12209         while (*nlpp)
12210                 nlpp = &(*nlpp)->next;
12211         *nlpp = stzalloc(sizeof(**nlpp));
12212         /* (*nlpp)->next = NULL; - stzalloc did it */
12213
12214         if (oldstyle) {
12215                 saveprompt = doprompt;
12216                 doprompt = 0;
12217         }
12218
12219         n = list(2);
12220
12221         if (oldstyle)
12222                 doprompt = saveprompt;
12223         else if (readtoken() != TRP)
12224                 raise_error_unexpected_syntax(TRP);
12225
12226         (*nlpp)->n = n;
12227         if (oldstyle) {
12228                 /*
12229                  * Start reading from old file again, ignoring any pushed back
12230                  * tokens left from the backquote parsing
12231                  */
12232                 popfile();
12233                 tokpushback = 0;
12234         }
12235         while (stackblocksize() <= savelen)
12236                 growstackblock();
12237         STARTSTACKSTR(out);
12238         if (str) {
12239                 memcpy(out, str, savelen);
12240                 STADJUST(savelen, out);
12241         }
12242         USTPUTC(CTLBACKQ, out);
12243         if (oldstyle)
12244                 goto parsebackq_oldreturn;
12245         goto parsebackq_newreturn;
12246 }
12247
12248 #if ENABLE_FEATURE_SH_MATH
12249 /*
12250  * Parse an arithmetic expansion (indicate start of one and set state)
12251  */
12252 parsearith: {
12253         if (++arinest == 1) {
12254                 prevsyntax = syntax;
12255                 syntax = ARISYNTAX;
12256         }
12257         USTPUTC(CTLARI, out);
12258         goto parsearith_return;
12259 }
12260 #endif
12261 } /* end of readtoken */
12262
12263 /*
12264  * Read the next input token.
12265  * If the token is a word, we set backquotelist to the list of cmds in
12266  *      backquotes.  We set quoteflag to true if any part of the word was
12267  *      quoted.
12268  * If the token is TREDIR, then we set redirnode to a structure containing
12269  *      the redirection.
12270  * In all cases, the variable startlinno is set to the number of the line
12271  *      on which the token starts.
12272  *
12273  * [Change comment:  here documents and internal procedures]
12274  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12275  *  word parsing code into a separate routine.  In this case, readtoken
12276  *  doesn't need to have any internal procedures, but parseword does.
12277  *  We could also make parseoperator in essence the main routine, and
12278  *  have parseword (readtoken1?) handle both words and redirection.]
12279  */
12280 #define NEW_xxreadtoken
12281 #ifdef NEW_xxreadtoken
12282 /* singles must be first! */
12283 static const char xxreadtoken_chars[7] ALIGN1 = {
12284         '\n', '(', ')', /* singles */
12285         '&', '|', ';',  /* doubles */
12286         0
12287 };
12288
12289 #define xxreadtoken_singles 3
12290 #define xxreadtoken_doubles 3
12291
12292 static const char xxreadtoken_tokens[] ALIGN1 = {
12293         TNL, TLP, TRP,          /* only single occurrence allowed */
12294         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12295         TEOF,                   /* corresponds to trailing nul */
12296         TAND, TOR, TENDCASE     /* if double occurrence */
12297 };
12298
12299 static int
12300 xxreadtoken(void)
12301 {
12302         int c;
12303
12304         if (tokpushback) {
12305                 tokpushback = 0;
12306                 return lasttoken;
12307         }
12308         setprompt_if(needprompt, 2);
12309         startlinno = g_parsefile->linno;
12310         for (;;) {                      /* until token or start of word found */
12311                 c = pgetc();
12312                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12313                         continue;
12314
12315                 if (c == '#') {
12316                         while ((c = pgetc()) != '\n' && c != PEOF)
12317                                 continue;
12318                         pungetc();
12319                 } else if (c == '\\') {
12320                         if (pgetc() != '\n') {
12321                                 pungetc();
12322                                 break; /* return readtoken1(...) */
12323                         }
12324                         nlprompt();
12325                 } else {
12326                         const char *p;
12327
12328                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12329                         if (c != PEOF) {
12330                                 if (c == '\n') {
12331                                         nlnoprompt();
12332                                 }
12333
12334                                 p = strchr(xxreadtoken_chars, c);
12335                                 if (p == NULL)
12336                                         break; /* return readtoken1(...) */
12337
12338                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12339                                         int cc = pgetc();
12340                                         if (cc == c) {    /* double occurrence? */
12341                                                 p += xxreadtoken_doubles + 1;
12342                                         } else {
12343                                                 pungetc();
12344 #if BASH_REDIR_OUTPUT
12345                                                 if (c == '&' && cc == '>') /* &> */
12346                                                         break; /* return readtoken1(...) */
12347 #endif
12348                                         }
12349                                 }
12350                         }
12351                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12352                         return lasttoken;
12353                 }
12354         } /* for (;;) */
12355
12356         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12357 }
12358 #else /* old xxreadtoken */
12359 #define RETURN(token)   return lasttoken = token
12360 static int
12361 xxreadtoken(void)
12362 {
12363         int c;
12364
12365         if (tokpushback) {
12366                 tokpushback = 0;
12367                 return lasttoken;
12368         }
12369         setprompt_if(needprompt, 2);
12370         startlinno = g_parsefile->linno;
12371         for (;;) {      /* until token or start of word found */
12372                 c = pgetc();
12373                 switch (c) {
12374                 case ' ': case '\t':
12375                 IF_ASH_ALIAS(case PEOA:)
12376                         continue;
12377                 case '#':
12378                         while ((c = pgetc()) != '\n' && c != PEOF)
12379                                 continue;
12380                         pungetc();
12381                         continue;
12382                 case '\\':
12383                         if (pgetc() == '\n') {
12384                                 nlprompt();
12385                                 continue;
12386                         }
12387                         pungetc();
12388                         goto breakloop;
12389                 case '\n':
12390                         nlnoprompt();
12391                         RETURN(TNL);
12392                 case PEOF:
12393                         RETURN(TEOF);
12394                 case '&':
12395                         if (pgetc() == '&')
12396                                 RETURN(TAND);
12397                         pungetc();
12398                         RETURN(TBACKGND);
12399                 case '|':
12400                         if (pgetc() == '|')
12401                                 RETURN(TOR);
12402                         pungetc();
12403                         RETURN(TPIPE);
12404                 case ';':
12405                         if (pgetc() == ';')
12406                                 RETURN(TENDCASE);
12407                         pungetc();
12408                         RETURN(TSEMI);
12409                 case '(':
12410                         RETURN(TLP);
12411                 case ')':
12412                         RETURN(TRP);
12413                 default:
12414                         goto breakloop;
12415                 }
12416         }
12417  breakloop:
12418         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12419 #undef RETURN
12420 }
12421 #endif /* old xxreadtoken */
12422
12423 static int
12424 readtoken(void)
12425 {
12426         int t;
12427         int kwd = checkkwd;
12428 #if DEBUG
12429         smallint alreadyseen = tokpushback;
12430 #endif
12431
12432 #if ENABLE_ASH_ALIAS
12433  top:
12434 #endif
12435
12436         t = xxreadtoken();
12437
12438         /*
12439          * eat newlines
12440          */
12441         if (kwd & CHKNL) {
12442                 while (t == TNL) {
12443                         parseheredoc();
12444                         t = xxreadtoken();
12445                 }
12446         }
12447
12448         if (t != TWORD || quoteflag) {
12449                 goto out;
12450         }
12451
12452         /*
12453          * check for keywords
12454          */
12455         if (kwd & CHKKWD) {
12456                 const char *const *pp;
12457
12458                 pp = findkwd(wordtext);
12459                 if (pp) {
12460                         lasttoken = t = pp - tokname_array;
12461                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12462                         goto out;
12463                 }
12464         }
12465
12466         if (checkkwd & CHKALIAS) {
12467 #if ENABLE_ASH_ALIAS
12468                 struct alias *ap;
12469                 ap = lookupalias(wordtext, 1);
12470                 if (ap != NULL) {
12471                         if (*ap->val) {
12472                                 pushstring(ap->val, ap);
12473                         }
12474                         goto top;
12475                 }
12476 #endif
12477         }
12478  out:
12479         checkkwd = 0;
12480 #if DEBUG
12481         if (!alreadyseen)
12482                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12483         else
12484                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12485 #endif
12486         return t;
12487 }
12488
12489 static int
12490 peektoken(void)
12491 {
12492         int t;
12493
12494         t = readtoken();
12495         tokpushback = 1;
12496         return t;
12497 }
12498
12499 /*
12500  * Read and parse a command.  Returns NODE_EOF on end of file.
12501  * (NULL is a valid parse tree indicating a blank line.)
12502  */
12503 static union node *
12504 parsecmd(int interact)
12505 {
12506         tokpushback = 0;
12507         checkkwd = 0;
12508         heredoclist = 0;
12509         doprompt = interact;
12510         setprompt_if(doprompt, doprompt);
12511         needprompt = 0;
12512         return list(1);
12513 }
12514
12515 /*
12516  * Input any here documents.
12517  */
12518 static void
12519 parseheredoc(void)
12520 {
12521         struct heredoc *here;
12522         union node *n;
12523
12524         here = heredoclist;
12525         heredoclist = NULL;
12526
12527         while (here) {
12528                 setprompt_if(needprompt, 2);
12529                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12530                                 here->eofmark, here->striptabs);
12531                 n = stzalloc(sizeof(struct narg));
12532                 n->narg.type = NARG;
12533                 /*n->narg.next = NULL; - stzalloc did it */
12534                 n->narg.text = wordtext;
12535                 n->narg.backquote = backquotelist;
12536                 here->here->nhere.doc = n;
12537                 here = here->next;
12538         }
12539 }
12540
12541
12542 /*
12543  * called by editline -- any expansions to the prompt should be added here.
12544  */
12545 static const char *
12546 expandstr(const char *ps)
12547 {
12548         union node n;
12549         int saveprompt;
12550
12551         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12552          * and token processing _can_ alter it (delete NULs etc). */
12553         setinputstring((char *)ps);
12554
12555         saveprompt = doprompt;
12556         doprompt = 0;
12557         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12558         doprompt = saveprompt;
12559
12560         popfile();
12561
12562         n.narg.type = NARG;
12563         n.narg.next = NULL;
12564         n.narg.text = wordtext;
12565         n.narg.backquote = backquotelist;
12566
12567         expandarg(&n, NULL, EXP_QUOTED);
12568         return stackblock();
12569 }
12570
12571 /*
12572  * Execute a command or commands contained in a string.
12573  */
12574 static int
12575 evalstring(char *s, int flags)
12576 {
12577         struct jmploc *volatile savehandler;
12578         struct jmploc jmploc;
12579         int ex;
12580
12581         union node *n;
12582         struct stackmark smark;
12583         int status;
12584
12585         s = sstrdup(s);
12586         setinputstring(s);
12587         setstackmark(&smark);
12588
12589         status = 0;
12590         /* On exception inside execution loop, we must popfile().
12591          * Try interactively:
12592          *      readonly a=a
12593          *      command eval "a=b"  # throws "is read only" error
12594          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12595          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12596          */
12597         savehandler = exception_handler;
12598         ex = setjmp(jmploc.loc);
12599         if (ex)
12600                 goto out;
12601         exception_handler = &jmploc;
12602
12603         while ((n = parsecmd(0)) != NODE_EOF) {
12604                 int i;
12605
12606                 i = evaltree(n, flags);
12607                 if (n)
12608                         status = i;
12609                 popstackmark(&smark);
12610                 if (evalskip)
12611                         break;
12612         }
12613  out:
12614         popstackmark(&smark);
12615         popfile();
12616         stunalloc(s);
12617
12618         exception_handler = savehandler;
12619         if (ex)
12620                 longjmp(exception_handler->loc, ex);
12621
12622         return status;
12623 }
12624
12625 /*
12626  * The eval command.
12627  */
12628 static int FAST_FUNC
12629 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12630 {
12631         char *p;
12632         char *concat;
12633
12634         if (argv[1]) {
12635                 p = argv[1];
12636                 argv += 2;
12637                 if (argv[0]) {
12638                         STARTSTACKSTR(concat);
12639                         for (;;) {
12640                                 concat = stack_putstr(p, concat);
12641                                 p = *argv++;
12642                                 if (p == NULL)
12643                                         break;
12644                                 STPUTC(' ', concat);
12645                         }
12646                         STPUTC('\0', concat);
12647                         p = grabstackstr(concat);
12648                 }
12649                 return evalstring(p, flags & EV_TESTED);
12650         }
12651         return 0;
12652 }
12653
12654 /*
12655  * Read and execute commands.
12656  * "Top" is nonzero for the top level command loop;
12657  * it turns on prompting if the shell is interactive.
12658  */
12659 static int
12660 cmdloop(int top)
12661 {
12662         union node *n;
12663         struct stackmark smark;
12664         int inter;
12665         int status = 0;
12666         int numeof = 0;
12667
12668         TRACE(("cmdloop(%d) called\n", top));
12669         for (;;) {
12670                 int skip;
12671
12672                 setstackmark(&smark);
12673 #if JOBS
12674                 if (doing_jobctl)
12675                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12676 #endif
12677                 inter = 0;
12678                 if (iflag && top) {
12679                         inter++;
12680                         chkmail();
12681                 }
12682                 n = parsecmd(inter);
12683 #if DEBUG
12684                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12685                         showtree(n);
12686 #endif
12687                 if (n == NODE_EOF) {
12688                         if (!top || numeof >= 50)
12689                                 break;
12690                         if (!stoppedjobs()) {
12691                                 if (!Iflag)
12692                                         break;
12693                                 out2str("\nUse \"exit\" to leave shell.\n");
12694                         }
12695                         numeof++;
12696                 } else if (nflag == 0) {
12697                         int i;
12698
12699                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12700                         job_warning >>= 1;
12701                         numeof = 0;
12702                         i = evaltree(n, 0);
12703                         if (n)
12704                                 status = i;
12705                 }
12706                 popstackmark(&smark);
12707                 skip = evalskip;
12708
12709                 if (skip) {
12710                         evalskip &= ~SKIPFUNC;
12711                         break;
12712                 }
12713         }
12714         return status;
12715 }
12716
12717 /*
12718  * Take commands from a file.  To be compatible we should do a path
12719  * search for the file, which is necessary to find sub-commands.
12720  */
12721 static char *
12722 find_dot_file(char *name)
12723 {
12724         char *fullname;
12725         const char *path = pathval();
12726         struct stat statb;
12727
12728         /* don't try this for absolute or relative paths */
12729         if (strchr(name, '/'))
12730                 return name;
12731
12732         while ((fullname = path_advance(&path, name)) != NULL) {
12733                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12734                         /*
12735                          * Don't bother freeing here, since it will
12736                          * be freed by the caller.
12737                          */
12738                         return fullname;
12739                 }
12740                 if (fullname != name)
12741                         stunalloc(fullname);
12742         }
12743
12744         /* not found in the PATH */
12745         ash_msg_and_raise_error("%s: not found", name);
12746         /* NOTREACHED */
12747 }
12748
12749 static int FAST_FUNC
12750 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12751 {
12752         /* "false; . empty_file; echo $?" should print 0, not 1: */
12753         int status = 0;
12754         char *fullname;
12755         char **argv;
12756         char *args_need_save;
12757         struct strlist *sp;
12758         volatile struct shparam saveparam;
12759
12760         for (sp = cmdenviron; sp; sp = sp->next)
12761                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12762
12763         nextopt(nullstr); /* handle possible "--" */
12764         argv = argptr;
12765
12766         if (!argv[0]) {
12767                 /* bash says: "bash: .: filename argument required" */
12768                 return 2; /* bash compat */
12769         }
12770
12771         /* This aborts if file isn't found, which is POSIXly correct.
12772          * bash returns exitcode 1 instead.
12773          */
12774         fullname = find_dot_file(argv[0]);
12775         argv++;
12776         args_need_save = argv[0];
12777         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12778                 int argc;
12779                 saveparam = shellparam;
12780                 shellparam.malloced = 0;
12781                 argc = 1;
12782                 while (argv[argc])
12783                         argc++;
12784                 shellparam.nparam = argc;
12785                 shellparam.p = argv;
12786         };
12787
12788         /* This aborts if file can't be opened, which is POSIXly correct.
12789          * bash returns exitcode 1 instead.
12790          */
12791         setinputfile(fullname, INPUT_PUSH_FILE);
12792         commandname = fullname;
12793         status = cmdloop(0);
12794         popfile();
12795
12796         if (args_need_save) {
12797                 freeparam(&shellparam);
12798                 shellparam = saveparam;
12799         };
12800
12801         return status;
12802 }
12803
12804 static int FAST_FUNC
12805 exitcmd(int argc UNUSED_PARAM, char **argv)
12806 {
12807         if (stoppedjobs())
12808                 return 0;
12809         if (argv[1])
12810                 exitstatus = number(argv[1]);
12811         raise_exception(EXEXIT);
12812         /* NOTREACHED */
12813 }
12814
12815 /*
12816  * Read a file containing shell functions.
12817  */
12818 static void
12819 readcmdfile(char *name)
12820 {
12821         setinputfile(name, INPUT_PUSH_FILE);
12822         cmdloop(0);
12823         popfile();
12824 }
12825
12826
12827 /* ============ find_command inplementation */
12828
12829 /*
12830  * Resolve a command name.  If you change this routine, you may have to
12831  * change the shellexec routine as well.
12832  */
12833 static void
12834 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12835 {
12836         struct tblentry *cmdp;
12837         int idx;
12838         int prev;
12839         char *fullname;
12840         struct stat statb;
12841         int e;
12842         int updatetbl;
12843         struct builtincmd *bcmd;
12844
12845         /* If name contains a slash, don't use PATH or hash table */
12846         if (strchr(name, '/') != NULL) {
12847                 entry->u.index = -1;
12848                 if (act & DO_ABS) {
12849                         while (stat(name, &statb) < 0) {
12850 #ifdef SYSV
12851                                 if (errno == EINTR)
12852                                         continue;
12853 #endif
12854                                 entry->cmdtype = CMDUNKNOWN;
12855                                 return;
12856                         }
12857                 }
12858                 entry->cmdtype = CMDNORMAL;
12859                 return;
12860         }
12861
12862 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12863
12864         updatetbl = (path == pathval());
12865         if (!updatetbl) {
12866                 act |= DO_ALTPATH;
12867                 if (strstr(path, "%builtin") != NULL)
12868                         act |= DO_ALTBLTIN;
12869         }
12870
12871         /* If name is in the table, check answer will be ok */
12872         cmdp = cmdlookup(name, 0);
12873         if (cmdp != NULL) {
12874                 int bit;
12875
12876                 switch (cmdp->cmdtype) {
12877                 default:
12878 #if DEBUG
12879                         abort();
12880 #endif
12881                 case CMDNORMAL:
12882                         bit = DO_ALTPATH;
12883                         break;
12884                 case CMDFUNCTION:
12885                         bit = DO_NOFUNC;
12886                         break;
12887                 case CMDBUILTIN:
12888                         bit = DO_ALTBLTIN;
12889                         break;
12890                 }
12891                 if (act & bit) {
12892                         updatetbl = 0;
12893                         cmdp = NULL;
12894                 } else if (cmdp->rehash == 0)
12895                         /* if not invalidated by cd, we're done */
12896                         goto success;
12897         }
12898
12899         /* If %builtin not in path, check for builtin next */
12900         bcmd = find_builtin(name);
12901         if (bcmd) {
12902                 if (IS_BUILTIN_REGULAR(bcmd))
12903                         goto builtin_success;
12904                 if (act & DO_ALTPATH) {
12905                         if (!(act & DO_ALTBLTIN))
12906                                 goto builtin_success;
12907                 } else if (builtinloc <= 0) {
12908                         goto builtin_success;
12909                 }
12910         }
12911
12912 #if ENABLE_FEATURE_SH_STANDALONE
12913         {
12914                 int applet_no = find_applet_by_name(name);
12915                 if (applet_no >= 0) {
12916                         entry->cmdtype = CMDNORMAL;
12917                         entry->u.index = -2 - applet_no;
12918                         return;
12919                 }
12920         }
12921 #endif
12922
12923         /* We have to search path. */
12924         prev = -1;              /* where to start */
12925         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12926                 if (cmdp->cmdtype == CMDBUILTIN)
12927                         prev = builtinloc;
12928                 else
12929                         prev = cmdp->param.index;
12930         }
12931
12932         e = ENOENT;
12933         idx = -1;
12934  loop:
12935         while ((fullname = path_advance(&path, name)) != NULL) {
12936                 stunalloc(fullname);
12937                 /* NB: code below will still use fullname
12938                  * despite it being "unallocated" */
12939                 idx++;
12940                 if (pathopt) {
12941                         if (prefix(pathopt, "builtin")) {
12942                                 if (bcmd)
12943                                         goto builtin_success;
12944                                 continue;
12945                         }
12946                         if ((act & DO_NOFUNC)
12947                          || !prefix(pathopt, "func")
12948                         ) {     /* ignore unimplemented options */
12949                                 continue;
12950                         }
12951                 }
12952                 /* if rehash, don't redo absolute path names */
12953                 if (fullname[0] == '/' && idx <= prev) {
12954                         if (idx < prev)
12955                                 continue;
12956                         TRACE(("searchexec \"%s\": no change\n", name));
12957                         goto success;
12958                 }
12959                 while (stat(fullname, &statb) < 0) {
12960 #ifdef SYSV
12961                         if (errno == EINTR)
12962                                 continue;
12963 #endif
12964                         if (errno != ENOENT && errno != ENOTDIR)
12965                                 e = errno;
12966                         goto loop;
12967                 }
12968                 e = EACCES;     /* if we fail, this will be the error */
12969                 if (!S_ISREG(statb.st_mode))
12970                         continue;
12971                 if (pathopt) {          /* this is a %func directory */
12972                         stalloc(strlen(fullname) + 1);
12973                         /* NB: stalloc will return space pointed by fullname
12974                          * (because we don't have any intervening allocations
12975                          * between stunalloc above and this stalloc) */
12976                         readcmdfile(fullname);
12977                         cmdp = cmdlookup(name, 0);
12978                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12979                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12980                         stunalloc(fullname);
12981                         goto success;
12982                 }
12983                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12984                 if (!updatetbl) {
12985                         entry->cmdtype = CMDNORMAL;
12986                         entry->u.index = idx;
12987                         return;
12988                 }
12989                 INT_OFF;
12990                 cmdp = cmdlookup(name, 1);
12991                 cmdp->cmdtype = CMDNORMAL;
12992                 cmdp->param.index = idx;
12993                 INT_ON;
12994                 goto success;
12995         }
12996
12997         /* We failed.  If there was an entry for this command, delete it */
12998         if (cmdp && updatetbl)
12999                 delete_cmd_entry();
13000         if (act & DO_ERR)
13001                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13002         entry->cmdtype = CMDUNKNOWN;
13003         return;
13004
13005  builtin_success:
13006         if (!updatetbl) {
13007                 entry->cmdtype = CMDBUILTIN;
13008                 entry->u.cmd = bcmd;
13009                 return;
13010         }
13011         INT_OFF;
13012         cmdp = cmdlookup(name, 1);
13013         cmdp->cmdtype = CMDBUILTIN;
13014         cmdp->param.cmd = bcmd;
13015         INT_ON;
13016  success:
13017         cmdp->rehash = 0;
13018         entry->cmdtype = cmdp->cmdtype;
13019         entry->u = cmdp->param;
13020 }
13021
13022
13023 /*
13024  * The trap builtin.
13025  */
13026 static int FAST_FUNC
13027 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13028 {
13029         char *action;
13030         char **ap;
13031         int signo, exitcode;
13032
13033         nextopt(nullstr);
13034         ap = argptr;
13035         if (!*ap) {
13036                 for (signo = 0; signo < NSIG; signo++) {
13037                         char *tr = trap_ptr[signo];
13038                         if (tr) {
13039                                 /* note: bash adds "SIG", but only if invoked
13040                                  * as "bash". If called as "sh", or if set -o posix,
13041                                  * then it prints short signal names.
13042                                  * We are printing short names: */
13043                                 out1fmt("trap -- %s %s\n",
13044                                                 single_quote(tr),
13045                                                 get_signame(signo));
13046                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13047                  * In this case, we will exit very soon, no need to free(). */
13048                                 /* if (trap_ptr != trap && tp[0]) */
13049                                 /*      free(tr); */
13050                         }
13051                 }
13052                 /*
13053                 if (trap_ptr != trap) {
13054                         free(trap_ptr);
13055                         trap_ptr = trap;
13056                 }
13057                 */
13058                 return 0;
13059         }
13060
13061         action = NULL;
13062         if (ap[1])
13063                 action = *ap++;
13064         exitcode = 0;
13065         while (*ap) {
13066                 signo = get_signum(*ap);
13067                 if (signo < 0 || signo >= NSIG) {
13068                         /* Mimic bash message exactly */
13069                         ash_msg("%s: invalid signal specification", *ap);
13070                         exitcode = 1;
13071                         goto next;
13072                 }
13073                 INT_OFF;
13074                 if (action) {
13075                         if (LONE_DASH(action))
13076                                 action = NULL;
13077                         else {
13078                                 if (action[0]) /* not NULL and not "" and not "-" */
13079                                         may_have_traps = 1;
13080                                 action = ckstrdup(action);
13081                         }
13082                 }
13083                 free(trap[signo]);
13084                 trap[signo] = action;
13085                 if (signo != 0)
13086                         setsignal(signo);
13087                 INT_ON;
13088  next:
13089                 ap++;
13090         }
13091         return exitcode;
13092 }
13093
13094
13095 /* ============ Builtins */
13096
13097 #if ENABLE_ASH_HELP
13098 static int FAST_FUNC
13099 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13100 {
13101         unsigned col;
13102         unsigned i;
13103
13104         out1fmt(
13105                 "Built-in commands:\n"
13106                 "------------------\n");
13107         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13108                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13109                                         builtintab[i].name + 1);
13110                 if (col > 60) {
13111                         out1fmt("\n");
13112                         col = 0;
13113                 }
13114         }
13115 # if ENABLE_FEATURE_SH_STANDALONE
13116         {
13117                 const char *a = applet_names;
13118                 while (*a) {
13119                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13120                         if (col > 60) {
13121                                 out1fmt("\n");
13122                                 col = 0;
13123                         }
13124                         while (*a++ != '\0')
13125                                 continue;
13126                 }
13127         }
13128 # endif
13129         newline_and_flush(stdout);
13130         return EXIT_SUCCESS;
13131 }
13132 #endif
13133
13134 #if MAX_HISTORY
13135 static int FAST_FUNC
13136 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13137 {
13138         show_history(line_input_state);
13139         return EXIT_SUCCESS;
13140 }
13141 #endif
13142
13143 /*
13144  * The export and readonly commands.
13145  */
13146 static int FAST_FUNC
13147 exportcmd(int argc UNUSED_PARAM, char **argv)
13148 {
13149         struct var *vp;
13150         char *name;
13151         const char *p;
13152         char **aptr;
13153         char opt;
13154         int flag;
13155         int flag_off;
13156
13157         /* "readonly" in bash accepts, but ignores -n.
13158          * We do the same: it saves a conditional in nextopt's param.
13159          */
13160         flag_off = 0;
13161         while ((opt = nextopt("np")) != '\0') {
13162                 if (opt == 'n')
13163                         flag_off = VEXPORT;
13164         }
13165         flag = VEXPORT;
13166         if (argv[0][0] == 'r') {
13167                 flag = VREADONLY;
13168                 flag_off = 0; /* readonly ignores -n */
13169         }
13170         flag_off = ~flag_off;
13171
13172         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13173         {
13174                 aptr = argptr;
13175                 name = *aptr;
13176                 if (name) {
13177                         do {
13178                                 p = strchr(name, '=');
13179                                 if (p != NULL) {
13180                                         p++;
13181                                 } else {
13182                                         vp = *findvar(hashvar(name), name);
13183                                         if (vp) {
13184                                                 vp->flags = ((vp->flags | flag) & flag_off);
13185                                                 continue;
13186                                         }
13187                                 }
13188                                 setvar(name, p, (flag & flag_off));
13189                         } while ((name = *++aptr) != NULL);
13190                         return 0;
13191                 }
13192         }
13193
13194         /* No arguments. Show the list of exported or readonly vars.
13195          * -n is ignored.
13196          */
13197         showvars(argv[0], flag, 0);
13198         return 0;
13199 }
13200
13201 /*
13202  * Delete a function if it exists.
13203  */
13204 static void
13205 unsetfunc(const char *name)
13206 {
13207         struct tblentry *cmdp;
13208
13209         cmdp = cmdlookup(name, 0);
13210         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13211                 delete_cmd_entry();
13212 }
13213
13214 /*
13215  * The unset builtin command.  We unset the function before we unset the
13216  * variable to allow a function to be unset when there is a readonly variable
13217  * with the same name.
13218  */
13219 static int FAST_FUNC
13220 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13221 {
13222         char **ap;
13223         int i;
13224         int flag = 0;
13225         int ret = 0;
13226
13227         while ((i = nextopt("vf")) != 0) {
13228                 flag = i;
13229         }
13230
13231         for (ap = argptr; *ap; ap++) {
13232                 if (flag != 'f') {
13233                         i = unsetvar(*ap);
13234                         ret |= i;
13235                         if (!(i & 2))
13236                                 continue;
13237                 }
13238                 if (flag != 'v')
13239                         unsetfunc(*ap);
13240         }
13241         return ret & 1;
13242 }
13243
13244 static const unsigned char timescmd_str[] ALIGN1 = {
13245         ' ',  offsetof(struct tms, tms_utime),
13246         '\n', offsetof(struct tms, tms_stime),
13247         ' ',  offsetof(struct tms, tms_cutime),
13248         '\n', offsetof(struct tms, tms_cstime),
13249         0
13250 };
13251 static int FAST_FUNC
13252 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13253 {
13254         unsigned long clk_tck, s, t;
13255         const unsigned char *p;
13256         struct tms buf;
13257
13258         clk_tck = bb_clk_tck();
13259         times(&buf);
13260
13261         p = timescmd_str;
13262         do {
13263                 t = *(clock_t *)(((char *) &buf) + p[1]);
13264                 s = t / clk_tck;
13265                 t = t % clk_tck;
13266                 out1fmt("%lum%lu.%03lus%c",
13267                         s / 60, s % 60,
13268                         (t * 1000) / clk_tck,
13269                         p[0]);
13270                 p += 2;
13271         } while (*p);
13272
13273         return 0;
13274 }
13275
13276 #if ENABLE_FEATURE_SH_MATH
13277 /*
13278  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13279  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13280  *
13281  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13282  */
13283 static int FAST_FUNC
13284 letcmd(int argc UNUSED_PARAM, char **argv)
13285 {
13286         arith_t i;
13287
13288         argv++;
13289         if (!*argv)
13290                 ash_msg_and_raise_error("expression expected");
13291         do {
13292                 i = ash_arith(*argv);
13293         } while (*++argv);
13294
13295         return !i;
13296 }
13297 #endif
13298
13299 /*
13300  * The read builtin. Options:
13301  *      -r              Do not interpret '\' specially
13302  *      -s              Turn off echo (tty only)
13303  *      -n NCHARS       Read NCHARS max
13304  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13305  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13306  *      -u FD           Read from given FD instead of fd 0
13307  * This uses unbuffered input, which may be avoidable in some cases.
13308  * TODO: bash also has:
13309  *      -a ARRAY        Read into array[0],[1],etc
13310  *      -d DELIM        End on DELIM char, not newline
13311  *      -e              Use line editing (tty only)
13312  */
13313 static int FAST_FUNC
13314 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13315 {
13316         char *opt_n = NULL;
13317         char *opt_p = NULL;
13318         char *opt_t = NULL;
13319         char *opt_u = NULL;
13320         int read_flags = 0;
13321         const char *r;
13322         int i;
13323
13324         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13325                 switch (i) {
13326                 case 'p':
13327                         opt_p = optionarg;
13328                         break;
13329                 case 'n':
13330                         opt_n = optionarg;
13331                         break;
13332                 case 's':
13333                         read_flags |= BUILTIN_READ_SILENT;
13334                         break;
13335                 case 't':
13336                         opt_t = optionarg;
13337                         break;
13338                 case 'r':
13339                         read_flags |= BUILTIN_READ_RAW;
13340                         break;
13341                 case 'u':
13342                         opt_u = optionarg;
13343                         break;
13344                 default:
13345                         break;
13346                 }
13347         }
13348
13349         /* "read -s" needs to save/restore termios, can't allow ^C
13350          * to jump out of it.
13351          */
13352  again:
13353         INT_OFF;
13354         r = shell_builtin_read(setvar0,
13355                 argptr,
13356                 bltinlookup("IFS"), /* can be NULL */
13357                 read_flags,
13358                 opt_n,
13359                 opt_p,
13360                 opt_t,
13361                 opt_u
13362         );
13363         INT_ON;
13364
13365         if ((uintptr_t)r == 1 && errno == EINTR) {
13366                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13367                 if (pending_sig == 0)
13368                         goto again;
13369         }
13370
13371         if ((uintptr_t)r > 1)
13372                 ash_msg_and_raise_error(r);
13373
13374         return (uintptr_t)r;
13375 }
13376
13377 static int FAST_FUNC
13378 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13379 {
13380         static const char permuser[3] ALIGN1 = "ogu";
13381
13382         mode_t mask;
13383         int symbolic_mode = 0;
13384
13385         while (nextopt("S") != '\0') {
13386                 symbolic_mode = 1;
13387         }
13388
13389         INT_OFF;
13390         mask = umask(0);
13391         umask(mask);
13392         INT_ON;
13393
13394         if (*argptr == NULL) {
13395                 if (symbolic_mode) {
13396                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13397                         char *p = buf;
13398                         int i;
13399
13400                         i = 2;
13401                         for (;;) {
13402                                 *p++ = ',';
13403                                 *p++ = permuser[i];
13404                                 *p++ = '=';
13405                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13406                                 if (!(mask & 0400)) *p++ = 'r';
13407                                 if (!(mask & 0200)) *p++ = 'w';
13408                                 if (!(mask & 0100)) *p++ = 'x';
13409                                 mask <<= 3;
13410                                 if (--i < 0)
13411                                         break;
13412                         }
13413                         *p = '\0';
13414                         puts(buf + 1);
13415                 } else {
13416                         out1fmt("%04o\n", mask);
13417                 }
13418         } else {
13419                 char *modestr = *argptr;
13420                 /* numeric umasks are taken as-is */
13421                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13422                 if (!isdigit(modestr[0]))
13423                         mask ^= 0777;
13424                 mask = bb_parse_mode(modestr, mask);
13425                 if ((unsigned)mask > 0777) {
13426                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13427                 }
13428                 if (!isdigit(modestr[0]))
13429                         mask ^= 0777;
13430                 umask(mask);
13431         }
13432         return 0;
13433 }
13434
13435 static int FAST_FUNC
13436 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13437 {
13438         return shell_builtin_ulimit(argv);
13439 }
13440
13441 /* ============ main() and helpers */
13442
13443 /*
13444  * Called to exit the shell.
13445  */
13446 static void
13447 exitshell(void)
13448 {
13449         struct jmploc loc;
13450         char *p;
13451         int status;
13452
13453 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13454         save_history(line_input_state);
13455 #endif
13456         status = exitstatus;
13457         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13458         if (setjmp(loc.loc)) {
13459                 if (exception_type == EXEXIT)
13460                         status = exitstatus;
13461                 goto out;
13462         }
13463         exception_handler = &loc;
13464         p = trap[0];
13465         if (p) {
13466                 trap[0] = NULL;
13467                 evalskip = 0;
13468                 evalstring(p, 0);
13469                 /*free(p); - we'll exit soon */
13470         }
13471  out:
13472         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13473          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13474          */
13475         setjobctl(0);
13476         flush_stdout_stderr();
13477         _exit(status);
13478         /* NOTREACHED */
13479 }
13480
13481 static void
13482 init(void)
13483 {
13484         /* we will never free this */
13485         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13486
13487         sigmode[SIGCHLD - 1] = S_DFL;
13488         setsignal(SIGCHLD);
13489
13490         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13491          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13492          */
13493         signal(SIGHUP, SIG_DFL);
13494
13495         {
13496                 char **envp;
13497                 const char *p;
13498                 struct stat st1, st2;
13499
13500                 initvar();
13501                 for (envp = environ; envp && *envp; envp++) {
13502                         p = endofname(*envp);
13503                         if (p != *envp && *p == '=') {
13504                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13505                         }
13506                 }
13507
13508                 setvareq((char*)defoptindvar, VTEXTFIXED);
13509
13510                 setvar0("PPID", utoa(getppid()));
13511 #if BASH_SHLVL_VAR
13512                 p = lookupvar("SHLVL");
13513                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13514 #endif
13515 #if BASH_HOSTNAME_VAR
13516                 if (!lookupvar("HOSTNAME")) {
13517                         struct utsname uts;
13518                         uname(&uts);
13519                         setvar0("HOSTNAME", uts.nodename);
13520                 }
13521 #endif
13522                 p = lookupvar("PWD");
13523                 if (p) {
13524                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13525                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13526                         ) {
13527                                 p = NULL;
13528                         }
13529                 }
13530                 setpwd(p, 0);
13531         }
13532 }
13533
13534
13535 //usage:#define ash_trivial_usage
13536 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13537 //usage:#define ash_full_usage "\n\n"
13538 //usage:        "Unix shell interpreter"
13539
13540 /*
13541  * Process the shell command line arguments.
13542  */
13543 static void
13544 procargs(char **argv)
13545 {
13546         int i;
13547         const char *xminusc;
13548         char **xargv;
13549
13550         xargv = argv;
13551         arg0 = xargv[0];
13552         /* if (xargv[0]) - mmm, this is always true! */
13553                 xargv++;
13554         for (i = 0; i < NOPTS; i++)
13555                 optlist[i] = 2;
13556         argptr = xargv;
13557         if (options(/*cmdline:*/ 1)) {
13558                 /* it already printed err message */
13559                 raise_exception(EXERROR);
13560         }
13561         xargv = argptr;
13562         xminusc = minusc;
13563         if (*xargv == NULL) {
13564                 if (xminusc)
13565                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13566                 sflag = 1;
13567         }
13568         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13569                 iflag = 1;
13570         if (mflag == 2)
13571                 mflag = iflag;
13572         for (i = 0; i < NOPTS; i++)
13573                 if (optlist[i] == 2)
13574                         optlist[i] = 0;
13575 #if DEBUG == 2
13576         debug = 1;
13577 #endif
13578         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13579         if (xminusc) {
13580                 minusc = *xargv++;
13581                 if (*xargv)
13582                         goto setarg0;
13583         } else if (!sflag) {
13584                 setinputfile(*xargv, 0);
13585  setarg0:
13586                 arg0 = *xargv++;
13587                 commandname = arg0;
13588         }
13589
13590         shellparam.p = xargv;
13591 #if ENABLE_ASH_GETOPTS
13592         shellparam.optind = 1;
13593         shellparam.optoff = -1;
13594 #endif
13595         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13596         while (*xargv) {
13597                 shellparam.nparam++;
13598                 xargv++;
13599         }
13600         optschanged();
13601 }
13602
13603 /*
13604  * Read /etc/profile, ~/.profile, $ENV.
13605  */
13606 static void
13607 read_profile(const char *name)
13608 {
13609         name = expandstr(name);
13610         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13611                 return;
13612         cmdloop(0);
13613         popfile();
13614 }
13615
13616 /*
13617  * This routine is called when an error or an interrupt occurs in an
13618  * interactive shell and control is returned to the main command loop.
13619  * (In dash, this function is auto-generated by build machinery).
13620  */
13621 static void
13622 reset(void)
13623 {
13624         /* from eval.c: */
13625         evalskip = 0;
13626         loopnest = 0;
13627
13628         /* from expand.c: */
13629         ifsfree();
13630
13631         /* from input.c: */
13632         g_parsefile->left_in_buffer = 0;
13633         g_parsefile->left_in_line = 0;      /* clear input buffer */
13634         popallfiles();
13635
13636         /* from redir.c: */
13637         while (redirlist)
13638                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13639 }
13640
13641 #if PROFILE
13642 static short profile_buf[16384];
13643 extern int etext();
13644 #endif
13645
13646 /*
13647  * Main routine.  We initialize things, parse the arguments, execute
13648  * profiles if we're a login shell, and then call cmdloop to execute
13649  * commands.  The setjmp call sets up the location to jump to when an
13650  * exception occurs.  When an exception occurs the variable "state"
13651  * is used to figure out how far we had gotten.
13652  */
13653 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13654 int ash_main(int argc UNUSED_PARAM, char **argv)
13655 {
13656         volatile smallint state;
13657         struct jmploc jmploc;
13658         struct stackmark smark;
13659
13660         /* Initialize global data */
13661         INIT_G_misc();
13662         INIT_G_memstack();
13663         INIT_G_var();
13664 #if ENABLE_ASH_ALIAS
13665         INIT_G_alias();
13666 #endif
13667         INIT_G_cmdtable();
13668
13669 #if PROFILE
13670         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13671 #endif
13672
13673 #if ENABLE_FEATURE_EDITING
13674         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13675 #endif
13676         state = 0;
13677         if (setjmp(jmploc.loc)) {
13678                 smallint e;
13679                 smallint s;
13680
13681                 reset();
13682
13683                 e = exception_type;
13684                 s = state;
13685                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13686                         exitshell();
13687                 }
13688                 if (e == EXINT) {
13689                         newline_and_flush(stderr);
13690                 }
13691
13692                 popstackmark(&smark);
13693                 FORCE_INT_ON; /* enable interrupts */
13694                 if (s == 1)
13695                         goto state1;
13696                 if (s == 2)
13697                         goto state2;
13698                 if (s == 3)
13699                         goto state3;
13700                 goto state4;
13701         }
13702         exception_handler = &jmploc;
13703         rootpid = getpid();
13704
13705         init();
13706         setstackmark(&smark);
13707         procargs(argv);
13708 #if DEBUG
13709         TRACE(("Shell args: "));
13710         trace_puts_args(argv);
13711 #endif
13712
13713         if (argv[0] && argv[0][0] == '-')
13714                 isloginsh = 1;
13715         if (isloginsh) {
13716                 const char *hp;
13717
13718                 state = 1;
13719                 read_profile("/etc/profile");
13720  state1:
13721                 state = 2;
13722                 hp = lookupvar("HOME");
13723                 if (hp)
13724                         read_profile("$HOME/.profile");
13725         }
13726  state2:
13727         state = 3;
13728         if (
13729 #ifndef linux
13730          getuid() == geteuid() && getgid() == getegid() &&
13731 #endif
13732          iflag
13733         ) {
13734                 const char *shinit = lookupvar("ENV");
13735                 if (shinit != NULL && *shinit != '\0')
13736                         read_profile(shinit);
13737         }
13738         popstackmark(&smark);
13739  state3:
13740         state = 4;
13741         if (minusc) {
13742                 /* evalstring pushes parsefile stack.
13743                  * Ensure we don't falsely claim that 0 (stdin)
13744                  * is one of stacked source fds.
13745                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13746                 // if (!sflag) g_parsefile->pf_fd = -1;
13747                 // ^^ not necessary since now we special-case fd 0
13748                 // in is_hidden_fd() to not be considered "hidden fd"
13749                 evalstring(minusc, 0);
13750         }
13751
13752         if (sflag || minusc == NULL) {
13753 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13754                 if (iflag) {
13755                         const char *hp = lookupvar("HISTFILE");
13756                         if (!hp) {
13757                                 hp = lookupvar("HOME");
13758                                 if (hp) {
13759                                         INT_OFF;
13760                                         hp = concat_path_file(hp, ".ash_history");
13761                                         setvar0("HISTFILE", hp);
13762                                         free((char*)hp);
13763                                         INT_ON;
13764                                         hp = lookupvar("HISTFILE");
13765                                 }
13766                         }
13767                         if (hp)
13768                                 line_input_state->hist_file = hp;
13769 # if ENABLE_FEATURE_SH_HISTFILESIZE
13770                         hp = lookupvar("HISTFILESIZE");
13771                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13772 # endif
13773                 }
13774 #endif
13775  state4: /* XXX ??? - why isn't this before the "if" statement */
13776                 cmdloop(1);
13777         }
13778 #if PROFILE
13779         monitor(0);
13780 #endif
13781 #ifdef GPROF
13782         {
13783                 extern void _mcleanup(void);
13784                 _mcleanup();
13785         }
13786 #endif
13787         TRACE(("End of main reached\n"));
13788         exitshell();
13789         /* NOTREACHED */
13790 }
13791
13792
13793 /*-
13794  * Copyright (c) 1989, 1991, 1993, 1994
13795  *      The Regents of the University of California.  All rights reserved.
13796  *
13797  * This code is derived from software contributed to Berkeley by
13798  * Kenneth Almquist.
13799  *
13800  * Redistribution and use in source and binary forms, with or without
13801  * modification, are permitted provided that the following conditions
13802  * are met:
13803  * 1. Redistributions of source code must retain the above copyright
13804  *    notice, this list of conditions and the following disclaimer.
13805  * 2. Redistributions in binary form must reproduce the above copyright
13806  *    notice, this list of conditions and the following disclaimer in the
13807  *    documentation and/or other materials provided with the distribution.
13808  * 3. Neither the name of the University nor the names of its contributors
13809  *    may be used to endorse or promote products derived from this software
13810  *    without specific prior written permission.
13811  *
13812  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13813  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13814  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13815  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13816  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13817  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13818  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13819  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13820  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13821  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13822  * SUCH DAMAGE.
13823  */