Spelling fixes in comments, documentation, tests and examples
[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"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:         Tha 'ash' shell adds about 60k in the default configuration and is
24 //config:         the most complete and most pedantically correct shell included with
25 //config:         busybox. This shell is actually a derivative of the Debian 'dash'
26 //config:         shell (by Herbert Xu), which was created by porting the 'ash' shell
27 //config:         (written by Kenneth Almquist) from NetBSD.
28 //config:
29 //config:# ash options
30 //config:# note: Don't remove !NOMMU part in the next line; it would break
31 //config:# menuconfig's indenting.
32 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
33 //config:
34 //config:config ASH_OPTIMIZE_FOR_SIZE
35 //config:       bool "Optimize for size instead of speed"
36 //config:       default y
37 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
38 //config:
39 //config:config ASH_INTERNAL_GLOB
40 //config:       bool "Use internal glob() implementation"
41 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
42 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
43 //config:       help
44 //config:         Do not use glob() function from libc, use internal implementation.
45 //config:         Use this if you are getting "glob.h: No such file or directory"
46 //config:         or similar build errors.
47 //config:         Note that as of now (2017-01), uclibc and musl glob() both have bugs
48 //config:         which would break ash if you select N here.
49 //config:
50 //config:config ASH_BASH_COMPAT
51 //config:       bool "bash-compatible extensions"
52 //config:       default y
53 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
54 //config:
55 //config:config ASH_JOB_CONTROL
56 //config:       bool "Job control"
57 //config:       default y
58 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
59 //config:
60 //config:config ASH_ALIAS
61 //config:       bool "Alias support"
62 //config:       default y
63 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
64 //config:
65 //config:config ASH_RANDOM_SUPPORT
66 //config:       bool "Pseudorandom generator and $RANDOM variable"
67 //config:       default y
68 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
69 //config:       help
70 //config:         Enable pseudorandom generator and dynamic variable "$RANDOM".
71 //config:         Each read of "$RANDOM" will generate a new pseudorandom value.
72 //config:         You can reset the generator by using a specified start value.
73 //config:         After "unset RANDOM" the generator will switch off and this
74 //config:         variable will no longer have special treatment.
75 //config:
76 //config:config ASH_EXPAND_PRMT
77 //config:       bool "Expand prompt string"
78 //config:       default y
79 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
80 //config:       help
81 //config:         $PS# may contain volatile content, such as backquote commands.
82 //config:         This option recreates the prompt string from the environment
83 //config:         variable each time it is displayed.
84 //config:
85 //config:config ASH_IDLE_TIMEOUT
86 //config:       bool "Idle timeout variable $TMOUT"
87 //config:       default y
88 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
89 //config:       help
90 //config:         Enable bash-like auto-logout after $TMOUT seconds of idle time.
91 //config:
92 //config:config ASH_MAIL
93 //config:       bool "Check for new mail in interactive shell"
94 //config:       default y
95 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
96 //config:       help
97 //config:         Enable "check for new mail" function:
98 //config:         if set, $MAIL file and $MAILPATH list of files
99 //config:         are checked for mtime changes, and "you have mail"
100 //config:         message is printed if change is detected.
101 //config:
102 //config:config ASH_ECHO
103 //config:       bool "echo builtin"
104 //config:       default y
105 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
106 //config:
107 //config:config ASH_PRINTF
108 //config:       bool "printf builtin"
109 //config:       default y
110 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
111 //config:
112 //config:config ASH_TEST
113 //config:       bool "test builtin"
114 //config:       default y
115 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
116 //config:
117 //config:config ASH_HELP
118 //config:       bool "help builtin"
119 //config:       default y
120 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
121 //config:
122 //config:config ASH_GETOPTS
123 //config:       bool "getopts builtin"
124 //config:       default y
125 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
126 //config:
127 //config:config ASH_CMDCMD
128 //config:       bool "command builtin"
129 //config:       default y
130 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
131 //config:       help
132 //config:         Enable support for the 'command' builtin, which allows
133 //config:         you to run the specified command or builtin,
134 //config:         even when there is a function with the same name.
135 //config:
136 //config:endif # ash options
137
138 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
139 //                      APPLET_ODDNAME:name  main location    suid_type     help
140 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
142
143 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
146 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
147
148 /*
149  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
150  * DEBUG=2 to compile in and turn on debugging.
151  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
152  * debugging info is written to ./trace, quit signal generates core dump.
153  */
154 #define DEBUG 0
155 /* Tweak debug output verbosity here */
156 #define DEBUG_TIME 0
157 #define DEBUG_PID 1
158 #define DEBUG_SIG 1
159 #define DEBUG_INTONOFF 0
160
161 #define PROFILE 0
162
163 #define JOBS ENABLE_ASH_JOB_CONTROL
164
165 #include <setjmp.h>
166 #include <fnmatch.h>
167 #include <sys/times.h>
168 #include <sys/utsname.h> /* for setting $HOSTNAME */
169 #include "busybox.h" /* for applet_names */
170
171 /* So far, all bash compat is controlled by one config option */
172 /* Separate defines document which part of code implements what */
173 /* function keyword */
174 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
175 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
176 /* &>file */
177 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
178 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
179 /* $'...' */
180 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
181 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
182 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
183 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
184 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
185 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
186 /* [[ EXPR ]] */
187 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
188 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
189 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
190 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
191 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
192
193 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
194 /* Bionic at least up to version 24 has no glob() */
195 # undef  ENABLE_ASH_INTERNAL_GLOB
196 # define ENABLE_ASH_INTERNAL_GLOB 1
197 #endif
198
199 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
200 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
201 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
202 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
203 # error glob() should unbackslash them and match. uClibc does not unbackslash,
204 # error fails to match dirname, subsequently not expanding <pattern> in it.
205 // Testcase:
206 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
207 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
208 #endif
209
210 #if !ENABLE_ASH_INTERNAL_GLOB
211 # include <glob.h>
212 #endif
213
214 #include "unicode.h"
215 #include "shell_common.h"
216 #if ENABLE_FEATURE_SH_MATH
217 # include "math.h"
218 #endif
219 #if ENABLE_ASH_RANDOM_SUPPORT
220 # include "random.h"
221 #else
222 # define CLEAR_RANDOM_T(rnd) ((void)0)
223 #endif
224
225 #include "NUM_APPLETS.h"
226 #if NUM_APPLETS == 1
227 /* STANDALONE does not make sense, and won't compile */
228 # undef CONFIG_FEATURE_SH_STANDALONE
229 # undef ENABLE_FEATURE_SH_STANDALONE
230 # undef IF_FEATURE_SH_STANDALONE
231 # undef IF_NOT_FEATURE_SH_STANDALONE
232 # define ENABLE_FEATURE_SH_STANDALONE 0
233 # define IF_FEATURE_SH_STANDALONE(...)
234 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
235 #endif
236
237 #ifndef PIPE_BUF
238 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
239 #endif
240
241 #if !BB_MMU
242 # error "Do not even bother, ash will not run on NOMMU machine"
243 #endif
244
245
246 /* ============ Hash table sizes. Configurable. */
247
248 #define VTABSIZE 39
249 #define ATABSIZE 39
250 #define CMDTABLESIZE 31         /* should be prime */
251
252
253 /* ============ Shell options */
254
255 static const char *const optletters_optnames[] = {
256         "e"   "errexit",
257         "f"   "noglob",
258         "I"   "ignoreeof",
259         "i"   "interactive",
260         "m"   "monitor",
261         "n"   "noexec",
262         "s"   "stdin",
263         "x"   "xtrace",
264         "v"   "verbose",
265         "C"   "noclobber",
266         "a"   "allexport",
267         "b"   "notify",
268         "u"   "nounset",
269         "\0"  "vi"
270 #if BASH_PIPEFAIL
271         ,"\0"  "pipefail"
272 #endif
273 #if DEBUG
274         ,"\0"  "nolog"
275         ,"\0"  "debug"
276 #endif
277 };
278
279 #define optletters(n)  optletters_optnames[n][0]
280 #define optnames(n)   (optletters_optnames[n] + 1)
281
282 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
283
284
285 /* ============ Misc data */
286
287 #define msg_illnum "Illegal number: %s"
288
289 /*
290  * We enclose jmp_buf in a structure so that we can declare pointers to
291  * jump locations.  The global variable handler contains the location to
292  * jump to when an exception occurs, and the global variable exception_type
293  * contains a code identifying the exception.  To implement nested
294  * exception handlers, the user should save the value of handler on entry
295  * to an inner scope, set handler to point to a jmploc structure for the
296  * inner scope, and restore handler on exit from the scope.
297  */
298 struct jmploc {
299         jmp_buf loc;
300 };
301
302 struct globals_misc {
303         uint8_t exitstatus;     /* exit status of last command */
304         uint8_t back_exitstatus;/* exit status of backquoted command */
305         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
306         int rootpid;            /* pid of main shell */
307         /* shell level: 0 for the main shell, 1 for its children, and so on */
308         int shlvl;
309 #define rootshell (!shlvl)
310         char *minusc;  /* argument to -c option */
311
312         char *curdir; // = nullstr;     /* current working directory */
313         char *physdir; // = nullstr;    /* physical working directory */
314
315         char *arg0; /* value of $0 */
316
317         struct jmploc *exception_handler;
318
319         volatile int suppress_int; /* counter */
320         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
321         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
322         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
323         smallint exception_type; /* kind of exception (0..5) */
324         /* exceptions */
325 #define EXINT 0         /* SIGINT received */
326 #define EXERROR 1       /* a generic error */
327 #define EXEXIT 4        /* exit the shell */
328
329         smallint isloginsh;
330         char nullstr[1];        /* zero length string */
331
332         char optlist[NOPTS];
333 #define eflag optlist[0]
334 #define fflag optlist[1]
335 #define Iflag optlist[2]
336 #define iflag optlist[3]
337 #define mflag optlist[4]
338 #define nflag optlist[5]
339 #define sflag optlist[6]
340 #define xflag optlist[7]
341 #define vflag optlist[8]
342 #define Cflag optlist[9]
343 #define aflag optlist[10]
344 #define bflag optlist[11]
345 #define uflag optlist[12]
346 #define viflag optlist[13]
347 #if BASH_PIPEFAIL
348 # define pipefail optlist[14]
349 #else
350 # define pipefail 0
351 #endif
352 #if DEBUG
353 # define nolog optlist[14 + BASH_PIPEFAIL]
354 # define debug optlist[15 + BASH_PIPEFAIL]
355 #endif
356
357         /* trap handler commands */
358         /*
359          * Sigmode records the current value of the signal handlers for the various
360          * modes.  A value of zero means that the current handler is not known.
361          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
362          */
363         char sigmode[NSIG - 1];
364 #define S_DFL      1            /* default signal handling (SIG_DFL) */
365 #define S_CATCH    2            /* signal is caught */
366 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
367 #define S_HARD_IGN 4            /* signal is ignored permanently */
368
369         /* indicates specified signal received */
370         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
371         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
372         char *trap[NSIG];
373         char **trap_ptr;        /* used only by "trap hack" */
374
375         /* Rarely referenced stuff */
376 #if ENABLE_ASH_RANDOM_SUPPORT
377         random_t random_gen;
378 #endif
379         pid_t backgndpid;        /* pid of last background process */
380 };
381 extern struct globals_misc *const ash_ptr_to_globals_misc;
382 #define G_misc (*ash_ptr_to_globals_misc)
383 #define exitstatus        (G_misc.exitstatus )
384 #define back_exitstatus   (G_misc.back_exitstatus )
385 #define job_warning       (G_misc.job_warning)
386 #define rootpid     (G_misc.rootpid    )
387 #define shlvl       (G_misc.shlvl      )
388 #define minusc      (G_misc.minusc     )
389 #define curdir      (G_misc.curdir     )
390 #define physdir     (G_misc.physdir    )
391 #define arg0        (G_misc.arg0       )
392 #define exception_handler (G_misc.exception_handler)
393 #define exception_type    (G_misc.exception_type   )
394 #define suppress_int      (G_misc.suppress_int     )
395 #define pending_int       (G_misc.pending_int      )
396 #define got_sigchld       (G_misc.got_sigchld      )
397 #define pending_sig       (G_misc.pending_sig      )
398 #define isloginsh   (G_misc.isloginsh  )
399 #define nullstr     (G_misc.nullstr    )
400 #define optlist     (G_misc.optlist    )
401 #define sigmode     (G_misc.sigmode    )
402 #define gotsig      (G_misc.gotsig     )
403 #define may_have_traps    (G_misc.may_have_traps   )
404 #define trap        (G_misc.trap       )
405 #define trap_ptr    (G_misc.trap_ptr   )
406 #define random_gen  (G_misc.random_gen )
407 #define backgndpid  (G_misc.backgndpid )
408 #define INIT_G_misc() do { \
409         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
410         barrier(); \
411         curdir = nullstr; \
412         physdir = nullstr; \
413         trap_ptr = trap; \
414 } while (0)
415
416
417 /* ============ DEBUG */
418 #if DEBUG
419 static void trace_printf(const char *fmt, ...);
420 static void trace_vprintf(const char *fmt, va_list va);
421 # define TRACE(param)    trace_printf param
422 # define TRACEV(param)   trace_vprintf param
423 # define close(fd) do { \
424         int dfd = (fd); \
425         if (close(dfd) < 0) \
426                 bb_error_msg("bug on %d: closing %d(0x%x)", \
427                         __LINE__, dfd, dfd); \
428 } while (0)
429 #else
430 # define TRACE(param)
431 # define TRACEV(param)
432 #endif
433
434
435 /* ============ Utility functions */
436 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
437 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
438
439 static int
440 isdigit_str9(const char *str)
441 {
442         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
443         while (--maxlen && isdigit(*str))
444                 str++;
445         return (*str == '\0');
446 }
447
448 static const char *
449 var_end(const char *var)
450 {
451         while (*var)
452                 if (*var++ == '=')
453                         break;
454         return var;
455 }
456
457
458 /* ============ Interrupts / exceptions */
459
460 static void exitshell(void) NORETURN;
461
462 /*
463  * These macros allow the user to suspend the handling of interrupt signals
464  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
465  * much more efficient and portable.  (But hacking the kernel is so much
466  * more fun than worrying about efficiency and portability. :-))
467  */
468 #if DEBUG_INTONOFF
469 # define INT_OFF do { \
470         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
471         suppress_int++; \
472         barrier(); \
473 } while (0)
474 #else
475 # define INT_OFF do { \
476         suppress_int++; \
477         barrier(); \
478 } while (0)
479 #endif
480
481 /*
482  * Called to raise an exception.  Since C doesn't include exceptions, we
483  * just do a longjmp to the exception handler.  The type of exception is
484  * stored in the global variable "exception_type".
485  */
486 static void raise_exception(int) NORETURN;
487 static void
488 raise_exception(int e)
489 {
490 #if DEBUG
491         if (exception_handler == NULL)
492                 abort();
493 #endif
494         INT_OFF;
495         exception_type = e;
496         longjmp(exception_handler->loc, 1);
497 }
498 #if DEBUG
499 #define raise_exception(e) do { \
500         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
501         raise_exception(e); \
502 } while (0)
503 #endif
504
505 /*
506  * Called when a SIGINT is received.  (If the user specifies
507  * that SIGINT is to be trapped or ignored using the trap builtin, then
508  * this routine is not called.)  Suppressint is nonzero when interrupts
509  * are held using the INT_OFF macro.  (The test for iflag is just
510  * defensive programming.)
511  */
512 static void raise_interrupt(void) NORETURN;
513 static void
514 raise_interrupt(void)
515 {
516         pending_int = 0;
517         /* Signal is not automatically unmasked after it is raised,
518          * do it ourself - unmask all signals */
519         sigprocmask_allsigs(SIG_UNBLOCK);
520         /* pending_sig = 0; - now done in signal_handler() */
521
522         if (!(rootshell && iflag)) {
523                 /* Kill ourself with SIGINT */
524                 signal(SIGINT, SIG_DFL);
525                 raise(SIGINT);
526         }
527         /* bash: ^C even on empty command line sets $? */
528         exitstatus = SIGINT + 128;
529         raise_exception(EXINT);
530         /* NOTREACHED */
531 }
532 #if DEBUG
533 #define raise_interrupt() do { \
534         TRACE(("raising interrupt on line %d\n", __LINE__)); \
535         raise_interrupt(); \
536 } while (0)
537 #endif
538
539 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
540 int_on(void)
541 {
542         barrier();
543         if (--suppress_int == 0 && pending_int) {
544                 raise_interrupt();
545         }
546 }
547 #if DEBUG_INTONOFF
548 # define INT_ON do { \
549         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
550         int_on(); \
551 } while (0)
552 #else
553 # define INT_ON int_on()
554 #endif
555 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
556 force_int_on(void)
557 {
558         barrier();
559         suppress_int = 0;
560         if (pending_int)
561                 raise_interrupt();
562 }
563 #define FORCE_INT_ON force_int_on()
564
565 #define SAVE_INT(v) ((v) = suppress_int)
566
567 #define RESTORE_INT(v) do { \
568         barrier(); \
569         suppress_int = (v); \
570         if (suppress_int == 0 && pending_int) \
571                 raise_interrupt(); \
572 } while (0)
573
574
575 /* ============ Stdout/stderr output */
576
577 static void
578 outstr(const char *p, FILE *file)
579 {
580         INT_OFF;
581         fputs(p, file);
582         INT_ON;
583 }
584
585 static void
586 flush_stdout_stderr(void)
587 {
588         INT_OFF;
589         fflush_all();
590         INT_ON;
591 }
592
593 /* Was called outcslow(c,FILE*), but c was always '\n' */
594 static void
595 newline_and_flush(FILE *dest)
596 {
597         INT_OFF;
598         putc('\n', dest);
599         fflush(dest);
600         INT_ON;
601 }
602
603 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
604 static int
605 out1fmt(const char *fmt, ...)
606 {
607         va_list ap;
608         int r;
609
610         INT_OFF;
611         va_start(ap, fmt);
612         r = vprintf(fmt, ap);
613         va_end(ap);
614         INT_ON;
615         return r;
616 }
617
618 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
619 static int
620 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
621 {
622         va_list ap;
623         int ret;
624
625         va_start(ap, fmt);
626         INT_OFF;
627         ret = vsnprintf(outbuf, length, fmt, ap);
628         va_end(ap);
629         INT_ON;
630         return ret;
631 }
632
633 static void
634 out1str(const char *p)
635 {
636         outstr(p, stdout);
637 }
638
639 static void
640 out2str(const char *p)
641 {
642         outstr(p, stderr);
643         flush_stdout_stderr();
644 }
645
646
647 /* ============ Parser structures */
648
649 /* control characters in argument strings */
650 #define CTL_FIRST CTLESC
651 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
652 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
653 #define CTLENDVAR    ((unsigned char)'\203')
654 #define CTLBACKQ     ((unsigned char)'\204')
655 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
656 #define CTLENDARI    ((unsigned char)'\207')
657 #define CTLQUOTEMARK ((unsigned char)'\210')
658 #define CTL_LAST CTLQUOTEMARK
659
660 /* variable substitution byte (follows CTLVAR) */
661 #define VSTYPE  0x0f            /* type of variable substitution */
662 #define VSNUL   0x10            /* colon--treat the empty string as unset */
663
664 /* values of VSTYPE field */
665 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
666 #define VSMINUS         0x2     /* ${var-text} */
667 #define VSPLUS          0x3     /* ${var+text} */
668 #define VSQUESTION      0x4     /* ${var?message} */
669 #define VSASSIGN        0x5     /* ${var=text} */
670 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
671 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
672 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
673 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
674 #define VSLENGTH        0xa     /* ${#var} */
675 #if BASH_SUBSTR
676 #define VSSUBSTR        0xc     /* ${var:position:length} */
677 #endif
678 #if BASH_PATTERN_SUBST
679 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
680 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
681 #endif
682
683 static const char dolatstr[] ALIGN1 = {
684         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
685 };
686 #define DOLATSTRLEN 6
687
688 #define NCMD      0
689 #define NPIPE     1
690 #define NREDIR    2
691 #define NBACKGND  3
692 #define NSUBSHELL 4
693 #define NAND      5
694 #define NOR       6
695 #define NSEMI     7
696 #define NIF       8
697 #define NWHILE    9
698 #define NUNTIL   10
699 #define NFOR     11
700 #define NCASE    12
701 #define NCLIST   13
702 #define NDEFUN   14
703 #define NARG     15
704 #define NTO      16
705 #if BASH_REDIR_OUTPUT
706 #define NTO2     17
707 #endif
708 #define NCLOBBER 18
709 #define NFROM    19
710 #define NFROMTO  20
711 #define NAPPEND  21
712 #define NTOFD    22
713 #define NFROMFD  23
714 #define NHERE    24
715 #define NXHERE   25
716 #define NNOT     26
717 #define N_NUMBER 27
718
719 union node;
720
721 struct ncmd {
722         smallint type; /* Nxxxx */
723         union node *assign;
724         union node *args;
725         union node *redirect;
726 };
727
728 struct npipe {
729         smallint type;
730         smallint pipe_backgnd;
731         struct nodelist *cmdlist;
732 };
733
734 struct nredir {
735         smallint type;
736         union node *n;
737         union node *redirect;
738 };
739
740 struct nbinary {
741         smallint type;
742         union node *ch1;
743         union node *ch2;
744 };
745
746 struct nif {
747         smallint type;
748         union node *test;
749         union node *ifpart;
750         union node *elsepart;
751 };
752
753 struct nfor {
754         smallint type;
755         union node *args;
756         union node *body;
757         char *var;
758 };
759
760 struct ncase {
761         smallint type;
762         union node *expr;
763         union node *cases;
764 };
765
766 struct nclist {
767         smallint type;
768         union node *next;
769         union node *pattern;
770         union node *body;
771 };
772
773 struct narg {
774         smallint type;
775         union node *next;
776         char *text;
777         struct nodelist *backquote;
778 };
779
780 /* nfile and ndup layout must match!
781  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
782  * that it is actually NTO2 (>&file), and change its type.
783  */
784 struct nfile {
785         smallint type;
786         union node *next;
787         int fd;
788         int _unused_dupfd;
789         union node *fname;
790         char *expfname;
791 };
792
793 struct ndup {
794         smallint type;
795         union node *next;
796         int fd;
797         int dupfd;
798         union node *vname;
799         char *_unused_expfname;
800 };
801
802 struct nhere {
803         smallint type;
804         union node *next;
805         int fd;
806         union node *doc;
807 };
808
809 struct nnot {
810         smallint type;
811         union node *com;
812 };
813
814 union node {
815         smallint type;
816         struct ncmd ncmd;
817         struct npipe npipe;
818         struct nredir nredir;
819         struct nbinary nbinary;
820         struct nif nif;
821         struct nfor nfor;
822         struct ncase ncase;
823         struct nclist nclist;
824         struct narg narg;
825         struct nfile nfile;
826         struct ndup ndup;
827         struct nhere nhere;
828         struct nnot nnot;
829 };
830
831 /*
832  * NODE_EOF is returned by parsecmd when it encounters an end of file.
833  * It must be distinct from NULL.
834  */
835 #define NODE_EOF ((union node *) -1L)
836
837 struct nodelist {
838         struct nodelist *next;
839         union node *n;
840 };
841
842 struct funcnode {
843         int count;
844         union node n;
845 };
846
847 /*
848  * Free a parse tree.
849  */
850 static void
851 freefunc(struct funcnode *f)
852 {
853         if (f && --f->count < 0)
854                 free(f);
855 }
856
857
858 /* ============ Debugging output */
859
860 #if DEBUG
861
862 static FILE *tracefile;
863
864 static void
865 trace_printf(const char *fmt, ...)
866 {
867         va_list va;
868
869         if (debug != 1)
870                 return;
871         if (DEBUG_TIME)
872                 fprintf(tracefile, "%u ", (int) time(NULL));
873         if (DEBUG_PID)
874                 fprintf(tracefile, "[%u] ", (int) getpid());
875         if (DEBUG_SIG)
876                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
877         va_start(va, fmt);
878         vfprintf(tracefile, fmt, va);
879         va_end(va);
880 }
881
882 static void
883 trace_vprintf(const char *fmt, va_list va)
884 {
885         if (debug != 1)
886                 return;
887         vfprintf(tracefile, fmt, va);
888         fprintf(tracefile, "\n");
889 }
890
891 static void
892 trace_puts(const char *s)
893 {
894         if (debug != 1)
895                 return;
896         fputs(s, tracefile);
897 }
898
899 static void
900 trace_puts_quoted(char *s)
901 {
902         char *p;
903         char c;
904
905         if (debug != 1)
906                 return;
907         putc('"', tracefile);
908         for (p = s; *p; p++) {
909                 switch ((unsigned char)*p) {
910                 case '\n': c = 'n'; goto backslash;
911                 case '\t': c = 't'; goto backslash;
912                 case '\r': c = 'r'; goto backslash;
913                 case '\"': c = '\"'; goto backslash;
914                 case '\\': c = '\\'; goto backslash;
915                 case CTLESC: c = 'e'; goto backslash;
916                 case CTLVAR: c = 'v'; goto backslash;
917                 case CTLBACKQ: c = 'q'; goto backslash;
918  backslash:
919                         putc('\\', tracefile);
920                         putc(c, tracefile);
921                         break;
922                 default:
923                         if (*p >= ' ' && *p <= '~')
924                                 putc(*p, tracefile);
925                         else {
926                                 putc('\\', tracefile);
927                                 putc((*p >> 6) & 03, tracefile);
928                                 putc((*p >> 3) & 07, tracefile);
929                                 putc(*p & 07, tracefile);
930                         }
931                         break;
932                 }
933         }
934         putc('"', tracefile);
935 }
936
937 static void
938 trace_puts_args(char **ap)
939 {
940         if (debug != 1)
941                 return;
942         if (!*ap)
943                 return;
944         while (1) {
945                 trace_puts_quoted(*ap);
946                 if (!*++ap) {
947                         putc('\n', tracefile);
948                         break;
949                 }
950                 putc(' ', tracefile);
951         }
952 }
953
954 static void
955 opentrace(void)
956 {
957         char s[100];
958 #ifdef O_APPEND
959         int flags;
960 #endif
961
962         if (debug != 1) {
963                 if (tracefile)
964                         fflush(tracefile);
965                 /* leave open because libedit might be using it */
966                 return;
967         }
968         strcpy(s, "./trace");
969         if (tracefile) {
970                 if (!freopen(s, "a", tracefile)) {
971                         fprintf(stderr, "Can't re-open %s\n", s);
972                         debug = 0;
973                         return;
974                 }
975         } else {
976                 tracefile = fopen(s, "a");
977                 if (tracefile == NULL) {
978                         fprintf(stderr, "Can't open %s\n", s);
979                         debug = 0;
980                         return;
981                 }
982         }
983 #ifdef O_APPEND
984         flags = fcntl(fileno(tracefile), F_GETFL);
985         if (flags >= 0)
986                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
987 #endif
988         setlinebuf(tracefile);
989         fputs("\nTracing started.\n", tracefile);
990 }
991
992 static void
993 indent(int amount, char *pfx, FILE *fp)
994 {
995         int i;
996
997         for (i = 0; i < amount; i++) {
998                 if (pfx && i == amount - 1)
999                         fputs(pfx, fp);
1000                 putc('\t', fp);
1001         }
1002 }
1003
1004 /* little circular references here... */
1005 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1006
1007 static void
1008 sharg(union node *arg, FILE *fp)
1009 {
1010         char *p;
1011         struct nodelist *bqlist;
1012         unsigned char subtype;
1013
1014         if (arg->type != NARG) {
1015                 out1fmt("<node type %d>\n", arg->type);
1016                 abort();
1017         }
1018         bqlist = arg->narg.backquote;
1019         for (p = arg->narg.text; *p; p++) {
1020                 switch ((unsigned char)*p) {
1021                 case CTLESC:
1022                         p++;
1023                         putc(*p, fp);
1024                         break;
1025                 case CTLVAR:
1026                         putc('$', fp);
1027                         putc('{', fp);
1028                         subtype = *++p;
1029                         if (subtype == VSLENGTH)
1030                                 putc('#', fp);
1031
1032                         while (*p != '=') {
1033                                 putc(*p, fp);
1034                                 p++;
1035                         }
1036
1037                         if (subtype & VSNUL)
1038                                 putc(':', fp);
1039
1040                         switch (subtype & VSTYPE) {
1041                         case VSNORMAL:
1042                                 putc('}', fp);
1043                                 break;
1044                         case VSMINUS:
1045                                 putc('-', fp);
1046                                 break;
1047                         case VSPLUS:
1048                                 putc('+', fp);
1049                                 break;
1050                         case VSQUESTION:
1051                                 putc('?', fp);
1052                                 break;
1053                         case VSASSIGN:
1054                                 putc('=', fp);
1055                                 break;
1056                         case VSTRIMLEFT:
1057                                 putc('#', fp);
1058                                 break;
1059                         case VSTRIMLEFTMAX:
1060                                 putc('#', fp);
1061                                 putc('#', fp);
1062                                 break;
1063                         case VSTRIMRIGHT:
1064                                 putc('%', fp);
1065                                 break;
1066                         case VSTRIMRIGHTMAX:
1067                                 putc('%', fp);
1068                                 putc('%', fp);
1069                                 break;
1070                         case VSLENGTH:
1071                                 break;
1072                         default:
1073                                 out1fmt("<subtype %d>", subtype);
1074                         }
1075                         break;
1076                 case CTLENDVAR:
1077                         putc('}', fp);
1078                         break;
1079                 case CTLBACKQ:
1080                         putc('$', fp);
1081                         putc('(', fp);
1082                         shtree(bqlist->n, -1, NULL, fp);
1083                         putc(')', fp);
1084                         break;
1085                 default:
1086                         putc(*p, fp);
1087                         break;
1088                 }
1089         }
1090 }
1091
1092 static void
1093 shcmd(union node *cmd, FILE *fp)
1094 {
1095         union node *np;
1096         int first;
1097         const char *s;
1098         int dftfd;
1099
1100         first = 1;
1101         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1102                 if (!first)
1103                         putc(' ', fp);
1104                 sharg(np, fp);
1105                 first = 0;
1106         }
1107         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1108                 if (!first)
1109                         putc(' ', fp);
1110                 dftfd = 0;
1111                 switch (np->nfile.type) {
1112                 case NTO:      s = ">>"+1; dftfd = 1; break;
1113                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1114                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1115 #if BASH_REDIR_OUTPUT
1116                 case NTO2:
1117 #endif
1118                 case NTOFD:    s = ">&"; dftfd = 1; break;
1119                 case NFROM:    s = "<"; break;
1120                 case NFROMFD:  s = "<&"; break;
1121                 case NFROMTO:  s = "<>"; break;
1122                 default:       s = "*error*"; break;
1123                 }
1124                 if (np->nfile.fd != dftfd)
1125                         fprintf(fp, "%d", np->nfile.fd);
1126                 fputs(s, fp);
1127                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1128                         fprintf(fp, "%d", np->ndup.dupfd);
1129                 } else {
1130                         sharg(np->nfile.fname, fp);
1131                 }
1132                 first = 0;
1133         }
1134 }
1135
1136 static void
1137 shtree(union node *n, int ind, char *pfx, FILE *fp)
1138 {
1139         struct nodelist *lp;
1140         const char *s;
1141
1142         if (n == NULL)
1143                 return;
1144
1145         indent(ind, pfx, fp);
1146
1147         if (n == NODE_EOF) {
1148                 fputs("<EOF>", fp);
1149                 return;
1150         }
1151
1152         switch (n->type) {
1153         case NSEMI:
1154                 s = "; ";
1155                 goto binop;
1156         case NAND:
1157                 s = " && ";
1158                 goto binop;
1159         case NOR:
1160                 s = " || ";
1161  binop:
1162                 shtree(n->nbinary.ch1, ind, NULL, fp);
1163                 /* if (ind < 0) */
1164                         fputs(s, fp);
1165                 shtree(n->nbinary.ch2, ind, NULL, fp);
1166                 break;
1167         case NCMD:
1168                 shcmd(n, fp);
1169                 if (ind >= 0)
1170                         putc('\n', fp);
1171                 break;
1172         case NPIPE:
1173                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1174                         shtree(lp->n, 0, NULL, fp);
1175                         if (lp->next)
1176                                 fputs(" | ", fp);
1177                 }
1178                 if (n->npipe.pipe_backgnd)
1179                         fputs(" &", fp);
1180                 if (ind >= 0)
1181                         putc('\n', fp);
1182                 break;
1183         default:
1184                 fprintf(fp, "<node type %d>", n->type);
1185                 if (ind >= 0)
1186                         putc('\n', fp);
1187                 break;
1188         }
1189 }
1190
1191 static void
1192 showtree(union node *n)
1193 {
1194         trace_puts("showtree called\n");
1195         shtree(n, 1, NULL, stderr);
1196 }
1197
1198 #endif /* DEBUG */
1199
1200
1201 /* ============ Parser data */
1202
1203 /*
1204  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1205  */
1206 struct strlist {
1207         struct strlist *next;
1208         char *text;
1209 };
1210
1211 struct alias;
1212
1213 struct strpush {
1214         struct strpush *prev;   /* preceding string on stack */
1215         char *prev_string;
1216         int prev_left_in_line;
1217 #if ENABLE_ASH_ALIAS
1218         struct alias *ap;       /* if push was associated with an alias */
1219 #endif
1220         char *string;           /* remember the string since it may change */
1221
1222         /* Remember last two characters for pungetc. */
1223         int lastc[2];
1224
1225         /* Number of outstanding calls to pungetc. */
1226         int unget;
1227 };
1228
1229 struct parsefile {
1230         struct parsefile *prev; /* preceding file on stack */
1231         int linno;              /* current line */
1232         int pf_fd;              /* file descriptor (or -1 if string) */
1233         int left_in_line;       /* number of chars left in this line */
1234         int left_in_buffer;     /* number of chars left in this buffer past the line */
1235         char *next_to_pgetc;    /* next char in buffer */
1236         char *buf;              /* input buffer */
1237         struct strpush *strpush; /* for pushing strings at this level */
1238         struct strpush basestrpush; /* so pushing one is fast */
1239
1240         /* Remember last two characters for pungetc. */
1241         int lastc[2];
1242
1243         /* Number of outstanding calls to pungetc. */
1244         int unget;
1245 };
1246
1247 static struct parsefile basepf;        /* top level input file */
1248 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1249 static int startlinno;                 /* line # where last token started */
1250 static char *commandname;              /* currently executing command */
1251 static struct strlist *cmdenviron;     /* environment for builtin command */
1252
1253
1254 /* ============ Message printing */
1255
1256 static void
1257 ash_vmsg(const char *msg, va_list ap)
1258 {
1259         fprintf(stderr, "%s: ", arg0);
1260         if (commandname) {
1261                 if (strcmp(arg0, commandname))
1262                         fprintf(stderr, "%s: ", commandname);
1263                 if (!iflag || g_parsefile->pf_fd > 0)
1264                         fprintf(stderr, "line %d: ", startlinno);
1265         }
1266         vfprintf(stderr, msg, ap);
1267         newline_and_flush(stderr);
1268 }
1269
1270 /*
1271  * Exverror is called to raise the error exception.  If the second argument
1272  * is not NULL then error prints an error message using printf style
1273  * formatting.  It then raises the error exception.
1274  */
1275 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1276 static void
1277 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1278 {
1279 #if DEBUG
1280         if (msg) {
1281                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1282                 TRACEV((msg, ap));
1283         } else
1284                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1285         if (msg)
1286 #endif
1287                 ash_vmsg(msg, ap);
1288
1289         flush_stdout_stderr();
1290         raise_exception(cond);
1291         /* NOTREACHED */
1292 }
1293
1294 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1295 static void
1296 ash_msg_and_raise_error(const char *msg, ...)
1297 {
1298         va_list ap;
1299
1300         exitstatus = 2;
1301
1302         va_start(ap, msg);
1303         ash_vmsg_and_raise(EXERROR, msg, ap);
1304         /* NOTREACHED */
1305         va_end(ap);
1306 }
1307
1308 static void raise_error_syntax(const char *) NORETURN;
1309 static void
1310 raise_error_syntax(const char *msg)
1311 {
1312         ash_msg_and_raise_error("syntax error: %s", msg);
1313         /* NOTREACHED */
1314 }
1315
1316 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1317 static void
1318 ash_msg_and_raise(int cond, const char *msg, ...)
1319 {
1320         va_list ap;
1321
1322         va_start(ap, msg);
1323         ash_vmsg_and_raise(cond, msg, ap);
1324         /* NOTREACHED */
1325         va_end(ap);
1326 }
1327
1328 /*
1329  * error/warning routines for external builtins
1330  */
1331 static void
1332 ash_msg(const char *fmt, ...)
1333 {
1334         va_list ap;
1335
1336         va_start(ap, fmt);
1337         ash_vmsg(fmt, ap);
1338         va_end(ap);
1339 }
1340
1341 /*
1342  * Return a string describing an error.  The returned string may be a
1343  * pointer to a static buffer that will be overwritten on the next call.
1344  * Action describes the operation that got the error.
1345  */
1346 static const char *
1347 errmsg(int e, const char *em)
1348 {
1349         if (e == ENOENT || e == ENOTDIR) {
1350                 return em;
1351         }
1352         return strerror(e);
1353 }
1354
1355
1356 /* ============ Memory allocation */
1357
1358 #if 0
1359 /* I consider these wrappers nearly useless:
1360  * ok, they return you to nearest exception handler, but
1361  * how much memory do you leak in the process, making
1362  * memory starvation worse?
1363  */
1364 static void *
1365 ckrealloc(void * p, size_t nbytes)
1366 {
1367         p = realloc(p, nbytes);
1368         if (!p)
1369                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1370         return p;
1371 }
1372
1373 static void *
1374 ckmalloc(size_t nbytes)
1375 {
1376         return ckrealloc(NULL, nbytes);
1377 }
1378
1379 static void *
1380 ckzalloc(size_t nbytes)
1381 {
1382         return memset(ckmalloc(nbytes), 0, nbytes);
1383 }
1384
1385 static char *
1386 ckstrdup(const char *s)
1387 {
1388         char *p = strdup(s);
1389         if (!p)
1390                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1391         return p;
1392 }
1393 #else
1394 /* Using bbox equivalents. They exit if out of memory */
1395 # define ckrealloc xrealloc
1396 # define ckmalloc  xmalloc
1397 # define ckzalloc  xzalloc
1398 # define ckstrdup  xstrdup
1399 #endif
1400
1401 /*
1402  * It appears that grabstackstr() will barf with such alignments
1403  * because stalloc() will return a string allocated in a new stackblock.
1404  */
1405 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1406 enum {
1407         /* Most machines require the value returned from malloc to be aligned
1408          * in some way.  The following macro will get this right
1409          * on many machines.  */
1410         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1411         /* Minimum size of a block */
1412         MINSIZE = SHELL_ALIGN(504),
1413 };
1414
1415 struct stack_block {
1416         struct stack_block *prev;
1417         char space[MINSIZE];
1418 };
1419
1420 struct stackmark {
1421         struct stack_block *stackp;
1422         char *stacknxt;
1423         size_t stacknleft;
1424 };
1425
1426
1427 struct globals_memstack {
1428         struct stack_block *g_stackp; // = &stackbase;
1429         char *g_stacknxt; // = stackbase.space;
1430         char *sstrend; // = stackbase.space + MINSIZE;
1431         size_t g_stacknleft; // = MINSIZE;
1432         struct stack_block stackbase;
1433 };
1434 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1435 #define G_memstack (*ash_ptr_to_globals_memstack)
1436 #define g_stackp     (G_memstack.g_stackp    )
1437 #define g_stacknxt   (G_memstack.g_stacknxt  )
1438 #define sstrend      (G_memstack.sstrend     )
1439 #define g_stacknleft (G_memstack.g_stacknleft)
1440 #define stackbase    (G_memstack.stackbase   )
1441 #define INIT_G_memstack() do { \
1442         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1443         barrier(); \
1444         g_stackp = &stackbase; \
1445         g_stacknxt = stackbase.space; \
1446         g_stacknleft = MINSIZE; \
1447         sstrend = stackbase.space + MINSIZE; \
1448 } while (0)
1449
1450
1451 #define stackblock()     ((void *)g_stacknxt)
1452 #define stackblocksize() g_stacknleft
1453
1454 /*
1455  * Parse trees for commands are allocated in lifo order, so we use a stack
1456  * to make this more efficient, and also to avoid all sorts of exception
1457  * handling code to handle interrupts in the middle of a parse.
1458  *
1459  * The size 504 was chosen because the Ultrix malloc handles that size
1460  * well.
1461  */
1462 static void *
1463 stalloc(size_t nbytes)
1464 {
1465         char *p;
1466         size_t aligned;
1467
1468         aligned = SHELL_ALIGN(nbytes);
1469         if (aligned > g_stacknleft) {
1470                 size_t len;
1471                 size_t blocksize;
1472                 struct stack_block *sp;
1473
1474                 blocksize = aligned;
1475                 if (blocksize < MINSIZE)
1476                         blocksize = MINSIZE;
1477                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1478                 if (len < blocksize)
1479                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1480                 INT_OFF;
1481                 sp = ckmalloc(len);
1482                 sp->prev = g_stackp;
1483                 g_stacknxt = sp->space;
1484                 g_stacknleft = blocksize;
1485                 sstrend = g_stacknxt + blocksize;
1486                 g_stackp = sp;
1487                 INT_ON;
1488         }
1489         p = g_stacknxt;
1490         g_stacknxt += aligned;
1491         g_stacknleft -= aligned;
1492         return p;
1493 }
1494
1495 static void *
1496 stzalloc(size_t nbytes)
1497 {
1498         return memset(stalloc(nbytes), 0, nbytes);
1499 }
1500
1501 static void
1502 stunalloc(void *p)
1503 {
1504 #if DEBUG
1505         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1506                 write(STDERR_FILENO, "stunalloc\n", 10);
1507                 abort();
1508         }
1509 #endif
1510         g_stacknleft += g_stacknxt - (char *)p;
1511         g_stacknxt = p;
1512 }
1513
1514 /*
1515  * Like strdup but works with the ash stack.
1516  */
1517 static char *
1518 sstrdup(const char *p)
1519 {
1520         size_t len = strlen(p) + 1;
1521         return memcpy(stalloc(len), p, len);
1522 }
1523
1524 static inline void
1525 grabstackblock(size_t len)
1526 {
1527         stalloc(len);
1528 }
1529
1530 static void
1531 pushstackmark(struct stackmark *mark, size_t len)
1532 {
1533         mark->stackp = g_stackp;
1534         mark->stacknxt = g_stacknxt;
1535         mark->stacknleft = g_stacknleft;
1536         grabstackblock(len);
1537 }
1538
1539 static void
1540 setstackmark(struct stackmark *mark)
1541 {
1542         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1543 }
1544
1545 static void
1546 popstackmark(struct stackmark *mark)
1547 {
1548         struct stack_block *sp;
1549
1550         if (!mark->stackp)
1551                 return;
1552
1553         INT_OFF;
1554         while (g_stackp != mark->stackp) {
1555                 sp = g_stackp;
1556                 g_stackp = sp->prev;
1557                 free(sp);
1558         }
1559         g_stacknxt = mark->stacknxt;
1560         g_stacknleft = mark->stacknleft;
1561         sstrend = mark->stacknxt + mark->stacknleft;
1562         INT_ON;
1563 }
1564
1565 /*
1566  * When the parser reads in a string, it wants to stick the string on the
1567  * stack and only adjust the stack pointer when it knows how big the
1568  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1569  * of space on top of the stack and stackblocklen returns the length of
1570  * this block.  Growstackblock will grow this space by at least one byte,
1571  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1572  * part of the block that has been used.
1573  */
1574 static void
1575 growstackblock(void)
1576 {
1577         size_t newlen;
1578
1579         newlen = g_stacknleft * 2;
1580         if (newlen < g_stacknleft)
1581                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1582         if (newlen < 128)
1583                 newlen += 128;
1584
1585         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1586                 struct stack_block *sp;
1587                 struct stack_block *prevstackp;
1588                 size_t grosslen;
1589
1590                 INT_OFF;
1591                 sp = g_stackp;
1592                 prevstackp = sp->prev;
1593                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1594                 sp = ckrealloc(sp, grosslen);
1595                 sp->prev = prevstackp;
1596                 g_stackp = sp;
1597                 g_stacknxt = sp->space;
1598                 g_stacknleft = newlen;
1599                 sstrend = sp->space + newlen;
1600                 INT_ON;
1601         } else {
1602                 char *oldspace = g_stacknxt;
1603                 size_t oldlen = g_stacknleft;
1604                 char *p = stalloc(newlen);
1605
1606                 /* free the space we just allocated */
1607                 g_stacknxt = memcpy(p, oldspace, oldlen);
1608                 g_stacknleft += newlen;
1609         }
1610 }
1611
1612 /*
1613  * The following routines are somewhat easier to use than the above.
1614  * The user declares a variable of type STACKSTR, which may be declared
1615  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1616  * the user uses the macro STPUTC to add characters to the string.  In
1617  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1618  * grown as necessary.  When the user is done, she can just leave the
1619  * string there and refer to it using stackblock().  Or she can allocate
1620  * the space for it using grabstackstr().  If it is necessary to allow
1621  * someone else to use the stack temporarily and then continue to grow
1622  * the string, the user should use grabstack to allocate the space, and
1623  * then call ungrabstr(p) to return to the previous mode of operation.
1624  *
1625  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1626  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1627  * is space for at least one character.
1628  */
1629 static void *
1630 growstackstr(void)
1631 {
1632         size_t len = stackblocksize();
1633         growstackblock();
1634         return (char *)stackblock() + len;
1635 }
1636
1637 /*
1638  * Called from CHECKSTRSPACE.
1639  */
1640 static char *
1641 makestrspace(size_t newlen, char *p)
1642 {
1643         size_t len = p - g_stacknxt;
1644         size_t size;
1645
1646         for (;;) {
1647                 size_t nleft;
1648
1649                 size = stackblocksize();
1650                 nleft = size - len;
1651                 if (nleft >= newlen)
1652                         break;
1653                 growstackblock();
1654         }
1655         return (char *)stackblock() + len;
1656 }
1657
1658 static char *
1659 stack_nputstr(const char *s, size_t n, char *p)
1660 {
1661         p = makestrspace(n, p);
1662         p = (char *)memcpy(p, s, n) + n;
1663         return p;
1664 }
1665
1666 static char *
1667 stack_putstr(const char *s, char *p)
1668 {
1669         return stack_nputstr(s, strlen(s), p);
1670 }
1671
1672 static char *
1673 _STPUTC(int c, char *p)
1674 {
1675         if (p == sstrend)
1676                 p = growstackstr();
1677         *p++ = c;
1678         return p;
1679 }
1680
1681 #define STARTSTACKSTR(p)        ((p) = stackblock())
1682 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1683 #define CHECKSTRSPACE(n, p) do { \
1684         char *q = (p); \
1685         size_t l = (n); \
1686         size_t m = sstrend - q; \
1687         if (l > m) \
1688                 (p) = makestrspace(l, q); \
1689 } while (0)
1690 #define USTPUTC(c, p)           (*(p)++ = (c))
1691 #define STACKSTRNUL(p) do { \
1692         if ((p) == sstrend) \
1693                 (p) = growstackstr(); \
1694         *(p) = '\0'; \
1695 } while (0)
1696 #define STUNPUTC(p)             (--(p))
1697 #define STTOPC(p)               ((p)[-1])
1698 #define STADJUST(amount, p)     ((p) += (amount))
1699
1700 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1701 #define ungrabstackstr(s, p)    stunalloc(s)
1702 #define stackstrend()           ((void *)sstrend)
1703
1704
1705 /* ============ String helpers */
1706
1707 /*
1708  * prefix -- see if pfx is a prefix of string.
1709  */
1710 static char *
1711 prefix(const char *string, const char *pfx)
1712 {
1713         while (*pfx) {
1714                 if (*pfx++ != *string++)
1715                         return NULL;
1716         }
1717         return (char *) string;
1718 }
1719
1720 /*
1721  * Check for a valid number.  This should be elsewhere.
1722  */
1723 static int
1724 is_number(const char *p)
1725 {
1726         do {
1727                 if (!isdigit(*p))
1728                         return 0;
1729         } while (*++p != '\0');
1730         return 1;
1731 }
1732
1733 /*
1734  * Convert a string of digits to an integer, printing an error message on
1735  * failure.
1736  */
1737 static int
1738 number(const char *s)
1739 {
1740         if (!is_number(s))
1741                 ash_msg_and_raise_error(msg_illnum, s);
1742         return atoi(s);
1743 }
1744
1745 /*
1746  * Produce a possibly single quoted string suitable as input to the shell.
1747  * The return string is allocated on the stack.
1748  */
1749 static char *
1750 single_quote(const char *s)
1751 {
1752         char *p;
1753
1754         STARTSTACKSTR(p);
1755
1756         do {
1757                 char *q;
1758                 size_t len;
1759
1760                 len = strchrnul(s, '\'') - s;
1761
1762                 q = p = makestrspace(len + 3, p);
1763
1764                 *q++ = '\'';
1765                 q = (char *)memcpy(q, s, len) + len;
1766                 *q++ = '\'';
1767                 s += len;
1768
1769                 STADJUST(q - p, p);
1770
1771                 if (*s != '\'')
1772                         break;
1773                 len = 0;
1774                 do len++; while (*++s == '\'');
1775
1776                 q = p = makestrspace(len + 3, p);
1777
1778                 *q++ = '"';
1779                 q = (char *)memcpy(q, s - len, len) + len;
1780                 *q++ = '"';
1781
1782                 STADJUST(q - p, p);
1783         } while (*s);
1784
1785         USTPUTC('\0', p);
1786
1787         return stackblock();
1788 }
1789
1790
1791 /* ============ nextopt */
1792
1793 static char **argptr;                  /* argument list for builtin commands */
1794 static char *optionarg;                /* set by nextopt (like getopt) */
1795 static char *optptr;                   /* used by nextopt */
1796
1797 /*
1798  * XXX - should get rid of. Have all builtins use getopt(3).
1799  * The library getopt must have the BSD extension static variable
1800  * "optreset", otherwise it can't be used within the shell safely.
1801  *
1802  * Standard option processing (a la getopt) for builtin routines.
1803  * The only argument that is passed to nextopt is the option string;
1804  * the other arguments are unnecessary. It returns the character,
1805  * or '\0' on end of input.
1806  */
1807 static int
1808 nextopt(const char *optstring)
1809 {
1810         char *p;
1811         const char *q;
1812         char c;
1813
1814         p = optptr;
1815         if (p == NULL || *p == '\0') {
1816                 /* We ate entire "-param", take next one */
1817                 p = *argptr;
1818                 if (p == NULL)
1819                         return '\0';
1820                 if (*p != '-')
1821                         return '\0';
1822                 if (*++p == '\0') /* just "-" ? */
1823                         return '\0';
1824                 argptr++;
1825                 if (LONE_DASH(p)) /* "--" ? */
1826                         return '\0';
1827                 /* p => next "-param" */
1828         }
1829         /* p => some option char in the middle of a "-param" */
1830         c = *p++;
1831         for (q = optstring; *q != c;) {
1832                 if (*q == '\0')
1833                         ash_msg_and_raise_error("illegal option -%c", c);
1834                 if (*++q == ':')
1835                         q++;
1836         }
1837         if (*++q == ':') {
1838                 if (*p == '\0') {
1839                         p = *argptr++;
1840                         if (p == NULL)
1841                                 ash_msg_and_raise_error("no arg for -%c option", c);
1842                 }
1843                 optionarg = p;
1844                 p = NULL;
1845         }
1846         optptr = p;
1847         return c;
1848 }
1849
1850
1851 /* ============ Shell variables */
1852
1853 /*
1854  * The parsefile structure pointed to by the global variable parsefile
1855  * contains information about the current file being read.
1856  */
1857 struct shparam {
1858         int nparam;             /* # of positional parameters (without $0) */
1859 #if ENABLE_ASH_GETOPTS
1860         int optind;             /* next parameter to be processed by getopts */
1861         int optoff;             /* used by getopts */
1862 #endif
1863         unsigned char malloced; /* if parameter list dynamically allocated */
1864         char **p;               /* parameter list */
1865 };
1866
1867 /*
1868  * Free the list of positional parameters.
1869  */
1870 static void
1871 freeparam(volatile struct shparam *param)
1872 {
1873         if (param->malloced) {
1874                 char **ap, **ap1;
1875                 ap = ap1 = param->p;
1876                 while (*ap)
1877                         free(*ap++);
1878                 free(ap1);
1879         }
1880 }
1881
1882 #if ENABLE_ASH_GETOPTS
1883 static void FAST_FUNC getoptsreset(const char *value);
1884 #endif
1885
1886 struct var {
1887         struct var *next;               /* next entry in hash list */
1888         int flags;                      /* flags are defined above */
1889         const char *var_text;           /* name=value */
1890         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1891                                         /* the variable gets set/unset */
1892 };
1893
1894 struct localvar {
1895         struct localvar *next;          /* next local variable in list */
1896         struct var *vp;                 /* the variable that was made local */
1897         int flags;                      /* saved flags */
1898         const char *text;               /* saved text */
1899 };
1900
1901 /* flags */
1902 #define VEXPORT         0x01    /* variable is exported */
1903 #define VREADONLY       0x02    /* variable cannot be modified */
1904 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1905 #define VTEXTFIXED      0x08    /* text is statically allocated */
1906 #define VSTACK          0x10    /* text is allocated on the stack */
1907 #define VUNSET          0x20    /* the variable is not set */
1908 #define VNOFUNC         0x40    /* don't call the callback function */
1909 #define VNOSET          0x80    /* do not set variable - just readonly test */
1910 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1911 #if ENABLE_ASH_RANDOM_SUPPORT
1912 # define VDYNAMIC       0x200   /* dynamic variable */
1913 #else
1914 # define VDYNAMIC       0
1915 #endif
1916
1917
1918 /* Need to be before varinit_data[] */
1919 #if ENABLE_LOCALE_SUPPORT
1920 static void FAST_FUNC
1921 change_lc_all(const char *value)
1922 {
1923         if (value && *value != '\0')
1924                 setlocale(LC_ALL, value);
1925 }
1926 static void FAST_FUNC
1927 change_lc_ctype(const char *value)
1928 {
1929         if (value && *value != '\0')
1930                 setlocale(LC_CTYPE, value);
1931 }
1932 #endif
1933 #if ENABLE_ASH_MAIL
1934 static void chkmail(void);
1935 static void changemail(const char *var_value) FAST_FUNC;
1936 #else
1937 # define chkmail()  ((void)0)
1938 #endif
1939 static void changepath(const char *) FAST_FUNC;
1940 #if ENABLE_ASH_RANDOM_SUPPORT
1941 static void change_random(const char *) FAST_FUNC;
1942 #endif
1943
1944 static const struct {
1945         int flags;
1946         const char *var_text;
1947         void (*var_func)(const char *) FAST_FUNC;
1948 } varinit_data[] = {
1949         /*
1950          * Note: VEXPORT would not work correctly here for NOFORK applets:
1951          * some environment strings may be constant.
1952          */
1953         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1954 #if ENABLE_ASH_MAIL
1955         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1956         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1957 #endif
1958         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1959         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1960         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1961         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1962 #if ENABLE_ASH_GETOPTS
1963         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
1964 #endif
1965 #if ENABLE_ASH_RANDOM_SUPPORT
1966         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
1967 #endif
1968 #if ENABLE_LOCALE_SUPPORT
1969         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
1970         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
1971 #endif
1972 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1973         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
1974 #endif
1975 };
1976
1977 struct redirtab;
1978
1979 struct globals_var {
1980         struct shparam shellparam;      /* $@ current positional parameters */
1981         struct redirtab *redirlist;
1982         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
1983         struct var *vartab[VTABSIZE];
1984         struct var varinit[ARRAY_SIZE(varinit_data)];
1985 };
1986 extern struct globals_var *const ash_ptr_to_globals_var;
1987 #define G_var (*ash_ptr_to_globals_var)
1988 #define shellparam    (G_var.shellparam   )
1989 //#define redirlist     (G_var.redirlist    )
1990 #define preverrout_fd (G_var.preverrout_fd)
1991 #define vartab        (G_var.vartab       )
1992 #define varinit       (G_var.varinit      )
1993 #define INIT_G_var() do { \
1994         unsigned i; \
1995         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1996         barrier(); \
1997         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1998                 varinit[i].flags    = varinit_data[i].flags; \
1999                 varinit[i].var_text = varinit_data[i].var_text; \
2000                 varinit[i].var_func = varinit_data[i].var_func; \
2001         } \
2002 } while (0)
2003
2004 #define vifs      varinit[0]
2005 #if ENABLE_ASH_MAIL
2006 # define vmail    (&vifs)[1]
2007 # define vmpath   (&vmail)[1]
2008 # define vpath    (&vmpath)[1]
2009 #else
2010 # define vpath    (&vifs)[1]
2011 #endif
2012 #define vps1      (&vpath)[1]
2013 #define vps2      (&vps1)[1]
2014 #define vps4      (&vps2)[1]
2015 #if ENABLE_ASH_GETOPTS
2016 # define voptind  (&vps4)[1]
2017 # if ENABLE_ASH_RANDOM_SUPPORT
2018 #  define vrandom (&voptind)[1]
2019 # endif
2020 #else
2021 # if ENABLE_ASH_RANDOM_SUPPORT
2022 #  define vrandom (&vps4)[1]
2023 # endif
2024 #endif
2025
2026 /*
2027  * The following macros access the values of the above variables.
2028  * They have to skip over the name.  They return the null string
2029  * for unset variables.
2030  */
2031 #define ifsval()        (vifs.var_text + 4)
2032 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2033 #if ENABLE_ASH_MAIL
2034 # define mailval()      (vmail.var_text + 5)
2035 # define mpathval()     (vmpath.var_text + 9)
2036 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2037 #endif
2038 #define pathval()       (vpath.var_text + 5)
2039 #define ps1val()        (vps1.var_text + 4)
2040 #define ps2val()        (vps2.var_text + 4)
2041 #define ps4val()        (vps4.var_text + 4)
2042 #if ENABLE_ASH_GETOPTS
2043 # define optindval()    (voptind.var_text + 7)
2044 #endif
2045
2046 #if ENABLE_ASH_GETOPTS
2047 static void FAST_FUNC
2048 getoptsreset(const char *value)
2049 {
2050         shellparam.optind = number(value) ?: 1;
2051         shellparam.optoff = -1;
2052 }
2053 #endif
2054
2055 /*
2056  * Compares two strings up to the first = or '\0'.  The first
2057  * string must be terminated by '='; the second may be terminated by
2058  * either '=' or '\0'.
2059  */
2060 static int
2061 varcmp(const char *p, const char *q)
2062 {
2063         int c, d;
2064
2065         while ((c = *p) == (d = *q)) {
2066                 if (c == '\0' || c == '=')
2067                         goto out;
2068                 p++;
2069                 q++;
2070         }
2071         if (c == '=')
2072                 c = '\0';
2073         if (d == '=')
2074                 d = '\0';
2075  out:
2076         return c - d;
2077 }
2078
2079 /*
2080  * Find the appropriate entry in the hash table from the name.
2081  */
2082 static struct var **
2083 hashvar(const char *p)
2084 {
2085         unsigned hashval;
2086
2087         hashval = ((unsigned char) *p) << 4;
2088         while (*p && *p != '=')
2089                 hashval += (unsigned char) *p++;
2090         return &vartab[hashval % VTABSIZE];
2091 }
2092
2093 static int
2094 vpcmp(const void *a, const void *b)
2095 {
2096         return varcmp(*(const char **)a, *(const char **)b);
2097 }
2098
2099 /*
2100  * This routine initializes the builtin variables.
2101  */
2102 static void
2103 initvar(void)
2104 {
2105         struct var *vp;
2106         struct var *end;
2107         struct var **vpp;
2108
2109         /*
2110          * PS1 depends on uid
2111          */
2112 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2113         vps1.var_text = "PS1=\\w \\$ ";
2114 #else
2115         if (!geteuid())
2116                 vps1.var_text = "PS1=# ";
2117 #endif
2118         vp = varinit;
2119         end = vp + ARRAY_SIZE(varinit);
2120         do {
2121                 vpp = hashvar(vp->var_text);
2122                 vp->next = *vpp;
2123                 *vpp = vp;
2124         } while (++vp < end);
2125 }
2126
2127 static struct var **
2128 findvar(struct var **vpp, const char *name)
2129 {
2130         for (; *vpp; vpp = &(*vpp)->next) {
2131                 if (varcmp((*vpp)->var_text, name) == 0) {
2132                         break;
2133                 }
2134         }
2135         return vpp;
2136 }
2137
2138 /*
2139  * Find the value of a variable.  Returns NULL if not set.
2140  */
2141 static const char* FAST_FUNC
2142 lookupvar(const char *name)
2143 {
2144         struct var *v;
2145
2146         v = *findvar(hashvar(name), name);
2147         if (v) {
2148 #if ENABLE_ASH_RANDOM_SUPPORT
2149         /*
2150          * Dynamic variables are implemented roughly the same way they are
2151          * in bash. Namely, they're "special" so long as they aren't unset.
2152          * As soon as they're unset, they're no longer dynamic, and dynamic
2153          * lookup will no longer happen at that point. -- PFM.
2154          */
2155                 if (v->flags & VDYNAMIC)
2156                         v->var_func(NULL);
2157 #endif
2158                 if (!(v->flags & VUNSET))
2159                         return var_end(v->var_text);
2160         }
2161         return NULL;
2162 }
2163
2164 #if ENABLE_UNICODE_SUPPORT
2165 static void
2166 reinit_unicode_for_ash(void)
2167 {
2168         /* Unicode support should be activated even if LANG is set
2169          * _during_ shell execution, not only if it was set when
2170          * shell was started. Therefore, re-check LANG every time:
2171          */
2172         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2173          || ENABLE_UNICODE_USING_LOCALE
2174         ) {
2175                 const char *s = lookupvar("LC_ALL");
2176                 if (!s) s = lookupvar("LC_CTYPE");
2177                 if (!s) s = lookupvar("LANG");
2178                 reinit_unicode(s);
2179         }
2180 }
2181 #else
2182 # define reinit_unicode_for_ash() ((void)0)
2183 #endif
2184
2185 /*
2186  * Search the environment of a builtin command.
2187  */
2188 static const char *
2189 bltinlookup(const char *name)
2190 {
2191         struct strlist *sp;
2192
2193         for (sp = cmdenviron; sp; sp = sp->next) {
2194                 if (varcmp(sp->text, name) == 0)
2195                         return var_end(sp->text);
2196         }
2197         return lookupvar(name);
2198 }
2199
2200 /*
2201  * Same as setvar except that the variable and value are passed in
2202  * the first argument as name=value.  Since the first argument will
2203  * be actually stored in the table, it should not be a string that
2204  * will go away.
2205  * Called with interrupts off.
2206  */
2207 static void
2208 setvareq(char *s, int flags)
2209 {
2210         struct var *vp, **vpp;
2211
2212         vpp = hashvar(s);
2213         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2214         vp = *findvar(vpp, s);
2215         if (vp) {
2216                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2217                         const char *n;
2218
2219                         if (flags & VNOSAVE)
2220                                 free(s);
2221                         n = vp->var_text;
2222                         exitstatus = 1;
2223                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2224                 }
2225
2226                 if (flags & VNOSET)
2227                         return;
2228
2229                 if (vp->var_func && !(flags & VNOFUNC))
2230                         vp->var_func(var_end(s));
2231
2232                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2233                         free((char*)vp->var_text);
2234
2235                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2236         } else {
2237                 /* variable s is not found */
2238                 if (flags & VNOSET)
2239                         return;
2240                 vp = ckzalloc(sizeof(*vp));
2241                 vp->next = *vpp;
2242                 /*vp->func = NULL; - ckzalloc did it */
2243                 *vpp = vp;
2244         }
2245         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2246                 s = ckstrdup(s);
2247         vp->var_text = s;
2248         vp->flags = flags;
2249 }
2250
2251 /*
2252  * Set the value of a variable.  The flags argument is ored with the
2253  * flags of the variable.  If val is NULL, the variable is unset.
2254  */
2255 static void
2256 setvar(const char *name, const char *val, int flags)
2257 {
2258         const char *q;
2259         char *p;
2260         char *nameeq;
2261         size_t namelen;
2262         size_t vallen;
2263
2264         q = endofname(name);
2265         p = strchrnul(q, '=');
2266         namelen = p - name;
2267         if (!namelen || p != q)
2268                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2269         vallen = 0;
2270         if (val == NULL) {
2271                 flags |= VUNSET;
2272         } else {
2273                 vallen = strlen(val);
2274         }
2275
2276         INT_OFF;
2277         nameeq = ckmalloc(namelen + vallen + 2);
2278         p = memcpy(nameeq, name, namelen) + namelen;
2279         if (val) {
2280                 *p++ = '=';
2281                 p = memcpy(p, val, vallen) + vallen;
2282         }
2283         *p = '\0';
2284         setvareq(nameeq, flags | VNOSAVE);
2285         INT_ON;
2286 }
2287
2288 static void FAST_FUNC
2289 setvar0(const char *name, const char *val)
2290 {
2291         setvar(name, val, 0);
2292 }
2293
2294 /*
2295  * Unset the specified variable.
2296  */
2297 static int
2298 unsetvar(const char *s)
2299 {
2300         struct var **vpp;
2301         struct var *vp;
2302         int retval;
2303
2304         vpp = findvar(hashvar(s), s);
2305         vp = *vpp;
2306         retval = 2;
2307         if (vp) {
2308                 int flags = vp->flags;
2309
2310                 retval = 1;
2311                 if (flags & VREADONLY)
2312                         goto out;
2313 #if ENABLE_ASH_RANDOM_SUPPORT
2314                 vp->flags &= ~VDYNAMIC;
2315 #endif
2316                 if (flags & VUNSET)
2317                         goto ok;
2318                 if ((flags & VSTRFIXED) == 0) {
2319                         INT_OFF;
2320                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2321                                 free((char*)vp->var_text);
2322                         *vpp = vp->next;
2323                         free(vp);
2324                         INT_ON;
2325                 } else {
2326                         setvar0(s, NULL);
2327                         vp->flags &= ~VEXPORT;
2328                 }
2329  ok:
2330                 retval = 0;
2331         }
2332  out:
2333         return retval;
2334 }
2335
2336 /*
2337  * Process a linked list of variable assignments.
2338  */
2339 static void
2340 listsetvar(struct strlist *list_set_var, int flags)
2341 {
2342         struct strlist *lp = list_set_var;
2343
2344         if (!lp)
2345                 return;
2346         INT_OFF;
2347         do {
2348                 setvareq(lp->text, flags);
2349                 lp = lp->next;
2350         } while (lp);
2351         INT_ON;
2352 }
2353
2354 /*
2355  * Generate a list of variables satisfying the given conditions.
2356  */
2357 static char **
2358 listvars(int on, int off, char ***end)
2359 {
2360         struct var **vpp;
2361         struct var *vp;
2362         char **ep;
2363         int mask;
2364
2365         STARTSTACKSTR(ep);
2366         vpp = vartab;
2367         mask = on | off;
2368         do {
2369                 for (vp = *vpp; vp; vp = vp->next) {
2370                         if ((vp->flags & mask) == on) {
2371                                 if (ep == stackstrend())
2372                                         ep = growstackstr();
2373                                 *ep++ = (char*)vp->var_text;
2374                         }
2375                 }
2376         } while (++vpp < vartab + VTABSIZE);
2377         if (ep == stackstrend())
2378                 ep = growstackstr();
2379         if (end)
2380                 *end = ep;
2381         *ep++ = NULL;
2382         return grabstackstr(ep);
2383 }
2384
2385
2386 /* ============ Path search helper
2387  *
2388  * The variable path (passed by reference) should be set to the start
2389  * of the path before the first call; path_advance will update
2390  * this value as it proceeds.  Successive calls to path_advance will return
2391  * the possible path expansions in sequence.  If an option (indicated by
2392  * a percent sign) appears in the path entry then the global variable
2393  * pathopt will be set to point to it; otherwise pathopt will be set to
2394  * NULL.
2395  */
2396 static const char *pathopt;     /* set by path_advance */
2397
2398 static char *
2399 path_advance(const char **path, const char *name)
2400 {
2401         const char *p;
2402         char *q;
2403         const char *start;
2404         size_t len;
2405
2406         if (*path == NULL)
2407                 return NULL;
2408         start = *path;
2409         for (p = start; *p && *p != ':' && *p != '%'; p++)
2410                 continue;
2411         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2412         while (stackblocksize() < len)
2413                 growstackblock();
2414         q = stackblock();
2415         if (p != start) {
2416                 memcpy(q, start, p - start);
2417                 q += p - start;
2418                 *q++ = '/';
2419         }
2420         strcpy(q, name);
2421         pathopt = NULL;
2422         if (*p == '%') {
2423                 pathopt = ++p;
2424                 while (*p && *p != ':')
2425                         p++;
2426         }
2427         if (*p == ':')
2428                 *path = p + 1;
2429         else
2430                 *path = NULL;
2431         return stalloc(len);
2432 }
2433
2434
2435 /* ============ Prompt */
2436
2437 static smallint doprompt;                   /* if set, prompt the user */
2438 static smallint needprompt;                 /* true if interactive and at start of line */
2439
2440 #if ENABLE_FEATURE_EDITING
2441 static line_input_t *line_input_state;
2442 static const char *cmdedit_prompt;
2443 static void
2444 putprompt(const char *s)
2445 {
2446         if (ENABLE_ASH_EXPAND_PRMT) {
2447                 free((char*)cmdedit_prompt);
2448                 cmdedit_prompt = ckstrdup(s);
2449                 return;
2450         }
2451         cmdedit_prompt = s;
2452 }
2453 #else
2454 static void
2455 putprompt(const char *s)
2456 {
2457         out2str(s);
2458 }
2459 #endif
2460
2461 #if ENABLE_ASH_EXPAND_PRMT
2462 /* expandstr() needs parsing machinery, so it is far away ahead... */
2463 static const char *expandstr(const char *ps);
2464 #else
2465 #define expandstr(s) s
2466 #endif
2467
2468 static void
2469 setprompt_if(smallint do_set, int whichprompt)
2470 {
2471         const char *prompt;
2472         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2473
2474         if (!do_set)
2475                 return;
2476
2477         needprompt = 0;
2478
2479         switch (whichprompt) {
2480         case 1:
2481                 prompt = ps1val();
2482                 break;
2483         case 2:
2484                 prompt = ps2val();
2485                 break;
2486         default:                        /* 0 */
2487                 prompt = nullstr;
2488         }
2489 #if ENABLE_ASH_EXPAND_PRMT
2490         pushstackmark(&smark, stackblocksize());
2491 #endif
2492         putprompt(expandstr(prompt));
2493 #if ENABLE_ASH_EXPAND_PRMT
2494         popstackmark(&smark);
2495 #endif
2496 }
2497
2498
2499 /* ============ The cd and pwd commands */
2500
2501 #define CD_PHYSICAL 1
2502 #define CD_PRINT 2
2503
2504 static int
2505 cdopt(void)
2506 {
2507         int flags = 0;
2508         int i, j;
2509
2510         j = 'L';
2511         while ((i = nextopt("LP")) != '\0') {
2512                 if (i != j) {
2513                         flags ^= CD_PHYSICAL;
2514                         j = i;
2515                 }
2516         }
2517
2518         return flags;
2519 }
2520
2521 /*
2522  * Update curdir (the name of the current directory) in response to a
2523  * cd command.
2524  */
2525 static const char *
2526 updatepwd(const char *dir)
2527 {
2528         char *new;
2529         char *p;
2530         char *cdcomppath;
2531         const char *lim;
2532
2533         cdcomppath = sstrdup(dir);
2534         STARTSTACKSTR(new);
2535         if (*dir != '/') {
2536                 if (curdir == nullstr)
2537                         return 0;
2538                 new = stack_putstr(curdir, new);
2539         }
2540         new = makestrspace(strlen(dir) + 2, new);
2541         lim = (char *)stackblock() + 1;
2542         if (*dir != '/') {
2543                 if (new[-1] != '/')
2544                         USTPUTC('/', new);
2545                 if (new > lim && *lim == '/')
2546                         lim++;
2547         } else {
2548                 USTPUTC('/', new);
2549                 cdcomppath++;
2550                 if (dir[1] == '/' && dir[2] != '/') {
2551                         USTPUTC('/', new);
2552                         cdcomppath++;
2553                         lim++;
2554                 }
2555         }
2556         p = strtok(cdcomppath, "/");
2557         while (p) {
2558                 switch (*p) {
2559                 case '.':
2560                         if (p[1] == '.' && p[2] == '\0') {
2561                                 while (new > lim) {
2562                                         STUNPUTC(new);
2563                                         if (new[-1] == '/')
2564                                                 break;
2565                                 }
2566                                 break;
2567                         }
2568                         if (p[1] == '\0')
2569                                 break;
2570                         /* fall through */
2571                 default:
2572                         new = stack_putstr(p, new);
2573                         USTPUTC('/', new);
2574                 }
2575                 p = strtok(NULL, "/");
2576         }
2577         if (new > lim)
2578                 STUNPUTC(new);
2579         *new = 0;
2580         return stackblock();
2581 }
2582
2583 /*
2584  * Find out what the current directory is. If we already know the current
2585  * directory, this routine returns immediately.
2586  */
2587 static char *
2588 getpwd(void)
2589 {
2590         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2591         return dir ? dir : nullstr;
2592 }
2593
2594 static void
2595 setpwd(const char *val, int setold)
2596 {
2597         char *oldcur, *dir;
2598
2599         oldcur = dir = curdir;
2600
2601         if (setold) {
2602                 setvar("OLDPWD", oldcur, VEXPORT);
2603         }
2604         INT_OFF;
2605         if (physdir != nullstr) {
2606                 if (physdir != oldcur)
2607                         free(physdir);
2608                 physdir = nullstr;
2609         }
2610         if (oldcur == val || !val) {
2611                 char *s = getpwd();
2612                 physdir = s;
2613                 if (!val)
2614                         dir = s;
2615         } else
2616                 dir = ckstrdup(val);
2617         if (oldcur != dir && oldcur != nullstr) {
2618                 free(oldcur);
2619         }
2620         curdir = dir;
2621         INT_ON;
2622         setvar("PWD", dir, VEXPORT);
2623 }
2624
2625 static void hashcd(void);
2626
2627 /*
2628  * Actually do the chdir.  We also call hashcd to let other routines
2629  * know that the current directory has changed.
2630  */
2631 static int
2632 docd(const char *dest, int flags)
2633 {
2634         const char *dir = NULL;
2635         int err;
2636
2637         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2638
2639         INT_OFF;
2640         if (!(flags & CD_PHYSICAL)) {
2641                 dir = updatepwd(dest);
2642                 if (dir)
2643                         dest = dir;
2644         }
2645         err = chdir(dest);
2646         if (err)
2647                 goto out;
2648         setpwd(dir, 1);
2649         hashcd();
2650  out:
2651         INT_ON;
2652         return err;
2653 }
2654
2655 static int FAST_FUNC
2656 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2657 {
2658         const char *dest;
2659         const char *path;
2660         const char *p;
2661         char c;
2662         struct stat statb;
2663         int flags;
2664
2665         flags = cdopt();
2666         dest = *argptr;
2667         if (!dest)
2668                 dest = bltinlookup("HOME");
2669         else if (LONE_DASH(dest)) {
2670                 dest = bltinlookup("OLDPWD");
2671                 flags |= CD_PRINT;
2672         }
2673         if (!dest)
2674                 dest = nullstr;
2675         if (*dest == '/')
2676                 goto step6;
2677         if (*dest == '.') {
2678                 c = dest[1];
2679  dotdot:
2680                 switch (c) {
2681                 case '\0':
2682                 case '/':
2683                         goto step6;
2684                 case '.':
2685                         c = dest[2];
2686                         if (c != '.')
2687                                 goto dotdot;
2688                 }
2689         }
2690         if (!*dest)
2691                 dest = ".";
2692         path = bltinlookup("CDPATH");
2693         while (path) {
2694                 c = *path;
2695                 p = path_advance(&path, dest);
2696                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2697                         if (c && c != ':')
2698                                 flags |= CD_PRINT;
2699  docd:
2700                         if (!docd(p, flags))
2701                                 goto out;
2702                         goto err;
2703                 }
2704         }
2705
2706  step6:
2707         p = dest;
2708         goto docd;
2709
2710  err:
2711         ash_msg_and_raise_error("can't cd to %s", dest);
2712         /* NOTREACHED */
2713  out:
2714         if (flags & CD_PRINT)
2715                 out1fmt("%s\n", curdir);
2716         return 0;
2717 }
2718
2719 static int FAST_FUNC
2720 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2721 {
2722         int flags;
2723         const char *dir = curdir;
2724
2725         flags = cdopt();
2726         if (flags) {
2727                 if (physdir == nullstr)
2728                         setpwd(dir, 0);
2729                 dir = physdir;
2730         }
2731         out1fmt("%s\n", dir);
2732         return 0;
2733 }
2734
2735
2736 /* ============ ... */
2737
2738
2739 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2740
2741 /* Syntax classes */
2742 #define CWORD     0             /* character is nothing special */
2743 #define CNL       1             /* newline character */
2744 #define CBACK     2             /* a backslash character */
2745 #define CSQUOTE   3             /* single quote */
2746 #define CDQUOTE   4             /* double quote */
2747 #define CENDQUOTE 5             /* a terminating quote */
2748 #define CBQUOTE   6             /* backwards single quote */
2749 #define CVAR      7             /* a dollar sign */
2750 #define CENDVAR   8             /* a '}' character */
2751 #define CLP       9             /* a left paren in arithmetic */
2752 #define CRP      10             /* a right paren in arithmetic */
2753 #define CENDFILE 11             /* end of file */
2754 #define CCTL     12             /* like CWORD, except it must be escaped */
2755 #define CSPCL    13             /* these terminate a word */
2756 #define CIGN     14             /* character should be ignored */
2757
2758 #define PEOF     256
2759 #if ENABLE_ASH_ALIAS
2760 # define PEOA    257
2761 #endif
2762
2763 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2764
2765 #if ENABLE_FEATURE_SH_MATH
2766 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2767 #else
2768 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2769 #endif
2770 static const uint16_t S_I_T[] ALIGN2 = {
2771 #if ENABLE_ASH_ALIAS
2772         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2773 #endif
2774         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2775         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2776         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2777         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2778         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2779         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2780         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2781         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2782         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2783         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2784         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2785 #if !USE_SIT_FUNCTION
2786         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2787         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2788         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2789 #endif
2790 #undef SIT_ITEM
2791 };
2792 /* Constants below must match table above */
2793 enum {
2794 #if ENABLE_ASH_ALIAS
2795         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2796 #endif
2797         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2798         CNL_CNL_CNL_CNL                    , /*  2 */
2799         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2800         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2801         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2802         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2803         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2804         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2805         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2806         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2807         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2808         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2809         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2810         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2811 };
2812
2813 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2814  * caller must ensure proper cast on it if c is *char_ptr!
2815  */
2816 /* Values for syntax param */
2817 #define BASESYNTAX 0    /* not in quotes */
2818 #define DQSYNTAX   1    /* in double quotes */
2819 #define SQSYNTAX   2    /* in single quotes */
2820 #define ARISYNTAX  3    /* in arithmetic */
2821 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2822
2823 #if USE_SIT_FUNCTION
2824
2825 static int
2826 SIT(int c, int syntax)
2827 {
2828         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2829         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2830         /*
2831          * This causes '/' to be prepended with CTLESC in dquoted string,
2832          * making "./file"* treated incorrectly because we feed
2833          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2834          * The "homegrown" glob implementation is okay with that,
2835          * but glibc one isn't. With '/' always treated as CWORD,
2836          * both work fine.
2837          */
2838 # if ENABLE_ASH_ALIAS
2839         static const uint8_t syntax_index_table[] ALIGN1 = {
2840                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2841                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2842                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2843                 11, 3                           /* "}~" */
2844         };
2845 # else
2846         static const uint8_t syntax_index_table[] ALIGN1 = {
2847                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2848                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2849                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2850                 10, 2                           /* "}~" */
2851         };
2852 # endif
2853         const char *s;
2854         int indx;
2855
2856         if (c == PEOF)
2857                 return CENDFILE;
2858 # if ENABLE_ASH_ALIAS
2859         if (c == PEOA)
2860                 indx = 0;
2861         else
2862 # endif
2863         {
2864                 /* Cast is purely for paranoia here,
2865                  * just in case someone passed signed char to us */
2866                 if ((unsigned char)c >= CTL_FIRST
2867                  && (unsigned char)c <= CTL_LAST
2868                 ) {
2869                         return CCTL;
2870                 }
2871                 s = strchrnul(spec_symbls, c);
2872                 if (*s == '\0')
2873                         return CWORD;
2874                 indx = syntax_index_table[s - spec_symbls];
2875         }
2876         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2877 }
2878
2879 #else   /* !USE_SIT_FUNCTION */
2880
2881 static const uint8_t syntax_index_table[] ALIGN1 = {
2882         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2883         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2884         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2885         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2886         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2887         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2888         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2889         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2890         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2891         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2892         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2893         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2894         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2895         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2896         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2897         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2898         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2899         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2900         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2901         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2902         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2903         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2904         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2905         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2906         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2907         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2908         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2909         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2910         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2911         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2912         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2913         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2914         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2915         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2916         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2917         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2918         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2919         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2920         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2921         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2922         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2923         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2924         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2925         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2926         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2927         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2928         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2929         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2930 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2931         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2932         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2933         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2934         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2935         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2936         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2937         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2938         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2939         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2940         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2941         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2942         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2943         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2944         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2945         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2946         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2947         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2948         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2950         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2953         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2954         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2956         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2958         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2976         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2977         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2978         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2981         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2984         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2985         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2986         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
2987         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
2988         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
2989         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
2990         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
2991         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
2992         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
2993         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
2994         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
2995         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
2996         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
2997         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
2998         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
2999         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3000         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3001         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3002         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3003         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3004         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3005         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3006         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3007         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3008         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3009         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3010         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3011         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3012         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3013         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3014         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3015         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3016         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3017         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3018         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3019         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3020         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3021         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3022         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3023         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3024         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3025         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3026         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3027         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3028         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3029         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3030         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3031         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3032         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3033         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3034         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3140         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3141 # if ENABLE_ASH_ALIAS
3142         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3143 # endif
3144 };
3145
3146 #if 1
3147 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3148 #else /* debug version, caught one signed char bug */
3149 # define SIT(c, syntax) \
3150         ({ \
3151                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3152                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3153                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3154                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3155                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3156         })
3157 #endif
3158
3159 #endif  /* !USE_SIT_FUNCTION */
3160
3161
3162 /* ============ Alias handling */
3163
3164 #if ENABLE_ASH_ALIAS
3165
3166 #define ALIASINUSE 1
3167 #define ALIASDEAD  2
3168
3169 struct alias {
3170         struct alias *next;
3171         char *name;
3172         char *val;
3173         int flag;
3174 };
3175
3176
3177 static struct alias **atab; // [ATABSIZE];
3178 #define INIT_G_alias() do { \
3179         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3180 } while (0)
3181
3182
3183 static struct alias **
3184 __lookupalias(const char *name)
3185 {
3186         unsigned int hashval;
3187         struct alias **app;
3188         const char *p;
3189         unsigned int ch;
3190
3191         p = name;
3192
3193         ch = (unsigned char)*p;
3194         hashval = ch << 4;
3195         while (ch) {
3196                 hashval += ch;
3197                 ch = (unsigned char)*++p;
3198         }
3199         app = &atab[hashval % ATABSIZE];
3200
3201         for (; *app; app = &(*app)->next) {
3202                 if (strcmp(name, (*app)->name) == 0) {
3203                         break;
3204                 }
3205         }
3206
3207         return app;
3208 }
3209
3210 static struct alias *
3211 lookupalias(const char *name, int check)
3212 {
3213         struct alias *ap = *__lookupalias(name);
3214
3215         if (check && ap && (ap->flag & ALIASINUSE))
3216                 return NULL;
3217         return ap;
3218 }
3219
3220 static struct alias *
3221 freealias(struct alias *ap)
3222 {
3223         struct alias *next;
3224
3225         if (ap->flag & ALIASINUSE) {
3226                 ap->flag |= ALIASDEAD;
3227                 return ap;
3228         }
3229
3230         next = ap->next;
3231         free(ap->name);
3232         free(ap->val);
3233         free(ap);
3234         return next;
3235 }
3236
3237 static void
3238 setalias(const char *name, const char *val)
3239 {
3240         struct alias *ap, **app;
3241
3242         app = __lookupalias(name);
3243         ap = *app;
3244         INT_OFF;
3245         if (ap) {
3246                 if (!(ap->flag & ALIASINUSE)) {
3247                         free(ap->val);
3248                 }
3249                 ap->val = ckstrdup(val);
3250                 ap->flag &= ~ALIASDEAD;
3251         } else {
3252                 /* not found */
3253                 ap = ckzalloc(sizeof(struct alias));
3254                 ap->name = ckstrdup(name);
3255                 ap->val = ckstrdup(val);
3256                 /*ap->flag = 0; - ckzalloc did it */
3257                 /*ap->next = NULL;*/
3258                 *app = ap;
3259         }
3260         INT_ON;
3261 }
3262
3263 static int
3264 unalias(const char *name)
3265 {
3266         struct alias **app;
3267
3268         app = __lookupalias(name);
3269
3270         if (*app) {
3271                 INT_OFF;
3272                 *app = freealias(*app);
3273                 INT_ON;
3274                 return 0;
3275         }
3276
3277         return 1;
3278 }
3279
3280 static void
3281 rmaliases(void)
3282 {
3283         struct alias *ap, **app;
3284         int i;
3285
3286         INT_OFF;
3287         for (i = 0; i < ATABSIZE; i++) {
3288                 app = &atab[i];
3289                 for (ap = *app; ap; ap = *app) {
3290                         *app = freealias(*app);
3291                         if (ap == *app) {
3292                                 app = &ap->next;
3293                         }
3294                 }
3295         }
3296         INT_ON;
3297 }
3298
3299 static void
3300 printalias(const struct alias *ap)
3301 {
3302         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3303 }
3304
3305 /*
3306  * TODO - sort output
3307  */
3308 static int FAST_FUNC
3309 aliascmd(int argc UNUSED_PARAM, char **argv)
3310 {
3311         char *n, *v;
3312         int ret = 0;
3313         struct alias *ap;
3314
3315         if (!argv[1]) {
3316                 int i;
3317
3318                 for (i = 0; i < ATABSIZE; i++) {
3319                         for (ap = atab[i]; ap; ap = ap->next) {
3320                                 printalias(ap);
3321                         }
3322                 }
3323                 return 0;
3324         }
3325         while ((n = *++argv) != NULL) {
3326                 v = strchr(n+1, '=');
3327                 if (v == NULL) { /* n+1: funny ksh stuff */
3328                         ap = *__lookupalias(n);
3329                         if (ap == NULL) {
3330                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3331                                 ret = 1;
3332                         } else
3333                                 printalias(ap);
3334                 } else {
3335                         *v++ = '\0';
3336                         setalias(n, v);
3337                 }
3338         }
3339
3340         return ret;
3341 }
3342
3343 static int FAST_FUNC
3344 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3345 {
3346         int i;
3347
3348         while (nextopt("a") != '\0') {
3349                 rmaliases();
3350                 return 0;
3351         }
3352         for (i = 0; *argptr; argptr++) {
3353                 if (unalias(*argptr)) {
3354                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3355                         i = 1;
3356                 }
3357         }
3358
3359         return i;
3360 }
3361
3362 #endif /* ASH_ALIAS */
3363
3364
3365 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3366 #define FORK_FG    0
3367 #define FORK_BG    1
3368 #define FORK_NOJOB 2
3369
3370 /* mode flags for showjob(s) */
3371 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3372 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3373 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3374 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3375
3376 /*
3377  * A job structure contains information about a job.  A job is either a
3378  * single process or a set of processes contained in a pipeline.  In the
3379  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3380  * array of pids.
3381  */
3382 struct procstat {
3383         pid_t   ps_pid;         /* process id */
3384         int     ps_status;      /* last process status from wait() */
3385         char    *ps_cmd;        /* text of command being run */
3386 };
3387
3388 struct job {
3389         struct procstat ps0;    /* status of process */
3390         struct procstat *ps;    /* status or processes when more than one */
3391 #if JOBS
3392         int stopstatus;         /* status of a stopped job */
3393 #endif
3394         unsigned nprocs;        /* number of processes */
3395
3396 #define JOBRUNNING      0       /* at least one proc running */
3397 #define JOBSTOPPED      1       /* all procs are stopped */
3398 #define JOBDONE         2       /* all procs are completed */
3399         unsigned
3400                 state: 8,
3401 #if JOBS
3402                 sigint: 1,      /* job was killed by SIGINT */
3403                 jobctl: 1,      /* job running under job control */
3404 #endif
3405                 waited: 1,      /* true if this entry has been waited for */
3406                 used: 1,        /* true if this entry is in used */
3407                 changed: 1;     /* true if status has changed */
3408         struct job *prev_job;   /* previous job */
3409 };
3410
3411 static struct job *makejob(/*union node *,*/ int);
3412 static int forkshell(struct job *, union node *, int);
3413 static int waitforjob(struct job *);
3414
3415 #if !JOBS
3416 enum { doing_jobctl = 0 };
3417 #define setjobctl(on) do {} while (0)
3418 #else
3419 static smallint doing_jobctl; //references:8
3420 static void setjobctl(int);
3421 #endif
3422
3423 /*
3424  * Ignore a signal.
3425  */
3426 static void
3427 ignoresig(int signo)
3428 {
3429         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3430         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3431                 /* No, need to do it */
3432                 signal(signo, SIG_IGN);
3433         }
3434         sigmode[signo - 1] = S_HARD_IGN;
3435 }
3436
3437 /*
3438  * Only one usage site - in setsignal()
3439  */
3440 static void
3441 signal_handler(int signo)
3442 {
3443         if (signo == SIGCHLD) {
3444                 got_sigchld = 1;
3445                 if (!trap[SIGCHLD])
3446                         return;
3447         }
3448
3449         gotsig[signo - 1] = 1;
3450         pending_sig = signo;
3451
3452         if (signo == SIGINT && !trap[SIGINT]) {
3453                 if (!suppress_int) {
3454                         pending_sig = 0;
3455                         raise_interrupt(); /* does not return */
3456                 }
3457                 pending_int = 1;
3458         }
3459 }
3460
3461 /*
3462  * Set the signal handler for the specified signal.  The routine figures
3463  * out what it should be set to.
3464  */
3465 static void
3466 setsignal(int signo)
3467 {
3468         char *t;
3469         char cur_act, new_act;
3470         struct sigaction act;
3471
3472         t = trap[signo];
3473         new_act = S_DFL;
3474         if (t != NULL) { /* trap for this sig is set */
3475                 new_act = S_CATCH;
3476                 if (t[0] == '\0') /* trap is "": ignore this sig */
3477                         new_act = S_IGN;
3478         }
3479
3480         if (rootshell && new_act == S_DFL) {
3481                 switch (signo) {
3482                 case SIGINT:
3483                         if (iflag || minusc || sflag == 0)
3484                                 new_act = S_CATCH;
3485                         break;
3486                 case SIGQUIT:
3487 #if DEBUG
3488                         if (debug)
3489                                 break;
3490 #endif
3491                         /* man bash:
3492                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3493                          * commands run by bash have signal handlers
3494                          * set to the values inherited by the shell
3495                          * from its parent". */
3496                         new_act = S_IGN;
3497                         break;
3498                 case SIGTERM:
3499                         if (iflag)
3500                                 new_act = S_IGN;
3501                         break;
3502 #if JOBS
3503                 case SIGTSTP:
3504                 case SIGTTOU:
3505                         if (mflag)
3506                                 new_act = S_IGN;
3507                         break;
3508 #endif
3509                 }
3510         }
3511 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3512 //whereas we have to restore it to what shell got on entry
3513 //from the parent. See comment above
3514
3515         if (signo == SIGCHLD)
3516                 new_act = S_CATCH;
3517
3518         t = &sigmode[signo - 1];
3519         cur_act = *t;
3520         if (cur_act == 0) {
3521                 /* current setting is not yet known */
3522                 if (sigaction(signo, NULL, &act)) {
3523                         /* pretend it worked; maybe we should give a warning,
3524                          * but other shells don't. We don't alter sigmode,
3525                          * so we retry every time.
3526                          * btw, in Linux it never fails. --vda */
3527                         return;
3528                 }
3529                 if (act.sa_handler == SIG_IGN) {
3530                         cur_act = S_HARD_IGN;
3531                         if (mflag
3532                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3533                         ) {
3534                                 cur_act = S_IGN;   /* don't hard ignore these */
3535                         }
3536                 }
3537         }
3538         if (cur_act == S_HARD_IGN || cur_act == new_act)
3539                 return;
3540
3541         act.sa_handler = SIG_DFL;
3542         switch (new_act) {
3543         case S_CATCH:
3544                 act.sa_handler = signal_handler;
3545                 break;
3546         case S_IGN:
3547                 act.sa_handler = SIG_IGN;
3548                 break;
3549         }
3550
3551         /* flags and mask matter only if !DFL and !IGN, but we do it
3552          * for all cases for more deterministic behavior:
3553          */
3554         act.sa_flags = 0;
3555         sigfillset(&act.sa_mask);
3556
3557         sigaction_set(signo, &act);
3558
3559         *t = new_act;
3560 }
3561
3562 /* mode flags for set_curjob */
3563 #define CUR_DELETE 2
3564 #define CUR_RUNNING 1
3565 #define CUR_STOPPED 0
3566
3567 #if JOBS
3568 /* pgrp of shell on invocation */
3569 static int initialpgrp; //references:2
3570 static int ttyfd = -1; //5
3571 #endif
3572 /* array of jobs */
3573 static struct job *jobtab; //5
3574 /* size of array */
3575 static unsigned njobs; //4
3576 /* current job */
3577 static struct job *curjob; //lots
3578 /* number of presumed living untracked jobs */
3579 static int jobless; //4
3580
3581 #if 0
3582 /* Bash has a feature: it restores termios after a successful wait for
3583  * a foreground job which had at least one stopped or sigkilled member.
3584  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3585  * properly restoring tty state. Should we do this too?
3586  * A reproducer: ^Z an interactive python:
3587  *
3588  * # python
3589  * Python 2.7.12 (...)
3590  * >>> ^Z
3591  *      { python leaves tty in -icanon -echo state. We do survive that... }
3592  *  [1]+  Stopped                    python
3593  *      { ...however, next program (python #2) does not survive it well: }
3594  * # python
3595  * Python 2.7.12 (...)
3596  * >>> Traceback (most recent call last):
3597  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3598  *   File "<stdin>", line 1, in <module>
3599  * NameError: name 'qwerty' is not defined
3600  *
3601  * The implementation below is modeled on bash code and seems to work.
3602  * However, I'm not sure we should do this. For one: what if I'd fg
3603  * the stopped python instead? It'll be confused by "restored" tty state.
3604  */
3605 static struct termios shell_tty_info;
3606 static void
3607 get_tty_state(void)
3608 {
3609         if (rootshell && ttyfd >= 0)
3610                 tcgetattr(ttyfd, &shell_tty_info);
3611 }
3612 static void
3613 set_tty_state(void)
3614 {
3615         /* if (rootshell) - caller ensures this */
3616         if (ttyfd >= 0)
3617                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3618 }
3619 static int
3620 job_signal_status(struct job *jp)
3621 {
3622         int status;
3623         unsigned i;
3624         struct procstat *ps = jp->ps;
3625         for (i = 0; i < jp->nprocs; i++) {
3626                 status = ps[i].ps_status;
3627                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3628                         return status;
3629         }
3630         return 0;
3631 }
3632 static void
3633 restore_tty_if_stopped_or_signaled(struct job *jp)
3634 {
3635 //TODO: check what happens if we come from waitforjob() in expbackq()
3636         if (rootshell) {
3637                 int s = job_signal_status(jp);
3638                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3639                         set_tty_state();
3640         }
3641 }
3642 #else
3643 # define get_tty_state() ((void)0)
3644 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3645 #endif
3646
3647 static void
3648 set_curjob(struct job *jp, unsigned mode)
3649 {
3650         struct job *jp1;
3651         struct job **jpp, **curp;
3652
3653         /* first remove from list */
3654         jpp = curp = &curjob;
3655         while (1) {
3656                 jp1 = *jpp;
3657                 if (jp1 == jp)
3658                         break;
3659                 jpp = &jp1->prev_job;
3660         }
3661         *jpp = jp1->prev_job;
3662
3663         /* Then re-insert in correct position */
3664         jpp = curp;
3665         switch (mode) {
3666         default:
3667 #if DEBUG
3668                 abort();
3669 #endif
3670         case CUR_DELETE:
3671                 /* job being deleted */
3672                 break;
3673         case CUR_RUNNING:
3674                 /* newly created job or backgrounded job,
3675                  * put after all stopped jobs.
3676                  */
3677                 while (1) {
3678                         jp1 = *jpp;
3679 #if JOBS
3680                         if (!jp1 || jp1->state != JOBSTOPPED)
3681 #endif
3682                                 break;
3683                         jpp = &jp1->prev_job;
3684                 }
3685                 /* FALLTHROUGH */
3686 #if JOBS
3687         case CUR_STOPPED:
3688 #endif
3689                 /* newly stopped job - becomes curjob */
3690                 jp->prev_job = *jpp;
3691                 *jpp = jp;
3692                 break;
3693         }
3694 }
3695
3696 #if JOBS || DEBUG
3697 static int
3698 jobno(const struct job *jp)
3699 {
3700         return jp - jobtab + 1;
3701 }
3702 #endif
3703
3704 /*
3705  * Convert a job name to a job structure.
3706  */
3707 #if !JOBS
3708 #define getjob(name, getctl) getjob(name)
3709 #endif
3710 static struct job *
3711 getjob(const char *name, int getctl)
3712 {
3713         struct job *jp;
3714         struct job *found;
3715         const char *err_msg = "%s: no such job";
3716         unsigned num;
3717         int c;
3718         const char *p;
3719         char *(*match)(const char *, const char *);
3720
3721         jp = curjob;
3722         p = name;
3723         if (!p)
3724                 goto currentjob;
3725
3726         if (*p != '%')
3727                 goto err;
3728
3729         c = *++p;
3730         if (!c)
3731                 goto currentjob;
3732
3733         if (!p[1]) {
3734                 if (c == '+' || c == '%') {
3735  currentjob:
3736                         err_msg = "No current job";
3737                         goto check;
3738                 }
3739                 if (c == '-') {
3740                         if (jp)
3741                                 jp = jp->prev_job;
3742                         err_msg = "No previous job";
3743  check:
3744                         if (!jp)
3745                                 goto err;
3746                         goto gotit;
3747                 }
3748         }
3749
3750         if (is_number(p)) {
3751                 num = atoi(p);
3752                 if (num > 0 && num <= njobs) {
3753                         jp = jobtab + num - 1;
3754                         if (jp->used)
3755                                 goto gotit;
3756                         goto err;
3757                 }
3758         }
3759
3760         match = prefix;
3761         if (*p == '?') {
3762                 match = strstr;
3763                 p++;
3764         }
3765
3766         found = NULL;
3767         while (jp) {
3768                 if (match(jp->ps[0].ps_cmd, p)) {
3769                         if (found)
3770                                 goto err;
3771                         found = jp;
3772                         err_msg = "%s: ambiguous";
3773                 }
3774                 jp = jp->prev_job;
3775         }
3776         if (!found)
3777                 goto err;
3778         jp = found;
3779
3780  gotit:
3781 #if JOBS
3782         err_msg = "job %s not created under job control";
3783         if (getctl && jp->jobctl == 0)
3784                 goto err;
3785 #endif
3786         return jp;
3787  err:
3788         ash_msg_and_raise_error(err_msg, name);
3789 }
3790
3791 /*
3792  * Mark a job structure as unused.
3793  */
3794 static void
3795 freejob(struct job *jp)
3796 {
3797         struct procstat *ps;
3798         int i;
3799
3800         INT_OFF;
3801         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3802                 if (ps->ps_cmd != nullstr)
3803                         free(ps->ps_cmd);
3804         }
3805         if (jp->ps != &jp->ps0)
3806                 free(jp->ps);
3807         jp->used = 0;
3808         set_curjob(jp, CUR_DELETE);
3809         INT_ON;
3810 }
3811
3812 #if JOBS
3813 static void
3814 xtcsetpgrp(int fd, pid_t pgrp)
3815 {
3816         if (tcsetpgrp(fd, pgrp))
3817                 ash_msg_and_raise_error("can't set tty process group (%m)");
3818 }
3819
3820 /*
3821  * Turn job control on and off.
3822  *
3823  * Note:  This code assumes that the third arg to ioctl is a character
3824  * pointer, which is true on Berkeley systems but not System V.  Since
3825  * System V doesn't have job control yet, this isn't a problem now.
3826  *
3827  * Called with interrupts off.
3828  */
3829 static void
3830 setjobctl(int on)
3831 {
3832         int fd;
3833         int pgrp;
3834
3835         if (on == doing_jobctl || rootshell == 0)
3836                 return;
3837         if (on) {
3838                 int ofd;
3839                 ofd = fd = open(_PATH_TTY, O_RDWR);
3840                 if (fd < 0) {
3841         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3842          * That sometimes helps to acquire controlling tty.
3843          * Obviously, a workaround for bugs when someone
3844          * failed to provide a controlling tty to bash! :) */
3845                         fd = 2;
3846                         while (!isatty(fd))
3847                                 if (--fd < 0)
3848                                         goto out;
3849                 }
3850                 /* fd is a tty at this point */
3851                 fd = fcntl(fd, F_DUPFD, 10);
3852                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3853                         close(ofd);
3854                 if (fd < 0)
3855                         goto out; /* F_DUPFD failed */
3856                 close_on_exec_on(fd);
3857                 while (1) { /* while we are in the background */
3858                         pgrp = tcgetpgrp(fd);
3859                         if (pgrp < 0) {
3860  out:
3861                                 ash_msg("can't access tty; job control turned off");
3862                                 mflag = on = 0;
3863                                 goto close;
3864                         }
3865                         if (pgrp == getpgrp())
3866                                 break;
3867                         killpg(0, SIGTTIN);
3868                 }
3869                 initialpgrp = pgrp;
3870
3871                 setsignal(SIGTSTP);
3872                 setsignal(SIGTTOU);
3873                 setsignal(SIGTTIN);
3874                 pgrp = rootpid;
3875                 setpgid(0, pgrp);
3876                 xtcsetpgrp(fd, pgrp);
3877         } else {
3878                 /* turning job control off */
3879                 fd = ttyfd;
3880                 pgrp = initialpgrp;
3881                 /* was xtcsetpgrp, but this can make exiting ash
3882                  * loop forever if pty is already deleted */
3883                 tcsetpgrp(fd, pgrp);
3884                 setpgid(0, pgrp);
3885                 setsignal(SIGTSTP);
3886                 setsignal(SIGTTOU);
3887                 setsignal(SIGTTIN);
3888  close:
3889                 if (fd >= 0)
3890                         close(fd);
3891                 fd = -1;
3892         }
3893         ttyfd = fd;
3894         doing_jobctl = on;
3895 }
3896
3897 static int FAST_FUNC
3898 killcmd(int argc, char **argv)
3899 {
3900         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3901                 int i = 1;
3902                 do {
3903                         if (argv[i][0] == '%') {
3904                                 /*
3905                                  * "kill %N" - job kill
3906                                  * Converting to pgrp / pid kill
3907                                  */
3908                                 struct job *jp;
3909                                 char *dst;
3910                                 int j, n;
3911
3912                                 jp = getjob(argv[i], 0);
3913                                 /*
3914                                  * In jobs started under job control, we signal
3915                                  * entire process group by kill -PGRP_ID.
3916                                  * This happens, f.e., in interactive shell.
3917                                  *
3918                                  * Otherwise, we signal each child via
3919                                  * kill PID1 PID2 PID3.
3920                                  * Testcases:
3921                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3922                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3923                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3924                                  */
3925                                 n = jp->nprocs; /* can't be 0 (I hope) */
3926                                 if (jp->jobctl)
3927                                         n = 1;
3928                                 dst = alloca(n * sizeof(int)*4);
3929                                 argv[i] = dst;
3930                                 for (j = 0; j < n; j++) {
3931                                         struct procstat *ps = &jp->ps[j];
3932                                         /* Skip non-running and not-stopped members
3933                                          * (i.e. dead members) of the job
3934                                          */
3935                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3936                                                 continue;
3937                                         /*
3938                                          * kill_main has matching code to expect
3939                                          * leading space. Needed to not confuse
3940                                          * negative pids with "kill -SIGNAL_NO" syntax
3941                                          */
3942                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3943                                 }
3944                                 *dst = '\0';
3945                         }
3946                 } while (argv[++i]);
3947         }
3948         return kill_main(argc, argv);
3949 }
3950
3951 static void
3952 showpipe(struct job *jp /*, FILE *out*/)
3953 {
3954         struct procstat *ps;
3955         struct procstat *psend;
3956
3957         psend = jp->ps + jp->nprocs;
3958         for (ps = jp->ps + 1; ps < psend; ps++)
3959                 printf(" | %s", ps->ps_cmd);
3960         newline_and_flush(stdout);
3961         flush_stdout_stderr();
3962 }
3963
3964
3965 static int
3966 restartjob(struct job *jp, int mode)
3967 {
3968         struct procstat *ps;
3969         int i;
3970         int status;
3971         pid_t pgid;
3972
3973         INT_OFF;
3974         if (jp->state == JOBDONE)
3975                 goto out;
3976         jp->state = JOBRUNNING;
3977         pgid = jp->ps[0].ps_pid;
3978         if (mode == FORK_FG) {
3979                 get_tty_state();
3980                 xtcsetpgrp(ttyfd, pgid);
3981         }
3982         killpg(pgid, SIGCONT);
3983         ps = jp->ps;
3984         i = jp->nprocs;
3985         do {
3986                 if (WIFSTOPPED(ps->ps_status)) {
3987                         ps->ps_status = -1;
3988                 }
3989                 ps++;
3990         } while (--i);
3991  out:
3992         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3993         INT_ON;
3994         return status;
3995 }
3996
3997 static int FAST_FUNC
3998 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3999 {
4000         struct job *jp;
4001         int mode;
4002         int retval;
4003
4004         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4005         nextopt(nullstr);
4006         argv = argptr;
4007         do {
4008                 jp = getjob(*argv, 1);
4009                 if (mode == FORK_BG) {
4010                         set_curjob(jp, CUR_RUNNING);
4011                         printf("[%d] ", jobno(jp));
4012                 }
4013                 out1str(jp->ps[0].ps_cmd);
4014                 showpipe(jp /*, stdout*/);
4015                 retval = restartjob(jp, mode);
4016         } while (*argv && *++argv);
4017         return retval;
4018 }
4019 #endif
4020
4021 static int
4022 sprint_status48(char *s, int status, int sigonly)
4023 {
4024         int col;
4025         int st;
4026
4027         col = 0;
4028         if (!WIFEXITED(status)) {
4029                 if (JOBS && WIFSTOPPED(status))
4030                         st = WSTOPSIG(status);
4031                 else
4032                         st = WTERMSIG(status);
4033                 if (sigonly) {
4034                         if (st == SIGINT || st == SIGPIPE)
4035                                 goto out;
4036                         if (JOBS && WIFSTOPPED(status))
4037                                 goto out;
4038                 }
4039                 st &= 0x7f;
4040 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4041                 col = fmtstr(s, 32, strsignal(st));
4042                 if (WCOREDUMP(status)) {
4043                         strcpy(s + col, " (core dumped)");
4044                         col += sizeof(" (core dumped)")-1;
4045                 }
4046         } else if (!sigonly) {
4047                 st = WEXITSTATUS(status);
4048                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4049         }
4050  out:
4051         return col;
4052 }
4053
4054 static int
4055 wait_block_or_sig(int *status)
4056 {
4057         int pid;
4058
4059         do {
4060                 sigset_t mask;
4061
4062                 /* Poll all children for changes in their state */
4063                 got_sigchld = 0;
4064                 /* if job control is active, accept stopped processes too */
4065                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4066                 if (pid != 0)
4067                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4068
4069                 /* Children exist, but none are ready. Sleep until interesting signal */
4070 #if 1
4071                 sigfillset(&mask);
4072                 sigprocmask(SIG_SETMASK, &mask, &mask);
4073                 while (!got_sigchld && !pending_sig)
4074                         sigsuspend(&mask);
4075                 sigprocmask(SIG_SETMASK, &mask, NULL);
4076 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4077                 while (!got_sigchld && !pending_sig)
4078                         pause();
4079 #endif
4080
4081                 /* If it was SIGCHLD, poll children again */
4082         } while (got_sigchld);
4083
4084         return pid;
4085 }
4086
4087 #define DOWAIT_NONBLOCK 0
4088 #define DOWAIT_BLOCK    1
4089 #define DOWAIT_BLOCK_OR_SIG 2
4090
4091 static int
4092 dowait(int block, struct job *job)
4093 {
4094         int pid;
4095         int status;
4096         struct job *jp;
4097         struct job *thisjob = NULL;
4098
4099         TRACE(("dowait(0x%x) called\n", block));
4100
4101         /* It's wrong to call waitpid() outside of INT_OFF region:
4102          * signal can arrive just after syscall return and handler can
4103          * longjmp away, losing stop/exit notification processing.
4104          * Thus, for "jobs" builtin, and for waiting for a fg job,
4105          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4106          *
4107          * However, for "wait" builtin it is wrong to simply call waitpid()
4108          * in INT_OFF region: "wait" needs to wait for any running job
4109          * to change state, but should exit on any trap too.
4110          * In INT_OFF region, a signal just before syscall entry can set
4111          * pending_sig variables, but we can't check them, and we would
4112          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4113          *
4114          * Because of this, we run inside INT_OFF, but use a special routine
4115          * which combines waitpid() and sigsuspend().
4116          * This is the reason why we need to have a handler for SIGCHLD:
4117          * SIG_DFL handler does not wake sigsuspend().
4118          */
4119         INT_OFF;
4120         if (block == DOWAIT_BLOCK_OR_SIG) {
4121                 pid = wait_block_or_sig(&status);
4122         } else {
4123                 int wait_flags = 0;
4124                 if (block == DOWAIT_NONBLOCK)
4125                         wait_flags = WNOHANG;
4126                 /* if job control is active, accept stopped processes too */
4127                 if (doing_jobctl)
4128                         wait_flags |= WUNTRACED;
4129                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4130                 pid = waitpid(-1, &status, wait_flags);
4131         }
4132         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4133                                 pid, status, errno, strerror(errno)));
4134         if (pid <= 0)
4135                 goto out;
4136
4137         thisjob = NULL;
4138         for (jp = curjob; jp; jp = jp->prev_job) {
4139                 int jobstate;
4140                 struct procstat *ps;
4141                 struct procstat *psend;
4142                 if (jp->state == JOBDONE)
4143                         continue;
4144                 jobstate = JOBDONE;
4145                 ps = jp->ps;
4146                 psend = ps + jp->nprocs;
4147                 do {
4148                         if (ps->ps_pid == pid) {
4149                                 TRACE(("Job %d: changing status of proc %d "
4150                                         "from 0x%x to 0x%x\n",
4151                                         jobno(jp), pid, ps->ps_status, status));
4152                                 ps->ps_status = status;
4153                                 thisjob = jp;
4154                         }
4155                         if (ps->ps_status == -1)
4156                                 jobstate = JOBRUNNING;
4157 #if JOBS
4158                         if (jobstate == JOBRUNNING)
4159                                 continue;
4160                         if (WIFSTOPPED(ps->ps_status)) {
4161                                 jp->stopstatus = ps->ps_status;
4162                                 jobstate = JOBSTOPPED;
4163                         }
4164 #endif
4165                 } while (++ps < psend);
4166                 if (!thisjob)
4167                         continue;
4168
4169                 /* Found the job where one of its processes changed its state.
4170                  * Is there at least one live and running process in this job? */
4171                 if (jobstate != JOBRUNNING) {
4172                         /* No. All live processes in the job are stopped
4173                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4174                          */
4175                         thisjob->changed = 1;
4176                         if (thisjob->state != jobstate) {
4177                                 TRACE(("Job %d: changing state from %d to %d\n",
4178                                         jobno(thisjob), thisjob->state, jobstate));
4179                                 thisjob->state = jobstate;
4180 #if JOBS
4181                                 if (jobstate == JOBSTOPPED)
4182                                         set_curjob(thisjob, CUR_STOPPED);
4183 #endif
4184                         }
4185                 }
4186                 goto out;
4187         }
4188         /* The process wasn't found in job list */
4189         if (JOBS && !WIFSTOPPED(status))
4190                 jobless--;
4191  out:
4192         INT_ON;
4193
4194         if (thisjob && thisjob == job) {
4195                 char s[48 + 1];
4196                 int len;
4197
4198                 len = sprint_status48(s, status, 1);
4199                 if (len) {
4200                         s[len] = '\n';
4201                         s[len + 1] = '\0';
4202                         out2str(s);
4203                 }
4204         }
4205         return pid;
4206 }
4207
4208 #if JOBS
4209 static void
4210 showjob(struct job *jp, int mode)
4211 {
4212         struct procstat *ps;
4213         struct procstat *psend;
4214         int col;
4215         int indent_col;
4216         char s[16 + 16 + 48];
4217         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4218
4219         ps = jp->ps;
4220
4221         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4222                 /* just output process (group) id of pipeline */
4223                 fprintf(out, "%d\n", ps->ps_pid);
4224                 return;
4225         }
4226
4227         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4228         indent_col = col;
4229
4230         if (jp == curjob)
4231                 s[col - 3] = '+';
4232         else if (curjob && jp == curjob->prev_job)
4233                 s[col - 3] = '-';
4234
4235         if (mode & SHOW_PIDS)
4236                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4237
4238         psend = ps + jp->nprocs;
4239
4240         if (jp->state == JOBRUNNING) {
4241                 strcpy(s + col, "Running");
4242                 col += sizeof("Running") - 1;
4243         } else {
4244                 int status = psend[-1].ps_status;
4245                 if (jp->state == JOBSTOPPED)
4246                         status = jp->stopstatus;
4247                 col += sprint_status48(s + col, status, 0);
4248         }
4249         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4250
4251         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4252          * or prints several "PID             | <cmdN>" lines,
4253          * depending on SHOW_PIDS bit.
4254          * We do not print status of individual processes
4255          * between PID and <cmdN>. bash does it, but not very well:
4256          * first line shows overall job status, not process status,
4257          * making it impossible to know 1st process status.
4258          */
4259         goto start;
4260         do {
4261                 /* for each process */
4262                 s[0] = '\0';
4263                 col = 33;
4264                 if (mode & SHOW_PIDS)
4265                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4266  start:
4267                 fprintf(out, "%s%*c%s%s",
4268                                 s,
4269                                 33 - col >= 0 ? 33 - col : 0, ' ',
4270                                 ps == jp->ps ? "" : "| ",
4271                                 ps->ps_cmd
4272                 );
4273         } while (++ps != psend);
4274         newline_and_flush(out);
4275
4276         jp->changed = 0;
4277
4278         if (jp->state == JOBDONE) {
4279                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4280                 freejob(jp);
4281         }
4282 }
4283
4284 /*
4285  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4286  * statuses have changed since the last call to showjobs.
4287  */
4288 static void
4289 showjobs(int mode)
4290 {
4291         struct job *jp;
4292
4293         TRACE(("showjobs(0x%x) called\n", mode));
4294
4295         /* Handle all finished jobs */
4296         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4297                 continue;
4298
4299         for (jp = curjob; jp; jp = jp->prev_job) {
4300                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4301                         showjob(jp, mode);
4302                 }
4303         }
4304 }
4305
4306 static int FAST_FUNC
4307 jobscmd(int argc UNUSED_PARAM, char **argv)
4308 {
4309         int mode, m;
4310
4311         mode = 0;
4312         while ((m = nextopt("lp")) != '\0') {
4313                 if (m == 'l')
4314                         mode |= SHOW_PIDS;
4315                 else
4316                         mode |= SHOW_ONLY_PGID;
4317         }
4318
4319         argv = argptr;
4320         if (*argv) {
4321                 do
4322                         showjob(getjob(*argv, 0), mode);
4323                 while (*++argv);
4324         } else {
4325                 showjobs(mode);
4326         }
4327
4328         return 0;
4329 }
4330 #endif /* JOBS */
4331
4332 /* Called only on finished or stopped jobs (no members are running) */
4333 static int
4334 getstatus(struct job *job)
4335 {
4336         int status;
4337         int retval;
4338         struct procstat *ps;
4339
4340         /* Fetch last member's status */
4341         ps = job->ps + job->nprocs - 1;
4342         status = ps->ps_status;
4343         if (pipefail) {
4344                 /* "set -o pipefail" mode: use last _nonzero_ status */
4345                 while (status == 0 && --ps >= job->ps)
4346                         status = ps->ps_status;
4347         }
4348
4349         retval = WEXITSTATUS(status);
4350         if (!WIFEXITED(status)) {
4351 #if JOBS
4352                 retval = WSTOPSIG(status);
4353                 if (!WIFSTOPPED(status))
4354 #endif
4355                 {
4356                         /* XXX: limits number of signals */
4357                         retval = WTERMSIG(status);
4358 #if JOBS
4359                         if (retval == SIGINT)
4360                                 job->sigint = 1;
4361 #endif
4362                 }
4363                 retval += 128;
4364         }
4365         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4366                 jobno(job), job->nprocs, status, retval));
4367         return retval;
4368 }
4369
4370 static int FAST_FUNC
4371 waitcmd(int argc UNUSED_PARAM, char **argv)
4372 {
4373         struct job *job;
4374         int retval;
4375         struct job *jp;
4376
4377         nextopt(nullstr);
4378         retval = 0;
4379
4380         argv = argptr;
4381         if (!*argv) {
4382                 /* wait for all jobs */
4383                 for (;;) {
4384                         jp = curjob;
4385                         while (1) {
4386                                 if (!jp) /* no running procs */
4387                                         goto ret;
4388                                 if (jp->state == JOBRUNNING)
4389                                         break;
4390                                 jp->waited = 1;
4391                                 jp = jp->prev_job;
4392                         }
4393         /* man bash:
4394          * "When bash is waiting for an asynchronous command via
4395          * the wait builtin, the reception of a signal for which a trap
4396          * has been set will cause the wait builtin to return immediately
4397          * with an exit status greater than 128, immediately after which
4398          * the trap is executed."
4399          */
4400                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4401         /* if child sends us a signal *and immediately exits*,
4402          * dowait() returns pid > 0. Check this case,
4403          * not "if (dowait() < 0)"!
4404          */
4405                         if (pending_sig)
4406                                 goto sigout;
4407                 }
4408         }
4409
4410         retval = 127;
4411         do {
4412                 if (**argv != '%') {
4413                         pid_t pid = number(*argv);
4414                         job = curjob;
4415                         while (1) {
4416                                 if (!job)
4417                                         goto repeat;
4418                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4419                                         break;
4420                                 job = job->prev_job;
4421                         }
4422                 } else {
4423                         job = getjob(*argv, 0);
4424                 }
4425                 /* loop until process terminated or stopped */
4426                 while (job->state == JOBRUNNING) {
4427                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4428                         if (pending_sig)
4429                                 goto sigout;
4430                 }
4431                 job->waited = 1;
4432                 retval = getstatus(job);
4433  repeat: ;
4434         } while (*++argv);
4435
4436  ret:
4437         return retval;
4438  sigout:
4439         retval = 128 + pending_sig;
4440         return retval;
4441 }
4442
4443 static struct job *
4444 growjobtab(void)
4445 {
4446         size_t len;
4447         ptrdiff_t offset;
4448         struct job *jp, *jq;
4449
4450         len = njobs * sizeof(*jp);
4451         jq = jobtab;
4452         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4453
4454         offset = (char *)jp - (char *)jq;
4455         if (offset) {
4456                 /* Relocate pointers */
4457                 size_t l = len;
4458
4459                 jq = (struct job *)((char *)jq + l);
4460                 while (l) {
4461                         l -= sizeof(*jp);
4462                         jq--;
4463 #define joff(p) ((struct job *)((char *)(p) + l))
4464 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4465                         if (joff(jp)->ps == &jq->ps0)
4466                                 jmove(joff(jp)->ps);
4467                         if (joff(jp)->prev_job)
4468                                 jmove(joff(jp)->prev_job);
4469                 }
4470                 if (curjob)
4471                         jmove(curjob);
4472 #undef joff
4473 #undef jmove
4474         }
4475
4476         njobs += 4;
4477         jobtab = jp;
4478         jp = (struct job *)((char *)jp + len);
4479         jq = jp + 3;
4480         do {
4481                 jq->used = 0;
4482         } while (--jq >= jp);
4483         return jp;
4484 }
4485
4486 /*
4487  * Return a new job structure.
4488  * Called with interrupts off.
4489  */
4490 static struct job *
4491 makejob(/*union node *node,*/ int nprocs)
4492 {
4493         int i;
4494         struct job *jp;
4495
4496         for (i = njobs, jp = jobtab; ; jp++) {
4497                 if (--i < 0) {
4498                         jp = growjobtab();
4499                         break;
4500                 }
4501                 if (jp->used == 0)
4502                         break;
4503                 if (jp->state != JOBDONE || !jp->waited)
4504                         continue;
4505 #if JOBS
4506                 if (doing_jobctl)
4507                         continue;
4508 #endif
4509                 freejob(jp);
4510                 break;
4511         }
4512         memset(jp, 0, sizeof(*jp));
4513 #if JOBS
4514         /* jp->jobctl is a bitfield.
4515          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4516         if (doing_jobctl)
4517                 jp->jobctl = 1;
4518 #endif
4519         jp->prev_job = curjob;
4520         curjob = jp;
4521         jp->used = 1;
4522         jp->ps = &jp->ps0;
4523         if (nprocs > 1) {
4524                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4525         }
4526         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4527                                 jobno(jp)));
4528         return jp;
4529 }
4530
4531 #if JOBS
4532 /*
4533  * Return a string identifying a command (to be printed by the
4534  * jobs command).
4535  */
4536 static char *cmdnextc;
4537
4538 static void
4539 cmdputs(const char *s)
4540 {
4541         static const char vstype[VSTYPE + 1][3] = {
4542                 "", "}", "-", "+", "?", "=",
4543                 "%", "%%", "#", "##"
4544                 IF_BASH_SUBSTR(, ":")
4545                 IF_BASH_PATTERN_SUBST(, "/", "//")
4546         };
4547
4548         const char *p, *str;
4549         char cc[2];
4550         char *nextc;
4551         unsigned char c;
4552         unsigned char subtype = 0;
4553         int quoted = 0;
4554
4555         cc[1] = '\0';
4556         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4557         p = s;
4558         while ((c = *p++) != '\0') {
4559                 str = NULL;
4560                 switch (c) {
4561                 case CTLESC:
4562                         c = *p++;
4563                         break;
4564                 case CTLVAR:
4565                         subtype = *p++;
4566                         if ((subtype & VSTYPE) == VSLENGTH)
4567                                 str = "${#";
4568                         else
4569                                 str = "${";
4570                         goto dostr;
4571                 case CTLENDVAR:
4572                         str = "\"}" + !(quoted & 1);
4573                         quoted >>= 1;
4574                         subtype = 0;
4575                         goto dostr;
4576                 case CTLBACKQ:
4577                         str = "$(...)";
4578                         goto dostr;
4579 #if ENABLE_FEATURE_SH_MATH
4580                 case CTLARI:
4581                         str = "$((";
4582                         goto dostr;
4583                 case CTLENDARI:
4584                         str = "))";
4585                         goto dostr;
4586 #endif
4587                 case CTLQUOTEMARK:
4588                         quoted ^= 1;
4589                         c = '"';
4590                         break;
4591                 case '=':
4592                         if (subtype == 0)
4593                                 break;
4594                         if ((subtype & VSTYPE) != VSNORMAL)
4595                                 quoted <<= 1;
4596                         str = vstype[subtype & VSTYPE];
4597                         if (subtype & VSNUL)
4598                                 c = ':';
4599                         else
4600                                 goto checkstr;
4601                         break;
4602                 case '\'':
4603                 case '\\':
4604                 case '"':
4605                 case '$':
4606                         /* These can only happen inside quotes */
4607                         cc[0] = c;
4608                         str = cc;
4609                         c = '\\';
4610                         break;
4611                 default:
4612                         break;
4613                 }
4614                 USTPUTC(c, nextc);
4615  checkstr:
4616                 if (!str)
4617                         continue;
4618  dostr:
4619                 while ((c = *str++) != '\0') {
4620                         USTPUTC(c, nextc);
4621                 }
4622         } /* while *p++ not NUL */
4623
4624         if (quoted & 1) {
4625                 USTPUTC('"', nextc);
4626         }
4627         *nextc = 0;
4628         cmdnextc = nextc;
4629 }
4630
4631 /* cmdtxt() and cmdlist() call each other */
4632 static void cmdtxt(union node *n);
4633
4634 static void
4635 cmdlist(union node *np, int sep)
4636 {
4637         for (; np; np = np->narg.next) {
4638                 if (!sep)
4639                         cmdputs(" ");
4640                 cmdtxt(np);
4641                 if (sep && np->narg.next)
4642                         cmdputs(" ");
4643         }
4644 }
4645
4646 static void
4647 cmdtxt(union node *n)
4648 {
4649         union node *np;
4650         struct nodelist *lp;
4651         const char *p;
4652
4653         if (!n)
4654                 return;
4655         switch (n->type) {
4656         default:
4657 #if DEBUG
4658                 abort();
4659 #endif
4660         case NPIPE:
4661                 lp = n->npipe.cmdlist;
4662                 for (;;) {
4663                         cmdtxt(lp->n);
4664                         lp = lp->next;
4665                         if (!lp)
4666                                 break;
4667                         cmdputs(" | ");
4668                 }
4669                 break;
4670         case NSEMI:
4671                 p = "; ";
4672                 goto binop;
4673         case NAND:
4674                 p = " && ";
4675                 goto binop;
4676         case NOR:
4677                 p = " || ";
4678  binop:
4679                 cmdtxt(n->nbinary.ch1);
4680                 cmdputs(p);
4681                 n = n->nbinary.ch2;
4682                 goto donode;
4683         case NREDIR:
4684         case NBACKGND:
4685                 n = n->nredir.n;
4686                 goto donode;
4687         case NNOT:
4688                 cmdputs("!");
4689                 n = n->nnot.com;
4690  donode:
4691                 cmdtxt(n);
4692                 break;
4693         case NIF:
4694                 cmdputs("if ");
4695                 cmdtxt(n->nif.test);
4696                 cmdputs("; then ");
4697                 if (n->nif.elsepart) {
4698                         cmdtxt(n->nif.ifpart);
4699                         cmdputs("; else ");
4700                         n = n->nif.elsepart;
4701                 } else {
4702                         n = n->nif.ifpart;
4703                 }
4704                 p = "; fi";
4705                 goto dotail;
4706         case NSUBSHELL:
4707                 cmdputs("(");
4708                 n = n->nredir.n;
4709                 p = ")";
4710                 goto dotail;
4711         case NWHILE:
4712                 p = "while ";
4713                 goto until;
4714         case NUNTIL:
4715                 p = "until ";
4716  until:
4717                 cmdputs(p);
4718                 cmdtxt(n->nbinary.ch1);
4719                 n = n->nbinary.ch2;
4720                 p = "; done";
4721  dodo:
4722                 cmdputs("; do ");
4723  dotail:
4724                 cmdtxt(n);
4725                 goto dotail2;
4726         case NFOR:
4727                 cmdputs("for ");
4728                 cmdputs(n->nfor.var);
4729                 cmdputs(" in ");
4730                 cmdlist(n->nfor.args, 1);
4731                 n = n->nfor.body;
4732                 p = "; done";
4733                 goto dodo;
4734         case NDEFUN:
4735                 cmdputs(n->narg.text);
4736                 p = "() { ... }";
4737                 goto dotail2;
4738         case NCMD:
4739                 cmdlist(n->ncmd.args, 1);
4740                 cmdlist(n->ncmd.redirect, 0);
4741                 break;
4742         case NARG:
4743                 p = n->narg.text;
4744  dotail2:
4745                 cmdputs(p);
4746                 break;
4747         case NHERE:
4748         case NXHERE:
4749                 p = "<<...";
4750                 goto dotail2;
4751         case NCASE:
4752                 cmdputs("case ");
4753                 cmdputs(n->ncase.expr->narg.text);
4754                 cmdputs(" in ");
4755                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4756                         cmdtxt(np->nclist.pattern);
4757                         cmdputs(") ");
4758                         cmdtxt(np->nclist.body);
4759                         cmdputs(";; ");
4760                 }
4761                 p = "esac";
4762                 goto dotail2;
4763         case NTO:
4764                 p = ">";
4765                 goto redir;
4766         case NCLOBBER:
4767                 p = ">|";
4768                 goto redir;
4769         case NAPPEND:
4770                 p = ">>";
4771                 goto redir;
4772 #if BASH_REDIR_OUTPUT
4773         case NTO2:
4774 #endif
4775         case NTOFD:
4776                 p = ">&";
4777                 goto redir;
4778         case NFROM:
4779                 p = "<";
4780                 goto redir;
4781         case NFROMFD:
4782                 p = "<&";
4783                 goto redir;
4784         case NFROMTO:
4785                 p = "<>";
4786  redir:
4787                 cmdputs(utoa(n->nfile.fd));
4788                 cmdputs(p);
4789                 if (n->type == NTOFD || n->type == NFROMFD) {
4790                         cmdputs(utoa(n->ndup.dupfd));
4791                         break;
4792                 }
4793                 n = n->nfile.fname;
4794                 goto donode;
4795         }
4796 }
4797
4798 static char *
4799 commandtext(union node *n)
4800 {
4801         char *name;
4802
4803         STARTSTACKSTR(cmdnextc);
4804         cmdtxt(n);
4805         name = stackblock();
4806         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4807         return ckstrdup(name);
4808 }
4809 #endif /* JOBS */
4810
4811 /*
4812  * Fork off a subshell.  If we are doing job control, give the subshell its
4813  * own process group.  Jp is a job structure that the job is to be added to.
4814  * N is the command that will be evaluated by the child.  Both jp and n may
4815  * be NULL.  The mode parameter can be one of the following:
4816  *      FORK_FG - Fork off a foreground process.
4817  *      FORK_BG - Fork off a background process.
4818  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4819  *                   process group even if job control is on.
4820  *
4821  * When job control is turned off, background processes have their standard
4822  * input redirected to /dev/null (except for the second and later processes
4823  * in a pipeline).
4824  *
4825  * Called with interrupts off.
4826  */
4827 /*
4828  * Clear traps on a fork.
4829  */
4830 static void
4831 clear_traps(void)
4832 {
4833         char **tp;
4834
4835         INT_OFF;
4836         for (tp = trap; tp < &trap[NSIG]; tp++) {
4837                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4838                         if (trap_ptr == trap)
4839                                 free(*tp);
4840                         /* else: it "belongs" to trap_ptr vector, don't free */
4841                         *tp = NULL;
4842                         if ((tp - trap) != 0)
4843                                 setsignal(tp - trap);
4844                 }
4845         }
4846         may_have_traps = 0;
4847         INT_ON;
4848 }
4849
4850 /* Lives far away from here, needed for forkchild */
4851 static void closescript(void);
4852
4853 /* Called after fork(), in child */
4854 /* jp and n are NULL when called by openhere() for heredoc support */
4855 static NOINLINE void
4856 forkchild(struct job *jp, union node *n, int mode)
4857 {
4858         int oldlvl;
4859
4860         TRACE(("Child shell %d\n", getpid()));
4861         oldlvl = shlvl;
4862         shlvl++;
4863
4864         /* man bash: "Non-builtin commands run by bash have signal handlers
4865          * set to the values inherited by the shell from its parent".
4866          * Do we do it correctly? */
4867
4868         closescript();
4869
4870         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4871          && n && n->type == NCMD        /* is it single cmd? */
4872         /* && n->ncmd.args->type == NARG - always true? */
4873          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4874          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4875         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4876         ) {
4877                 TRACE(("Trap hack\n"));
4878                 /* Awful hack for `trap` or $(trap).
4879                  *
4880                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4881                  * contains an example where "trap" is executed in a subshell:
4882                  *
4883                  * save_traps=$(trap)
4884                  * ...
4885                  * eval "$save_traps"
4886                  *
4887                  * Standard does not say that "trap" in subshell shall print
4888                  * parent shell's traps. It only says that its output
4889                  * must have suitable form, but then, in the above example
4890                  * (which is not supposed to be normative), it implies that.
4891                  *
4892                  * bash (and probably other shell) does implement it
4893                  * (traps are reset to defaults, but "trap" still shows them),
4894                  * but as a result, "trap" logic is hopelessly messed up:
4895                  *
4896                  * # trap
4897                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4898                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4899                  * # true | trap   <--- trap is in subshell - no output (ditto)
4900                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4901                  * trap -- 'echo Ho' SIGWINCH
4902                  * # echo `(trap)`         <--- in subshell in subshell - output
4903                  * trap -- 'echo Ho' SIGWINCH
4904                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4905                  * trap -- 'echo Ho' SIGWINCH
4906                  *
4907                  * The rules when to forget and when to not forget traps
4908                  * get really complex and nonsensical.
4909                  *
4910                  * Our solution: ONLY bare $(trap) or `trap` is special.
4911                  */
4912                 /* Save trap handler strings for trap builtin to print */
4913                 trap_ptr = xmemdup(trap, sizeof(trap));
4914                 /* Fall through into clearing traps */
4915         }
4916         clear_traps();
4917 #if JOBS
4918         /* do job control only in root shell */
4919         doing_jobctl = 0;
4920         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4921                 pid_t pgrp;
4922
4923                 if (jp->nprocs == 0)
4924                         pgrp = getpid();
4925                 else
4926                         pgrp = jp->ps[0].ps_pid;
4927                 /* this can fail because we are doing it in the parent also */
4928                 setpgid(0, pgrp);
4929                 if (mode == FORK_FG)
4930                         xtcsetpgrp(ttyfd, pgrp);
4931                 setsignal(SIGTSTP);
4932                 setsignal(SIGTTOU);
4933         } else
4934 #endif
4935         if (mode == FORK_BG) {
4936                 /* man bash: "When job control is not in effect,
4937                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4938                 ignoresig(SIGINT);
4939                 ignoresig(SIGQUIT);
4940                 if (jp->nprocs == 0) {
4941                         close(0);
4942                         if (open(bb_dev_null, O_RDONLY) != 0)
4943                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4944                 }
4945         }
4946         if (oldlvl == 0) {
4947                 if (iflag) { /* why if iflag only? */
4948                         setsignal(SIGINT);
4949                         setsignal(SIGTERM);
4950                 }
4951                 /* man bash:
4952                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4953                  * commands run by bash have signal handlers
4954                  * set to the values inherited by the shell
4955                  * from its parent".
4956                  * Take care of the second rule: */
4957                 setsignal(SIGQUIT);
4958         }
4959 #if JOBS
4960         if (n && n->type == NCMD
4961          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4962         ) {
4963                 TRACE(("Job hack\n"));
4964                 /* "jobs": we do not want to clear job list for it,
4965                  * instead we remove only _its_ own_ job from job list.
4966                  * This makes "jobs .... | cat" more useful.
4967                  */
4968                 freejob(curjob);
4969                 return;
4970         }
4971 #endif
4972         for (jp = curjob; jp; jp = jp->prev_job)
4973                 freejob(jp);
4974         jobless = 0;
4975 }
4976
4977 /* Called after fork(), in parent */
4978 #if !JOBS
4979 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4980 #endif
4981 static void
4982 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4983 {
4984         TRACE(("In parent shell: child = %d\n", pid));
4985         if (!jp) {
4986                 /* jp is NULL when called by openhere() for heredoc support */
4987                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4988                         continue;
4989                 jobless++;
4990                 return;
4991         }
4992 #if JOBS
4993         if (mode != FORK_NOJOB && jp->jobctl) {
4994                 int pgrp;
4995
4996                 if (jp->nprocs == 0)
4997                         pgrp = pid;
4998                 else
4999                         pgrp = jp->ps[0].ps_pid;
5000                 /* This can fail because we are doing it in the child also */
5001                 setpgid(pid, pgrp);
5002         }
5003 #endif
5004         if (mode == FORK_BG) {
5005                 backgndpid = pid;               /* set $! */
5006                 set_curjob(jp, CUR_RUNNING);
5007         }
5008         if (jp) {
5009                 struct procstat *ps = &jp->ps[jp->nprocs++];
5010                 ps->ps_pid = pid;
5011                 ps->ps_status = -1;
5012                 ps->ps_cmd = nullstr;
5013 #if JOBS
5014                 if (doing_jobctl && n)
5015                         ps->ps_cmd = commandtext(n);
5016 #endif
5017         }
5018 }
5019
5020 /* jp and n are NULL when called by openhere() for heredoc support */
5021 static int
5022 forkshell(struct job *jp, union node *n, int mode)
5023 {
5024         int pid;
5025
5026         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5027         pid = fork();
5028         if (pid < 0) {
5029                 TRACE(("Fork failed, errno=%d", errno));
5030                 if (jp)
5031                         freejob(jp);
5032                 ash_msg_and_raise_error("can't fork");
5033         }
5034         if (pid == 0) {
5035                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5036                 forkchild(jp, n, mode);
5037         } else {
5038                 forkparent(jp, n, mode, pid);
5039         }
5040         return pid;
5041 }
5042
5043 /*
5044  * Wait for job to finish.
5045  *
5046  * Under job control we have the problem that while a child process
5047  * is running interrupts generated by the user are sent to the child
5048  * but not to the shell.  This means that an infinite loop started by
5049  * an interactive user may be hard to kill.  With job control turned off,
5050  * an interactive user may place an interactive program inside a loop.
5051  * If the interactive program catches interrupts, the user doesn't want
5052  * these interrupts to also abort the loop.  The approach we take here
5053  * is to have the shell ignore interrupt signals while waiting for a
5054  * foreground process to terminate, and then send itself an interrupt
5055  * signal if the child process was terminated by an interrupt signal.
5056  * Unfortunately, some programs want to do a bit of cleanup and then
5057  * exit on interrupt; unless these processes terminate themselves by
5058  * sending a signal to themselves (instead of calling exit) they will
5059  * confuse this approach.
5060  *
5061  * Called with interrupts off.
5062  */
5063 static int
5064 waitforjob(struct job *jp)
5065 {
5066         int st;
5067
5068         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5069
5070         INT_OFF;
5071         while (jp->state == JOBRUNNING) {
5072                 /* In non-interactive shells, we _can_ get
5073                  * a keyboard signal here and be EINTRed,
5074                  * but we just loop back, waiting for command to complete.
5075                  *
5076                  * man bash:
5077                  * "If bash is waiting for a command to complete and receives
5078                  * a signal for which a trap has been set, the trap
5079                  * will not be executed until the command completes."
5080                  *
5081                  * Reality is that even if trap is not set, bash
5082                  * will not act on the signal until command completes.
5083                  * Try this. sleep5intoff.c:
5084                  * #include <signal.h>
5085                  * #include <unistd.h>
5086                  * int main() {
5087                  *         sigset_t set;
5088                  *         sigemptyset(&set);
5089                  *         sigaddset(&set, SIGINT);
5090                  *         sigaddset(&set, SIGQUIT);
5091                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5092                  *         sleep(5);
5093                  *         return 0;
5094                  * }
5095                  * $ bash -c './sleep5intoff; echo hi'
5096                  * ^C^C^C^C <--- pressing ^C once a second
5097                  * $ _
5098                  * $ bash -c './sleep5intoff; echo hi'
5099                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5100                  * $ _
5101                  */
5102                 dowait(DOWAIT_BLOCK, jp);
5103         }
5104         INT_ON;
5105
5106         st = getstatus(jp);
5107 #if JOBS
5108         if (jp->jobctl) {
5109                 xtcsetpgrp(ttyfd, rootpid);
5110                 restore_tty_if_stopped_or_signaled(jp);
5111
5112                 /*
5113                  * This is truly gross.
5114                  * If we're doing job control, then we did a TIOCSPGRP which
5115                  * caused us (the shell) to no longer be in the controlling
5116                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5117                  * intuit from the subprocess exit status whether a SIGINT
5118                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5119                  */
5120                 if (jp->sigint) /* TODO: do the same with all signals */
5121                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5122         }
5123         if (jp->state == JOBDONE)
5124 #endif
5125                 freejob(jp);
5126         return st;
5127 }
5128
5129 /*
5130  * return 1 if there are stopped jobs, otherwise 0
5131  */
5132 static int
5133 stoppedjobs(void)
5134 {
5135         struct job *jp;
5136         int retval;
5137
5138         retval = 0;
5139         if (job_warning)
5140                 goto out;
5141         jp = curjob;
5142         if (jp && jp->state == JOBSTOPPED) {
5143                 out2str("You have stopped jobs.\n");
5144                 job_warning = 2;
5145                 retval++;
5146         }
5147  out:
5148         return retval;
5149 }
5150
5151
5152 /*
5153  * Code for dealing with input/output redirection.
5154  */
5155
5156 #undef EMPTY
5157 #undef CLOSED
5158 #define EMPTY -2                /* marks an unused slot in redirtab */
5159 #define CLOSED -3               /* marks a slot of previously-closed fd */
5160
5161 /*
5162  * Open a file in noclobber mode.
5163  * The code was copied from bash.
5164  */
5165 static int
5166 noclobberopen(const char *fname)
5167 {
5168         int r, fd;
5169         struct stat finfo, finfo2;
5170
5171         /*
5172          * If the file exists and is a regular file, return an error
5173          * immediately.
5174          */
5175         r = stat(fname, &finfo);
5176         if (r == 0 && S_ISREG(finfo.st_mode)) {
5177                 errno = EEXIST;
5178                 return -1;
5179         }
5180
5181         /*
5182          * If the file was not present (r != 0), make sure we open it
5183          * exclusively so that if it is created before we open it, our open
5184          * will fail.  Make sure that we do not truncate an existing file.
5185          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5186          * file was not a regular file, we leave O_EXCL off.
5187          */
5188         if (r != 0)
5189                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5190         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5191
5192         /* If the open failed, return the file descriptor right away. */
5193         if (fd < 0)
5194                 return fd;
5195
5196         /*
5197          * OK, the open succeeded, but the file may have been changed from a
5198          * non-regular file to a regular file between the stat and the open.
5199          * We are assuming that the O_EXCL open handles the case where FILENAME
5200          * did not exist and is symlinked to an existing file between the stat
5201          * and open.
5202          */
5203
5204         /*
5205          * If we can open it and fstat the file descriptor, and neither check
5206          * revealed that it was a regular file, and the file has not been
5207          * replaced, return the file descriptor.
5208          */
5209         if (fstat(fd, &finfo2) == 0
5210          && !S_ISREG(finfo2.st_mode)
5211          && finfo.st_dev == finfo2.st_dev
5212          && finfo.st_ino == finfo2.st_ino
5213         ) {
5214                 return fd;
5215         }
5216
5217         /* The file has been replaced.  badness. */
5218         close(fd);
5219         errno = EEXIST;
5220         return -1;
5221 }
5222
5223 /*
5224  * Handle here documents.  Normally we fork off a process to write the
5225  * data to a pipe.  If the document is short, we can stuff the data in
5226  * the pipe without forking.
5227  */
5228 /* openhere needs this forward reference */
5229 static void expandhere(union node *arg, int fd);
5230 static int
5231 openhere(union node *redir)
5232 {
5233         int pip[2];
5234         size_t len = 0;
5235
5236         if (pipe(pip) < 0)
5237                 ash_msg_and_raise_error("pipe call failed");
5238         if (redir->type == NHERE) {
5239                 len = strlen(redir->nhere.doc->narg.text);
5240                 if (len <= PIPE_BUF) {
5241                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5242                         goto out;
5243                 }
5244         }
5245         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5246                 /* child */
5247                 close(pip[0]);
5248                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5249                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5250                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5251                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5252                 signal(SIGPIPE, SIG_DFL);
5253                 if (redir->type == NHERE)
5254                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5255                 else /* NXHERE */
5256                         expandhere(redir->nhere.doc, pip[1]);
5257                 _exit(EXIT_SUCCESS);
5258         }
5259  out:
5260         close(pip[1]);
5261         return pip[0];
5262 }
5263
5264 static int
5265 openredirect(union node *redir)
5266 {
5267         char *fname;
5268         int f;
5269
5270         switch (redir->nfile.type) {
5271 /* Can't happen, our single caller does this itself */
5272 //      case NTOFD:
5273 //      case NFROMFD:
5274 //              return -1;
5275         case NHERE:
5276         case NXHERE:
5277                 return openhere(redir);
5278         }
5279
5280         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5281          * allocated space. Do it only when we know it is safe.
5282          */
5283         fname = redir->nfile.expfname;
5284
5285         switch (redir->nfile.type) {
5286         default:
5287 #if DEBUG
5288                 abort();
5289 #endif
5290         case NFROM:
5291                 f = open(fname, O_RDONLY);
5292                 if (f < 0)
5293                         goto eopen;
5294                 break;
5295         case NFROMTO:
5296                 f = open(fname, O_RDWR|O_CREAT, 0666);
5297                 if (f < 0)
5298                         goto ecreate;
5299                 break;
5300         case NTO:
5301 #if BASH_REDIR_OUTPUT
5302         case NTO2:
5303 #endif
5304                 /* Take care of noclobber mode. */
5305                 if (Cflag) {
5306                         f = noclobberopen(fname);
5307                         if (f < 0)
5308                                 goto ecreate;
5309                         break;
5310                 }
5311                 /* FALLTHROUGH */
5312         case NCLOBBER:
5313                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5314                 if (f < 0)
5315                         goto ecreate;
5316                 break;
5317         case NAPPEND:
5318                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5319                 if (f < 0)
5320                         goto ecreate;
5321                 break;
5322         }
5323
5324         return f;
5325  ecreate:
5326         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5327  eopen:
5328         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5329 }
5330
5331 /*
5332  * Copy a file descriptor to be >= 10. Throws exception on error.
5333  */
5334 static int
5335 savefd(int from)
5336 {
5337         int newfd;
5338         int err;
5339
5340         newfd = fcntl(from, F_DUPFD, 10);
5341         err = newfd < 0 ? errno : 0;
5342         if (err != EBADF) {
5343                 if (err)
5344                         ash_msg_and_raise_error("%d: %m", from);
5345                 close(from);
5346                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5347         }
5348
5349         return newfd;
5350 }
5351 static int
5352 dup2_or_raise(int from, int to)
5353 {
5354         int newfd;
5355
5356         newfd = (from != to) ? dup2(from, to) : to;
5357         if (newfd < 0) {
5358                 /* Happens when source fd is not open: try "echo >&99" */
5359                 ash_msg_and_raise_error("%d: %m", from);
5360         }
5361         return newfd;
5362 }
5363
5364 /* Struct def and variable are moved down to the first usage site */
5365 struct two_fd_t {
5366         int orig, copy;
5367 };
5368 struct redirtab {
5369         struct redirtab *next;
5370         int pair_count;
5371         struct two_fd_t two_fd[];
5372 };
5373 #define redirlist (G_var.redirlist)
5374 enum {
5375         COPYFD_RESTORE = (int)~(INT_MAX),
5376 };
5377
5378 static int
5379 need_to_remember(struct redirtab *rp, int fd)
5380 {
5381         int i;
5382
5383         if (!rp) /* remembering was not requested */
5384                 return 0;
5385
5386         for (i = 0; i < rp->pair_count; i++) {
5387                 if (rp->two_fd[i].orig == fd) {
5388                         /* already remembered */
5389                         return 0;
5390                 }
5391         }
5392         return 1;
5393 }
5394
5395 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5396 static int
5397 is_hidden_fd(struct redirtab *rp, int fd)
5398 {
5399         int i;
5400         struct parsefile *pf;
5401
5402         if (fd == -1)
5403                 return 0;
5404         /* Check open scripts' fds */
5405         pf = g_parsefile;
5406         while (pf) {
5407                 /* We skip pf_fd == 0 case because of the following case:
5408                  * $ ash  # running ash interactively
5409                  * $ . ./script.sh
5410                  * and in script.sh: "exec 9>&0".
5411                  * Even though top-level pf_fd _is_ 0,
5412                  * it's still ok to use it: "read" builtin uses it,
5413                  * why should we cripple "exec" builtin?
5414                  */
5415                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5416                         return 1;
5417                 }
5418                 pf = pf->prev;
5419         }
5420
5421         if (!rp)
5422                 return 0;
5423         /* Check saved fds of redirects */
5424         fd |= COPYFD_RESTORE;
5425         for (i = 0; i < rp->pair_count; i++) {
5426                 if (rp->two_fd[i].copy == fd) {
5427                         return 1;
5428                 }
5429         }
5430         return 0;
5431 }
5432
5433 /*
5434  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5435  * old file descriptors are stashed away so that the redirection can be
5436  * undone by calling popredir.
5437  */
5438 /* flags passed to redirect */
5439 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5440 #define REDIR_SAVEFD2 03        /* set preverrout */
5441 static void
5442 redirect(union node *redir, int flags)
5443 {
5444         struct redirtab *sv;
5445         int sv_pos;
5446         int i;
5447         int fd;
5448         int newfd;
5449         int copied_fd2 = -1;
5450
5451         if (!redir) {
5452                 return;
5453         }
5454
5455         sv = NULL;
5456         sv_pos = 0;
5457         INT_OFF;
5458         if (flags & REDIR_PUSH) {
5459                 union node *tmp = redir;
5460                 do {
5461                         sv_pos++;
5462 #if BASH_REDIR_OUTPUT
5463                         if (tmp->nfile.type == NTO2)
5464                                 sv_pos++;
5465 #endif
5466                         tmp = tmp->nfile.next;
5467                 } while (tmp);
5468                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5469                 sv->next = redirlist;
5470                 sv->pair_count = sv_pos;
5471                 redirlist = sv;
5472                 while (sv_pos > 0) {
5473                         sv_pos--;
5474                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5475                 }
5476         }
5477
5478         do {
5479                 int right_fd = -1;
5480                 fd = redir->nfile.fd;
5481                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5482                         right_fd = redir->ndup.dupfd;
5483                         //bb_error_msg("doing %d > %d", fd, right_fd);
5484                         /* redirect from/to same file descriptor? */
5485                         if (right_fd == fd)
5486                                 continue;
5487                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5488                         if (is_hidden_fd(sv, right_fd)) {
5489                                 errno = EBADF; /* as if it is closed */
5490                                 ash_msg_and_raise_error("%d: %m", right_fd);
5491                         }
5492                         newfd = -1;
5493                 } else {
5494                         newfd = openredirect(redir); /* always >= 0 */
5495                         if (fd == newfd) {
5496                                 /* Descriptor wasn't open before redirect.
5497                                  * Mark it for close in the future */
5498                                 if (need_to_remember(sv, fd)) {
5499                                         goto remember_to_close;
5500                                 }
5501                                 continue;
5502                         }
5503                 }
5504 #if BASH_REDIR_OUTPUT
5505  redirect_more:
5506 #endif
5507                 if (need_to_remember(sv, fd)) {
5508                         /* Copy old descriptor */
5509                         /* Careful to not accidentally "save"
5510                          * to the same fd as right side fd in N>&M */
5511                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5512 #if defined(F_DUPFD_CLOEXEC)
5513                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5514 #else
5515                         i = fcntl(fd, F_DUPFD, minfd);
5516 #endif
5517                         if (i == -1) {
5518                                 i = errno;
5519                                 if (i != EBADF) {
5520                                         /* Strange error (e.g. "too many files" EMFILE?) */
5521                                         if (newfd >= 0)
5522                                                 close(newfd);
5523                                         errno = i;
5524                                         ash_msg_and_raise_error("%d: %m", fd);
5525                                         /* NOTREACHED */
5526                                 }
5527                                 /* EBADF: it is not open - good, remember to close it */
5528  remember_to_close:
5529                                 i = CLOSED;
5530                         } else { /* fd is open, save its copy */
5531 #if !defined(F_DUPFD_CLOEXEC)
5532                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5533 #endif
5534                                 /* "exec fd>&-" should not close fds
5535                                  * which point to script file(s).
5536                                  * Force them to be restored afterwards */
5537                                 if (is_hidden_fd(sv, fd))
5538                                         i |= COPYFD_RESTORE;
5539                         }
5540                         if (fd == 2)
5541                                 copied_fd2 = i;
5542                         sv->two_fd[sv_pos].orig = fd;
5543                         sv->two_fd[sv_pos].copy = i;
5544                         sv_pos++;
5545                 }
5546                 if (newfd < 0) {
5547                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5548                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5549                                 /* Don't want to trigger debugging */
5550                                 if (fd != -1)
5551                                         close(fd);
5552                         } else {
5553                                 dup2_or_raise(redir->ndup.dupfd, fd);
5554                         }
5555                 } else if (fd != newfd) { /* move newfd to fd */
5556                         dup2_or_raise(newfd, fd);
5557 #if BASH_REDIR_OUTPUT
5558                         if (!(redir->nfile.type == NTO2 && fd == 2))
5559 #endif
5560                                 close(newfd);
5561                 }
5562 #if BASH_REDIR_OUTPUT
5563                 if (redir->nfile.type == NTO2 && fd == 1) {
5564                         /* We already redirected it to fd 1, now copy it to 2 */
5565                         newfd = 1;
5566                         fd = 2;
5567                         goto redirect_more;
5568                 }
5569 #endif
5570         } while ((redir = redir->nfile.next) != NULL);
5571
5572         INT_ON;
5573         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5574                 preverrout_fd = copied_fd2;
5575 }
5576
5577 /*
5578  * Undo the effects of the last redirection.
5579  */
5580 static void
5581 popredir(int drop, int restore)
5582 {
5583         struct redirtab *rp;
5584         int i;
5585
5586         if (redirlist == NULL)
5587                 return;
5588         INT_OFF;
5589         rp = redirlist;
5590         for (i = 0; i < rp->pair_count; i++) {
5591                 int fd = rp->two_fd[i].orig;
5592                 int copy = rp->two_fd[i].copy;
5593                 if (copy == CLOSED) {
5594                         if (!drop)
5595                                 close(fd);
5596                         continue;
5597                 }
5598                 if (copy != EMPTY) {
5599                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5600                                 copy &= ~COPYFD_RESTORE;
5601                                 /*close(fd);*/
5602                                 dup2_or_raise(copy, fd);
5603                         }
5604                         close(copy & ~COPYFD_RESTORE);
5605                 }
5606         }
5607         redirlist = rp->next;
5608         free(rp);
5609         INT_ON;
5610 }
5611
5612 /*
5613  * Undo all redirections.  Called on error or interrupt.
5614  */
5615
5616 static int
5617 redirectsafe(union node *redir, int flags)
5618 {
5619         int err;
5620         volatile int saveint;
5621         struct jmploc *volatile savehandler = exception_handler;
5622         struct jmploc jmploc;
5623
5624         SAVE_INT(saveint);
5625         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5626         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5627         if (!err) {
5628                 exception_handler = &jmploc;
5629                 redirect(redir, flags);
5630         }
5631         exception_handler = savehandler;
5632         if (err && exception_type != EXERROR)
5633                 longjmp(exception_handler->loc, 1);
5634         RESTORE_INT(saveint);
5635         return err;
5636 }
5637
5638
5639 /* ============ Routines to expand arguments to commands
5640  *
5641  * We have to deal with backquotes, shell variables, and file metacharacters.
5642  */
5643
5644 #if ENABLE_FEATURE_SH_MATH
5645 static arith_t
5646 ash_arith(const char *s)
5647 {
5648         arith_state_t math_state;
5649         arith_t result;
5650
5651         math_state.lookupvar = lookupvar;
5652         math_state.setvar    = setvar0;
5653         //math_state.endofname = endofname;
5654
5655         INT_OFF;
5656         result = arith(&math_state, s);
5657         if (math_state.errmsg)
5658                 ash_msg_and_raise_error(math_state.errmsg);
5659         INT_ON;
5660
5661         return result;
5662 }
5663 #endif
5664
5665 /*
5666  * expandarg flags
5667  */
5668 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5669 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5670 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5671 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5672 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5673  * POSIX says for this case:
5674  *  Pathname expansion shall not be performed on the word by a
5675  *  non-interactive shell; an interactive shell may perform it, but shall
5676  *  do so only when the expansion would result in one word.
5677  * Currently, our code complies to the above rule by never globbing
5678  * redirection filenames.
5679  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5680  * (this means that on a typical Linux distro, bash almost always
5681  * performs globbing, and thus diverges from what we do).
5682  */
5683 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5684 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5685 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5686 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5687 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5688 /*
5689  * rmescape() flags
5690  */
5691 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5692 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5693 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5694 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5695 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5696
5697 /* Add CTLESC when necessary. */
5698 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR)
5699 /* Do not skip NUL characters. */
5700 #define QUOTES_KEEPNUL EXP_TILDE
5701
5702 /*
5703  * Structure specifying which parts of the string should be searched
5704  * for IFS characters.
5705  */
5706 struct ifsregion {
5707         struct ifsregion *next; /* next region in list */
5708         int begoff;             /* offset of start of region */
5709         int endoff;             /* offset of end of region */
5710         int nulonly;            /* search for nul bytes only */
5711 };
5712
5713 struct arglist {
5714         struct strlist *list;
5715         struct strlist **lastp;
5716 };
5717
5718 /* output of current string */
5719 static char *expdest;
5720 /* list of back quote expressions */
5721 static struct nodelist *argbackq;
5722 /* first struct in list of ifs regions */
5723 static struct ifsregion ifsfirst;
5724 /* last struct in list */
5725 static struct ifsregion *ifslastp;
5726 /* holds expanded arg list */
5727 static struct arglist exparg;
5728
5729 /*
5730  * Our own itoa().
5731  */
5732 #if !ENABLE_FEATURE_SH_MATH
5733 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5734 typedef long arith_t;
5735 # define ARITH_FMT "%ld"
5736 #endif
5737 static int
5738 cvtnum(arith_t num)
5739 {
5740         int len;
5741
5742         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5743         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5744         STADJUST(len, expdest);
5745         return len;
5746 }
5747
5748 /*
5749  * Break the argument string into pieces based upon IFS and add the
5750  * strings to the argument list.  The regions of the string to be
5751  * searched for IFS characters have been stored by recordregion.
5752  */
5753 static void
5754 ifsbreakup(char *string, struct arglist *arglist)
5755 {
5756         struct ifsregion *ifsp;
5757         struct strlist *sp;
5758         char *start;
5759         char *p;
5760         char *q;
5761         const char *ifs, *realifs;
5762         int ifsspc;
5763         int nulonly;
5764
5765         start = string;
5766         if (ifslastp != NULL) {
5767                 ifsspc = 0;
5768                 nulonly = 0;
5769                 realifs = ifsset() ? ifsval() : defifs;
5770                 ifsp = &ifsfirst;
5771                 do {
5772                         p = string + ifsp->begoff;
5773                         nulonly = ifsp->nulonly;
5774                         ifs = nulonly ? nullstr : realifs;
5775                         ifsspc = 0;
5776                         while (p < string + ifsp->endoff) {
5777                                 q = p;
5778                                 if ((unsigned char)*p == CTLESC)
5779                                         p++;
5780                                 if (!strchr(ifs, *p)) {
5781                                         p++;
5782                                         continue;
5783                                 }
5784                                 if (!nulonly)
5785                                         ifsspc = (strchr(defifs, *p) != NULL);
5786                                 /* Ignore IFS whitespace at start */
5787                                 if (q == start && ifsspc) {
5788                                         p++;
5789                                         start = p;
5790                                         continue;
5791                                 }
5792                                 *q = '\0';
5793                                 sp = stzalloc(sizeof(*sp));
5794                                 sp->text = start;
5795                                 *arglist->lastp = sp;
5796                                 arglist->lastp = &sp->next;
5797                                 p++;
5798                                 if (!nulonly) {
5799                                         for (;;) {
5800                                                 if (p >= string + ifsp->endoff) {
5801                                                         break;
5802                                                 }
5803                                                 q = p;
5804                                                 if ((unsigned char)*p == CTLESC)
5805                                                         p++;
5806                                                 if (strchr(ifs, *p) == NULL) {
5807                                                         p = q;
5808                                                         break;
5809                                                 }
5810                                                 if (strchr(defifs, *p) == NULL) {
5811                                                         if (ifsspc) {
5812                                                                 p++;
5813                                                                 ifsspc = 0;
5814                                                         } else {
5815                                                                 p = q;
5816                                                                 break;
5817                                                         }
5818                                                 } else
5819                                                         p++;
5820                                         }
5821                                 }
5822                                 start = p;
5823                         } /* while */
5824                         ifsp = ifsp->next;
5825                 } while (ifsp != NULL);
5826                 if (nulonly)
5827                         goto add;
5828         }
5829
5830         if (!*start)
5831                 return;
5832
5833  add:
5834         sp = stzalloc(sizeof(*sp));
5835         sp->text = start;
5836         *arglist->lastp = sp;
5837         arglist->lastp = &sp->next;
5838 }
5839
5840 static void
5841 ifsfree(void)
5842 {
5843         struct ifsregion *p = ifsfirst.next;
5844
5845         if (!p)
5846                 goto out;
5847
5848         INT_OFF;
5849         do {
5850                 struct ifsregion *ifsp;
5851                 ifsp = p->next;
5852                 free(p);
5853                 p = ifsp;
5854         } while (p);
5855         ifsfirst.next = NULL;
5856         INT_ON;
5857  out:
5858         ifslastp = NULL;
5859 }
5860
5861 static size_t
5862 esclen(const char *start, const char *p)
5863 {
5864         size_t esc = 0;
5865
5866         while (p > start && (unsigned char)*--p == CTLESC) {
5867                 esc++;
5868         }
5869         return esc;
5870 }
5871
5872 /*
5873  * Remove any CTLESC characters from a string.
5874  */
5875 static char *
5876 rmescapes(char *str, int flag)
5877 {
5878         static const char qchars[] ALIGN1 = {
5879                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5880
5881         char *p, *q, *r;
5882         unsigned inquotes;
5883         unsigned protect_against_glob;
5884         unsigned globbing;
5885         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5886
5887         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5888         if (!p)
5889                 return str;
5890
5891         q = p;
5892         r = str;
5893         if (flag & RMESCAPE_ALLOC) {
5894                 size_t len = p - str;
5895                 size_t fulllen = len + strlen(p) + 1;
5896
5897                 if (flag & RMESCAPE_GROW) {
5898                         int strloc = str - (char *)stackblock();
5899                         r = makestrspace(fulllen, expdest);
5900                         /* p and str may be invalidated by makestrspace */
5901                         str = (char *)stackblock() + strloc;
5902                         p = str + len;
5903                 } else if (flag & RMESCAPE_HEAP) {
5904                         r = ckmalloc(fulllen);
5905                 } else {
5906                         r = stalloc(fulllen);
5907                 }
5908                 q = r;
5909                 if (len > 0) {
5910                         q = (char *)memcpy(q, str, len) + len;
5911                 }
5912         }
5913
5914         inquotes = 0;
5915         globbing = flag & RMESCAPE_GLOB;
5916         protect_against_glob = globbing;
5917         while (*p) {
5918                 if ((unsigned char)*p == CTLQUOTEMARK) {
5919 // Note: both inquotes and protect_against_glob only affect whether
5920                         inquotes = ~inquotes;
5921                         p++;
5922                         protect_against_glob = globbing;
5923                         continue;
5924                 }
5925                 if ((unsigned char)*p == CTLESC) {
5926                         p++;
5927 #if DEBUG
5928                         if (*p == '\0')
5929                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5930 #endif
5931                         if (protect_against_glob) {
5932                                 *q++ = '\\';
5933                         }
5934                 } else if (*p == '\\' && !inquotes) {
5935                         /* naked back slash */
5936                         protect_against_glob = 0;
5937                         goto copy;
5938                 }
5939 #if BASH_PATTERN_SUBST
5940                 else if (*p == '/' && slash) {
5941                         /* stop handling globbing and mark location of slash */
5942                         globbing = slash = 0;
5943                         *p = CTLESC;
5944                 }
5945 #endif
5946                 protect_against_glob = globbing;
5947  copy:
5948                 *q++ = *p++;
5949         }
5950         *q = '\0';
5951         if (flag & RMESCAPE_GROW) {
5952                 expdest = r;
5953                 STADJUST(q - r + 1, expdest);
5954         }
5955         return r;
5956 }
5957 #define pmatch(a, b) !fnmatch((a), (b), 0)
5958
5959 /*
5960  * Prepare a pattern for a expmeta (internal glob(3)) call.
5961  *
5962  * Returns an stalloced string.
5963  */
5964 static char *
5965 preglob(const char *pattern, int flag)
5966 {
5967         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5968 }
5969
5970 /*
5971  * Put a string on the stack.
5972  */
5973 static void
5974 memtodest(const char *p, size_t len, int syntax, int quotes)
5975 {
5976         char *q;
5977
5978         if (!len)
5979                 return;
5980
5981         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
5982
5983         do {
5984                 unsigned char c = *p++;
5985                 if (c) {
5986                         if (quotes & QUOTES_ESC) {
5987                                 int n = SIT(c, syntax);
5988                                 if (n == CCTL
5989                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
5990                                      && n == CBACK
5991                                     )
5992                                 ) {
5993                                         USTPUTC(CTLESC, q);
5994                                 }
5995                         }
5996                 } else if (!(quotes & QUOTES_KEEPNUL))
5997                         continue;
5998                 USTPUTC(c, q);
5999         } while (--len);
6000
6001         expdest = q;
6002 }
6003
6004 static size_t
6005 strtodest(const char *p, int syntax, int quotes)
6006 {
6007         size_t len = strlen(p);
6008         memtodest(p, len, syntax, quotes);
6009         return len;
6010 }
6011
6012 /*
6013  * Record the fact that we have to scan this region of the
6014  * string for IFS characters.
6015  */
6016 static void
6017 recordregion(int start, int end, int nulonly)
6018 {
6019         struct ifsregion *ifsp;
6020
6021         if (ifslastp == NULL) {
6022                 ifsp = &ifsfirst;
6023         } else {
6024                 INT_OFF;
6025                 ifsp = ckzalloc(sizeof(*ifsp));
6026                 /*ifsp->next = NULL; - ckzalloc did it */
6027                 ifslastp->next = ifsp;
6028                 INT_ON;
6029         }
6030         ifslastp = ifsp;
6031         ifslastp->begoff = start;
6032         ifslastp->endoff = end;
6033         ifslastp->nulonly = nulonly;
6034 }
6035
6036 static void
6037 removerecordregions(int endoff)
6038 {
6039         if (ifslastp == NULL)
6040                 return;
6041
6042         if (ifsfirst.endoff > endoff) {
6043                 while (ifsfirst.next) {
6044                         struct ifsregion *ifsp;
6045                         INT_OFF;
6046                         ifsp = ifsfirst.next->next;
6047                         free(ifsfirst.next);
6048                         ifsfirst.next = ifsp;
6049                         INT_ON;
6050                 }
6051                 if (ifsfirst.begoff > endoff) {
6052                         ifslastp = NULL;
6053                 } else {
6054                         ifslastp = &ifsfirst;
6055                         ifsfirst.endoff = endoff;
6056                 }
6057                 return;
6058         }
6059
6060         ifslastp = &ifsfirst;
6061         while (ifslastp->next && ifslastp->next->begoff < endoff)
6062                 ifslastp = ifslastp->next;
6063         while (ifslastp->next) {
6064                 struct ifsregion *ifsp;
6065                 INT_OFF;
6066                 ifsp = ifslastp->next->next;
6067                 free(ifslastp->next);
6068                 ifslastp->next = ifsp;
6069                 INT_ON;
6070         }
6071         if (ifslastp->endoff > endoff)
6072                 ifslastp->endoff = endoff;
6073 }
6074
6075 static char *
6076 exptilde(char *startp, char *p, int flags)
6077 {
6078         unsigned char c;
6079         char *name;
6080         struct passwd *pw;
6081         const char *home;
6082         int quotes = flags & QUOTES_ESC;
6083
6084         name = p + 1;
6085
6086         while ((c = *++p) != '\0') {
6087                 switch (c) {
6088                 case CTLESC:
6089                         return startp;
6090                 case CTLQUOTEMARK:
6091                         return startp;
6092                 case ':':
6093                         if (flags & EXP_VARTILDE)
6094                                 goto done;
6095                         break;
6096                 case '/':
6097                 case CTLENDVAR:
6098                         goto done;
6099                 }
6100         }
6101  done:
6102         *p = '\0';
6103         if (*name == '\0') {
6104                 home = lookupvar("HOME");
6105         } else {
6106                 pw = getpwnam(name);
6107                 if (pw == NULL)
6108                         goto lose;
6109                 home = pw->pw_dir;
6110         }
6111         if (!home || !*home)
6112                 goto lose;
6113         *p = c;
6114         strtodest(home, SQSYNTAX, quotes);
6115         return p;
6116  lose:
6117         *p = c;
6118         return startp;
6119 }
6120
6121 /*
6122  * Execute a command inside back quotes.  If it's a builtin command, we
6123  * want to save its output in a block obtained from malloc.  Otherwise
6124  * we fork off a subprocess and get the output of the command via a pipe.
6125  * Should be called with interrupts off.
6126  */
6127 struct backcmd {                /* result of evalbackcmd */
6128         int fd;                 /* file descriptor to read from */
6129         int nleft;              /* number of chars in buffer */
6130         char *buf;              /* buffer */
6131         struct job *jp;         /* job structure for command */
6132 };
6133
6134 /* These forward decls are needed to use "eval" code for backticks handling: */
6135 #define EV_EXIT 01              /* exit after evaluating tree */
6136 static int evaltree(union node *, int);
6137
6138 static void FAST_FUNC
6139 evalbackcmd(union node *n, struct backcmd *result)
6140 {
6141         int pip[2];
6142         struct job *jp;
6143
6144         result->fd = -1;
6145         result->buf = NULL;
6146         result->nleft = 0;
6147         result->jp = NULL;
6148         if (n == NULL) {
6149                 goto out;
6150         }
6151
6152         if (pipe(pip) < 0)
6153                 ash_msg_and_raise_error("pipe call failed");
6154         jp = makejob(/*n,*/ 1);
6155         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6156                 /* child */
6157                 FORCE_INT_ON;
6158                 close(pip[0]);
6159                 if (pip[1] != 1) {
6160                         /*close(1);*/
6161                         dup2_or_raise(pip[1], 1);
6162                         close(pip[1]);
6163                 }
6164 /* TODO: eflag clearing makes the following not abort:
6165  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6166  * which is what bash does (unless it is in POSIX mode).
6167  * dash deleted "eflag = 0" line in the commit
6168  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6169  *  [EVAL] Don't clear eflag in evalbackcmd
6170  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6171  */
6172                 eflag = 0;
6173                 ifsfree();
6174                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6175                 /* NOTREACHED */
6176         }
6177         /* parent */
6178         close(pip[1]);
6179         result->fd = pip[0];
6180         result->jp = jp;
6181
6182  out:
6183         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6184                 result->fd, result->buf, result->nleft, result->jp));
6185 }
6186
6187 /*
6188  * Expand stuff in backwards quotes.
6189  */
6190 static void
6191 expbackq(union node *cmd, int flag)
6192 {
6193         struct backcmd in;
6194         int i;
6195         char buf[128];
6196         char *p;
6197         char *dest;
6198         int startloc;
6199         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6200         struct stackmark smark;
6201
6202         INT_OFF;
6203         startloc = expdest - (char *)stackblock();
6204         pushstackmark(&smark, startloc);
6205         evalbackcmd(cmd, &in);
6206         popstackmark(&smark);
6207
6208         p = in.buf;
6209         i = in.nleft;
6210         if (i == 0)
6211                 goto read;
6212         for (;;) {
6213                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6214  read:
6215                 if (in.fd < 0)
6216                         break;
6217                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6218                 TRACE(("expbackq: read returns %d\n", i));
6219                 if (i <= 0)
6220                         break;
6221                 p = buf;
6222         }
6223
6224         free(in.buf);
6225         if (in.fd >= 0) {
6226                 close(in.fd);
6227                 back_exitstatus = waitforjob(in.jp);
6228         }
6229         INT_ON;
6230
6231         /* Eat all trailing newlines */
6232         dest = expdest;
6233         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6234                 STUNPUTC(dest);
6235         expdest = dest;
6236
6237         if (!(flag & EXP_QUOTED))
6238                 recordregion(startloc, dest - (char *)stackblock(), 0);
6239         TRACE(("evalbackq: size:%d:'%.*s'\n",
6240                 (int)((dest - (char *)stackblock()) - startloc),
6241                 (int)((dest - (char *)stackblock()) - startloc),
6242                 stackblock() + startloc));
6243 }
6244
6245 #if ENABLE_FEATURE_SH_MATH
6246 /*
6247  * Expand arithmetic expression.  Backup to start of expression,
6248  * evaluate, place result in (backed up) result, adjust string position.
6249  */
6250 static void
6251 expari(int flag)
6252 {
6253         char *p, *start;
6254         int begoff;
6255         int len;
6256
6257         /* ifsfree(); */
6258
6259         /*
6260          * This routine is slightly over-complicated for
6261          * efficiency.  Next we scan backwards looking for the
6262          * start of arithmetic.
6263          */
6264         start = stackblock();
6265         p = expdest - 1;
6266         *p = '\0';
6267         p--;
6268         while (1) {
6269                 int esc;
6270
6271                 while ((unsigned char)*p != CTLARI) {
6272                         p--;
6273 #if DEBUG
6274                         if (p < start) {
6275                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6276                         }
6277 #endif
6278                 }
6279
6280                 esc = esclen(start, p);
6281                 if (!(esc % 2)) {
6282                         break;
6283                 }
6284
6285                 p -= esc + 1;
6286         }
6287
6288         begoff = p - start;
6289
6290         removerecordregions(begoff);
6291
6292         expdest = p;
6293
6294         if (flag & QUOTES_ESC)
6295                 rmescapes(p + 1, 0);
6296
6297         len = cvtnum(ash_arith(p + 1));
6298
6299         if (!(flag & EXP_QUOTED))
6300                 recordregion(begoff, begoff + len, 0);
6301 }
6302 #endif
6303
6304 /* argstr needs it */
6305 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6306
6307 /*
6308  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6309  * characters to allow for further processing.  Otherwise treat
6310  * $@ like $* since no splitting will be performed.
6311  *
6312  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6313  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6314  * for correct expansion of "B=$A" word.
6315  */
6316 static void
6317 argstr(char *p, int flags, struct strlist *var_str_list)
6318 {
6319         static const char spclchars[] ALIGN1 = {
6320                 '=',
6321                 ':',
6322                 CTLQUOTEMARK,
6323                 CTLENDVAR,
6324                 CTLESC,
6325                 CTLVAR,
6326                 CTLBACKQ,
6327 #if ENABLE_FEATURE_SH_MATH
6328                 CTLENDARI,
6329 #endif
6330                 '\0'
6331         };
6332         const char *reject = spclchars;
6333         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6334         int inquotes;
6335         size_t length;
6336         int startloc;
6337
6338         if (!(flags & EXP_VARTILDE)) {
6339                 reject += 2;
6340         } else if (flags & EXP_VARTILDE2) {
6341                 reject++;
6342         }
6343         inquotes = 0;
6344         length = 0;
6345         if (flags & EXP_TILDE) {
6346                 char *q;
6347
6348                 flags &= ~EXP_TILDE;
6349  tilde:
6350                 q = p;
6351                 if (*q == '~')
6352                         p = exptilde(p, q, flags);
6353         }
6354  start:
6355         startloc = expdest - (char *)stackblock();
6356         for (;;) {
6357                 unsigned char c;
6358
6359                 length += strcspn(p + length, reject);
6360                 c = p[length];
6361                 if (c) {
6362                         if (!(c & 0x80)
6363                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6364                         ) {
6365                                 /* c == '=' || c == ':' || c == CTLENDARI */
6366                                 length++;
6367                         }
6368                 }
6369                 if (length > 0) {
6370                         int newloc;
6371                         expdest = stack_nputstr(p, length, expdest);
6372                         newloc = expdest - (char *)stackblock();
6373                         if (breakall && !inquotes && newloc > startloc) {
6374                                 recordregion(startloc, newloc, 0);
6375                         }
6376                         startloc = newloc;
6377                 }
6378                 p += length + 1;
6379                 length = 0;
6380
6381                 switch (c) {
6382                 case '\0':
6383                         goto breakloop;
6384                 case '=':
6385                         if (flags & EXP_VARTILDE2) {
6386                                 p--;
6387                                 continue;
6388                         }
6389                         flags |= EXP_VARTILDE2;
6390                         reject++;
6391                         /* fall through */
6392                 case ':':
6393                         /*
6394                          * sort of a hack - expand tildes in variable
6395                          * assignments (after the first '=' and after ':'s).
6396                          */
6397                         if (*--p == '~') {
6398                                 goto tilde;
6399                         }
6400                         continue;
6401                 }
6402
6403                 switch (c) {
6404                 case CTLENDVAR: /* ??? */
6405                         goto breakloop;
6406                 case CTLQUOTEMARK:
6407                         inquotes ^= EXP_QUOTED;
6408                         /* "$@" syntax adherence hack */
6409                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6410                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6411                                 goto start;
6412                         }
6413  addquote:
6414                         if (flags & QUOTES_ESC) {
6415                                 p--;
6416                                 length++;
6417                                 startloc++;
6418                         }
6419                         break;
6420                 case CTLESC:
6421                         startloc++;
6422                         length++;
6423
6424                         /*
6425                          * Quoted parameter expansion pattern: remove quote
6426                          * unless inside inner quotes or we have a literal
6427                          * backslash.
6428                          */
6429                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6430                             EXP_QPAT && *p != '\\')
6431                                 break;
6432
6433                         goto addquote;
6434                 case CTLVAR:
6435                         TRACE(("argstr: evalvar('%s')\n", p));
6436                         p = evalvar(p, flags | inquotes, var_str_list);
6437                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6438                         goto start;
6439                 case CTLBACKQ:
6440                         expbackq(argbackq->n, flags | inquotes);
6441                         argbackq = argbackq->next;
6442                         goto start;
6443 #if ENABLE_FEATURE_SH_MATH
6444                 case CTLENDARI:
6445                         p--;
6446                         expari(flags | inquotes);
6447                         goto start;
6448 #endif
6449                 }
6450         }
6451  breakloop: ;
6452 }
6453
6454 static char *
6455 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6456                 char *pattern, int quotes, int zero)
6457 {
6458         char *loc, *loc2;
6459         char c;
6460
6461         loc = startp;
6462         loc2 = rmesc;
6463         do {
6464                 int match;
6465                 const char *s = loc2;
6466
6467                 c = *loc2;
6468                 if (zero) {
6469                         *loc2 = '\0';
6470                         s = rmesc;
6471                 }
6472                 match = pmatch(pattern, s);
6473
6474                 *loc2 = c;
6475                 if (match)
6476                         return loc;
6477                 if (quotes && (unsigned char)*loc == CTLESC)
6478                         loc++;
6479                 loc++;
6480                 loc2++;
6481         } while (c);
6482         return NULL;
6483 }
6484
6485 static char *
6486 scanright(char *startp, char *rmesc, char *rmescend,
6487                 char *pattern, int quotes, int match_at_start)
6488 {
6489 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6490         int try2optimize = match_at_start;
6491 #endif
6492         int esc = 0;
6493         char *loc;
6494         char *loc2;
6495
6496         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6497          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6498          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6499          * Logic:
6500          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6501          * and on each iteration they go back two/one char until they reach the beginning.
6502          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6503          */
6504         /* TODO: document in what other circumstances we are called. */
6505
6506         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6507                 int match;
6508                 char c = *loc2;
6509                 const char *s = loc2;
6510                 if (match_at_start) {
6511                         *loc2 = '\0';
6512                         s = rmesc;
6513                 }
6514                 match = pmatch(pattern, s);
6515                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6516                 *loc2 = c;
6517                 if (match)
6518                         return loc;
6519 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6520                 if (try2optimize) {
6521                         /* Maybe we can optimize this:
6522                          * if pattern ends with unescaped *, we can avoid checking
6523                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6524                          * it won't match truncated "raw_value_of_" strings too.
6525                          */
6526                         unsigned plen = strlen(pattern);
6527                         /* Does it end with "*"? */
6528                         if (plen != 0 && pattern[--plen] == '*') {
6529                                 /* "xxxx*" is not escaped */
6530                                 /* "xxx\*" is escaped */
6531                                 /* "xx\\*" is not escaped */
6532                                 /* "x\\\*" is escaped */
6533                                 int slashes = 0;
6534                                 while (plen != 0 && pattern[--plen] == '\\')
6535                                         slashes++;
6536                                 if (!(slashes & 1))
6537                                         break; /* ends with unescaped "*" */
6538                         }
6539                         try2optimize = 0;
6540                 }
6541 #endif
6542                 loc--;
6543                 if (quotes) {
6544                         if (--esc < 0) {
6545                                 esc = esclen(startp, loc);
6546                         }
6547                         if (esc % 2) {
6548                                 esc--;
6549                                 loc--;
6550                         }
6551                 }
6552         }
6553         return NULL;
6554 }
6555
6556 static void varunset(const char *, const char *, const char *, int) NORETURN;
6557 static void
6558 varunset(const char *end, const char *var, const char *umsg, int varflags)
6559 {
6560         const char *msg;
6561         const char *tail;
6562
6563         tail = nullstr;
6564         msg = "parameter not set";
6565         if (umsg) {
6566                 if ((unsigned char)*end == CTLENDVAR) {
6567                         if (varflags & VSNUL)
6568                                 tail = " or null";
6569                 } else {
6570                         msg = umsg;
6571                 }
6572         }
6573         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6574 }
6575
6576 static const char *
6577 subevalvar(char *p, char *varname, int strloc, int subtype,
6578                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6579 {
6580         struct nodelist *saveargbackq = argbackq;
6581         int quotes = flag & QUOTES_ESC;
6582         char *startp;
6583         char *loc;
6584         char *rmesc, *rmescend;
6585         char *str;
6586         IF_BASH_SUBSTR(int pos, len, orig_len;)
6587         int amount, resetloc;
6588         IF_BASH_PATTERN_SUBST(int workloc;)
6589         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6590         int zero;
6591         char *(*scan)(char*, char*, char*, char*, int, int);
6592
6593         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6594         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6595
6596         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6597                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6598                         var_str_list);
6599         STPUTC('\0', expdest);
6600         argbackq = saveargbackq;
6601         startp = (char *)stackblock() + startloc;
6602
6603         switch (subtype) {
6604         case VSASSIGN:
6605                 setvar0(varname, startp);
6606                 amount = startp - expdest;
6607                 STADJUST(amount, expdest);
6608                 return startp;
6609
6610         case VSQUESTION:
6611                 varunset(p, varname, startp, varflags);
6612                 /* NOTREACHED */
6613
6614 #if BASH_SUBSTR
6615         case VSSUBSTR:
6616 //TODO: support more general format ${v:EXPR:EXPR},
6617 // where EXPR follows $(()) rules
6618                 loc = str = stackblock() + strloc;
6619                 /* Read POS in ${var:POS:LEN} */
6620                 pos = atoi(loc); /* number(loc) errors out on "1:4" */
6621                 len = str - startp - 1;
6622
6623                 /* *loc != '\0', guaranteed by parser */
6624                 if (quotes) {
6625                         char *ptr;
6626
6627                         /* Adjust the length by the number of escapes */
6628                         for (ptr = startp; ptr < (str - 1); ptr++) {
6629                                 if ((unsigned char)*ptr == CTLESC) {
6630                                         len--;
6631                                         ptr++;
6632                                 }
6633                         }
6634                 }
6635                 orig_len = len;
6636
6637                 if (*loc++ == ':') {
6638                         /* ${var::LEN} */
6639                         len = number(loc);
6640                 } else {
6641                         /* Skip POS in ${var:POS:LEN} */
6642                         len = orig_len;
6643                         while (*loc && *loc != ':') {
6644                                 /* TODO?
6645                                  * bash complains on: var=qwe; echo ${var:1a:123}
6646                                 if (!isdigit(*loc))
6647                                         ash_msg_and_raise_error(msg_illnum, str);
6648                                  */
6649                                 loc++;
6650                         }
6651                         if (*loc++ == ':') {
6652                                 len = number(loc);
6653                         }
6654                 }
6655                 if (pos < 0) {
6656                         /* ${VAR:$((-n)):l} starts n chars from the end */
6657                         pos = orig_len + pos;
6658                 }
6659                 if ((unsigned)pos >= orig_len) {
6660                         /* apart from obvious ${VAR:999999:l},
6661                          * covers ${VAR:$((-9999999)):l} - result is ""
6662                          * (bash-compat)
6663                          */
6664                         pos = 0;
6665                         len = 0;
6666                 }
6667                 if (len > (orig_len - pos))
6668                         len = orig_len - pos;
6669
6670                 for (str = startp; pos; str++, pos--) {
6671                         if (quotes && (unsigned char)*str == CTLESC)
6672                                 str++;
6673                 }
6674                 for (loc = startp; len; len--) {
6675                         if (quotes && (unsigned char)*str == CTLESC)
6676                                 *loc++ = *str++;
6677                         *loc++ = *str++;
6678                 }
6679                 *loc = '\0';
6680                 amount = loc - expdest;
6681                 STADJUST(amount, expdest);
6682                 return loc;
6683 #endif /* BASH_SUBSTR */
6684         }
6685
6686         resetloc = expdest - (char *)stackblock();
6687
6688 #if BASH_PATTERN_SUBST
6689         /* We'll comeback here if we grow the stack while handling
6690          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6691          * stack will need rebasing, and we'll need to remove our work
6692          * areas each time
6693          */
6694  restart:
6695 #endif
6696
6697         amount = expdest - ((char *)stackblock() + resetloc);
6698         STADJUST(-amount, expdest);
6699         startp = (char *)stackblock() + startloc;
6700
6701         rmesc = startp;
6702         rmescend = (char *)stackblock() + strloc;
6703         if (quotes) {
6704                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6705                 if (rmesc != startp) {
6706                         rmescend = expdest;
6707                         startp = (char *)stackblock() + startloc;
6708                 }
6709         }
6710         rmescend--;
6711         str = (char *)stackblock() + strloc;
6712         /*
6713          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6714          * The result is a_\_z_c (not a\_\_z_c)!
6715          *
6716          * The search pattern and replace string treat backslashes differently!
6717          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6718          * and string.  It's only used on the first call.
6719          */
6720         preglob(str, IF_BASH_PATTERN_SUBST(
6721                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6722                         RMESCAPE_SLASH : ) 0);
6723
6724 #if BASH_PATTERN_SUBST
6725         workloc = expdest - (char *)stackblock();
6726         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6727                 char *idx, *end;
6728
6729                 if (!repl) {
6730                         repl = strchr(str, CTLESC);
6731                         if (repl)
6732                                 *repl++ = '\0';
6733                         else
6734                                 repl = nullstr;
6735                 }
6736                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6737
6738                 /* If there's no pattern to match, return the expansion unmolested */
6739                 if (str[0] == '\0')
6740                         return NULL;
6741
6742                 len = 0;
6743                 idx = startp;
6744                 end = str - 1;
6745                 while (idx < end) {
6746  try_to_match:
6747                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6748                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6749                         if (!loc) {
6750                                 /* No match, advance */
6751                                 char *restart_detect = stackblock();
6752  skip_matching:
6753                                 STPUTC(*idx, expdest);
6754                                 if (quotes && (unsigned char)*idx == CTLESC) {
6755                                         idx++;
6756                                         len++;
6757                                         STPUTC(*idx, expdest);
6758                                 }
6759                                 if (stackblock() != restart_detect)
6760                                         goto restart;
6761                                 idx++;
6762                                 len++;
6763                                 rmesc++;
6764                                 /* continue; - prone to quadratic behavior, smarter code: */
6765                                 if (idx >= end)
6766                                         break;
6767                                 if (str[0] == '*') {
6768                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6769                                          * it would never match "ong_string" etc, no point in trying.
6770                                          */
6771                                         goto skip_matching;
6772                                 }
6773                                 goto try_to_match;
6774                         }
6775
6776                         if (subtype == VSREPLACEALL) {
6777                                 while (idx < loc) {
6778                                         if (quotes && (unsigned char)*idx == CTLESC)
6779                                                 idx++;
6780                                         idx++;
6781                                         rmesc++;
6782                                 }
6783                         } else {
6784                                 idx = loc;
6785                         }
6786
6787                         //bb_error_msg("repl:'%s'", repl);
6788                         for (loc = (char*)repl; *loc; loc++) {
6789                                 char *restart_detect = stackblock();
6790                                 if (quotes && *loc == '\\') {
6791                                         STPUTC(CTLESC, expdest);
6792                                         len++;
6793                                 }
6794                                 STPUTC(*loc, expdest);
6795                                 if (stackblock() != restart_detect)
6796                                         goto restart;
6797                                 len++;
6798                         }
6799
6800                         if (subtype == VSREPLACE) {
6801                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6802                                 while (*idx) {
6803                                         char *restart_detect = stackblock();
6804                                         STPUTC(*idx, expdest);
6805                                         if (stackblock() != restart_detect)
6806                                                 goto restart;
6807                                         len++;
6808                                         idx++;
6809                                 }
6810                                 break;
6811                         }
6812                 }
6813
6814                 /* We've put the replaced text into a buffer at workloc, now
6815                  * move it to the right place and adjust the stack.
6816                  */
6817                 STPUTC('\0', expdest);
6818                 startp = (char *)stackblock() + startloc;
6819                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6820                 //bb_error_msg("startp:'%s'", startp);
6821                 amount = expdest - (startp + len);
6822                 STADJUST(-amount, expdest);
6823                 return startp;
6824         }
6825 #endif /* BASH_PATTERN_SUBST */
6826
6827         subtype -= VSTRIMRIGHT;
6828 #if DEBUG
6829         if (subtype < 0 || subtype > 7)
6830                 abort();
6831 #endif
6832         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6833         zero = subtype >> 1;
6834         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6835         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6836
6837         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6838         if (loc) {
6839                 if (zero) {
6840                         memmove(startp, loc, str - loc);
6841                         loc = startp + (str - loc) - 1;
6842                 }
6843                 *loc = '\0';
6844                 amount = loc - expdest;
6845                 STADJUST(amount, expdest);
6846         }
6847         return loc;
6848 }
6849
6850 /*
6851  * Add the value of a specialized variable to the stack string.
6852  * name parameter (examples):
6853  * ash -c 'echo $1'      name:'1='
6854  * ash -c 'echo $qwe'    name:'qwe='
6855  * ash -c 'echo $$'      name:'$='
6856  * ash -c 'echo ${$}'    name:'$='
6857  * ash -c 'echo ${$##q}' name:'$=q'
6858  * ash -c 'echo ${#$}'   name:'$='
6859  * note: examples with bad shell syntax:
6860  * ash -c 'echo ${#$1}'  name:'$=1'
6861  * ash -c 'echo ${#1#}'  name:'1=#'
6862  */
6863 static NOINLINE ssize_t
6864 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6865 {
6866         const char *p;
6867         int num;
6868         int i;
6869         ssize_t len = 0;
6870         int sep;
6871         int quoted = *quotedp;
6872         int subtype = varflags & VSTYPE;
6873         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6874         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6875         int syntax;
6876
6877         sep = (flags & EXP_FULL) << CHAR_BIT;
6878         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6879
6880         switch (*name) {
6881         case '$':
6882                 num = rootpid;
6883                 goto numvar;
6884         case '?':
6885                 num = exitstatus;
6886                 goto numvar;
6887         case '#':
6888                 num = shellparam.nparam;
6889                 goto numvar;
6890         case '!':
6891                 num = backgndpid;
6892                 if (num == 0)
6893                         return -1;
6894  numvar:
6895                 len = cvtnum(num);
6896                 goto check_1char_name;
6897         case '-':
6898                 expdest = makestrspace(NOPTS, expdest);
6899                 for (i = NOPTS - 1; i >= 0; i--) {
6900                         if (optlist[i]) {
6901                                 USTPUTC(optletters(i), expdest);
6902                                 len++;
6903                         }
6904                 }
6905  check_1char_name:
6906 #if 0
6907                 /* handles cases similar to ${#$1} */
6908                 if (name[2] != '\0')
6909                         raise_error_syntax("bad substitution");
6910 #endif
6911                 break;
6912         case '@':
6913                 if (quoted && sep)
6914                         goto param;
6915                 /* fall through */
6916         case '*': {
6917                 char **ap;
6918                 char sepc;
6919
6920                 if (quoted)
6921                         sep = 0;
6922                 sep |= ifsset() ? ifsval()[0] : ' ';
6923  param:
6924                 sepc = sep;
6925                 *quotedp = !sepc;
6926                 ap = shellparam.p;
6927                 if (!ap)
6928                         return -1;
6929                 while ((p = *ap++) != NULL) {
6930                         len += strtodest(p, syntax, quotes);
6931
6932                         if (*ap && sep) {
6933                                 len++;
6934                                 memtodest(&sepc, 1, syntax, quotes);
6935                         }
6936                 }
6937                 break;
6938         } /* case '*' */
6939         case '0':
6940         case '1':
6941         case '2':
6942         case '3':
6943         case '4':
6944         case '5':
6945         case '6':
6946         case '7':
6947         case '8':
6948         case '9':
6949                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6950                 if (num < 0 || num > shellparam.nparam)
6951                         return -1;
6952                 p = num ? shellparam.p[num - 1] : arg0;
6953                 goto value;
6954         default:
6955                 /* NB: name has form "VAR=..." */
6956
6957                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6958                  * which should be considered before we check variables. */
6959                 if (var_str_list) {
6960                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6961                         p = NULL;
6962                         do {
6963                                 char *str, *eq;
6964                                 str = var_str_list->text;
6965                                 eq = strchr(str, '=');
6966                                 if (!eq) /* stop at first non-assignment */
6967                                         break;
6968                                 eq++;
6969                                 if (name_len == (unsigned)(eq - str)
6970                                  && strncmp(str, name, name_len) == 0
6971                                 ) {
6972                                         p = eq;
6973                                         /* goto value; - WRONG! */
6974                                         /* think "A=1 A=2 B=$A" */
6975                                 }
6976                                 var_str_list = var_str_list->next;
6977                         } while (var_str_list);
6978                         if (p)
6979                                 goto value;
6980                 }
6981                 p = lookupvar(name);
6982  value:
6983                 if (!p)
6984                         return -1;
6985
6986                 len = strtodest(p, syntax, quotes);
6987 #if ENABLE_UNICODE_SUPPORT
6988                 if (subtype == VSLENGTH && len > 0) {
6989                         reinit_unicode_for_ash();
6990                         if (unicode_status == UNICODE_ON) {
6991                                 STADJUST(-len, expdest);
6992                                 discard = 0;
6993                                 len = unicode_strlen(p);
6994                         }
6995                 }
6996 #endif
6997                 break;
6998         }
6999
7000         if (discard)
7001                 STADJUST(-len, expdest);
7002         return len;
7003 }
7004
7005 /*
7006  * Expand a variable, and return a pointer to the next character in the
7007  * input string.
7008  */
7009 static char *
7010 evalvar(char *p, int flag, struct strlist *var_str_list)
7011 {
7012         char varflags;
7013         char subtype;
7014         int quoted;
7015         char easy;
7016         char *var;
7017         int patloc;
7018         int startloc;
7019         ssize_t varlen;
7020
7021         varflags = (unsigned char) *p++;
7022         subtype = varflags & VSTYPE;
7023
7024         if (!subtype)
7025                 raise_error_syntax("bad substitution");
7026
7027         quoted = flag & EXP_QUOTED;
7028         var = p;
7029         easy = (!quoted || (*var == '@' && shellparam.nparam));
7030         startloc = expdest - (char *)stackblock();
7031         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7032
7033  again:
7034         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7035         if (varflags & VSNUL)
7036                 varlen--;
7037
7038         if (subtype == VSPLUS) {
7039                 varlen = -1 - varlen;
7040                 goto vsplus;
7041         }
7042
7043         if (subtype == VSMINUS) {
7044  vsplus:
7045                 if (varlen < 0) {
7046                         argstr(
7047                                 p,
7048                                 flag | EXP_TILDE | EXP_WORD,
7049                                 var_str_list
7050                         );
7051                         goto end;
7052                 }
7053                 goto record;
7054         }
7055
7056         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7057                 if (varlen >= 0)
7058                         goto record;
7059
7060                 subevalvar(p, var, 0, subtype, startloc, varflags,
7061                            flag & ~QUOTES_ESC, var_str_list);
7062                 varflags &= ~VSNUL;
7063                 /*
7064                  * Remove any recorded regions beyond
7065                  * start of variable
7066                  */
7067                 removerecordregions(startloc);
7068                 goto again;
7069         }
7070
7071         if (varlen < 0 && uflag)
7072                 varunset(p, var, 0, 0);
7073
7074         if (subtype == VSLENGTH) {
7075                 cvtnum(varlen > 0 ? varlen : 0);
7076                 goto record;
7077         }
7078
7079         if (subtype == VSNORMAL) {
7080  record:
7081                 if (!easy)
7082                         goto end;
7083                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7084                 goto end;
7085         }
7086
7087 #if DEBUG
7088         switch (subtype) {
7089         case VSTRIMLEFT:
7090         case VSTRIMLEFTMAX:
7091         case VSTRIMRIGHT:
7092         case VSTRIMRIGHTMAX:
7093 #if BASH_SUBSTR
7094         case VSSUBSTR:
7095 #endif
7096 #if BASH_PATTERN_SUBST
7097         case VSREPLACE:
7098         case VSREPLACEALL:
7099 #endif
7100                 break;
7101         default:
7102                 abort();
7103         }
7104 #endif
7105
7106         if (varlen >= 0) {
7107                 /*
7108                  * Terminate the string and start recording the pattern
7109                  * right after it
7110                  */
7111                 STPUTC('\0', expdest);
7112                 patloc = expdest - (char *)stackblock();
7113                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7114                                 startloc, varflags, flag, var_str_list)) {
7115                         int amount = expdest - (
7116                                 (char *)stackblock() + patloc - 1
7117                         );
7118                         STADJUST(-amount, expdest);
7119                 }
7120                 /* Remove any recorded regions beyond start of variable */
7121                 removerecordregions(startloc);
7122                 goto record;
7123         }
7124
7125  end:
7126         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7127                 int nesting = 1;
7128                 for (;;) {
7129                         unsigned char c = *p++;
7130                         if (c == CTLESC)
7131                                 p++;
7132                         else if (c == CTLBACKQ) {
7133                                 if (varlen >= 0)
7134                                         argbackq = argbackq->next;
7135                         } else if (c == CTLVAR) {
7136                                 if ((*p++ & VSTYPE) != VSNORMAL)
7137                                         nesting++;
7138                         } else if (c == CTLENDVAR) {
7139                                 if (--nesting == 0)
7140                                         break;
7141                         }
7142                 }
7143         }
7144         return p;
7145 }
7146
7147 /*
7148  * Add a file name to the list.
7149  */
7150 static void
7151 addfname(const char *name)
7152 {
7153         struct strlist *sp;
7154
7155         sp = stzalloc(sizeof(*sp));
7156         sp->text = sstrdup(name);
7157         *exparg.lastp = sp;
7158         exparg.lastp = &sp->next;
7159 }
7160
7161 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7162 static int
7163 hasmeta(const char *p)
7164 {
7165         static const char chars[] ALIGN1 = {
7166                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7167         };
7168
7169         for (;;) {
7170                 p = strpbrk(p, chars);
7171                 if (!p)
7172                         break;
7173                 switch ((unsigned char) *p) {
7174                 case CTLQUOTEMARK:
7175                         for (;;) {
7176                                 p++;
7177                                 if (*p == CTLQUOTEMARK)
7178                                         break;
7179                                 if (*p == CTLESC)
7180                                         p++;
7181                                 if (*p == '\0') /* huh? */
7182                                         return 0;
7183                         }
7184                         break;
7185                 case '\\':
7186                 case CTLESC:
7187                         p++;
7188                         if (*p == '\0')
7189                                 return 0;
7190                         break;
7191                 case '[':
7192                         if (!strchr(p + 1, ']')) {
7193                                 /* It's not a properly closed [] pattern,
7194                                  * but other metas may follow. Continue checking.
7195                                  * my[file* _is_ globbed by bash
7196                                  * and matches filenames like "my[file1".
7197                                  */
7198                                 break;
7199                         }
7200                         /* fallthrough */
7201                 default:
7202                 /* case '*': */
7203                 /* case '?': */
7204                         return 1;
7205                 }
7206                 p++;
7207         }
7208
7209         return 0;
7210 }
7211
7212 /* If we want to use glob() from libc... */
7213 #if !ENABLE_ASH_INTERNAL_GLOB
7214
7215 /* Add the result of glob() to the list */
7216 static void
7217 addglob(const glob_t *pglob)
7218 {
7219         char **p = pglob->gl_pathv;
7220
7221         do {
7222                 addfname(*p);
7223         } while (*++p);
7224 }
7225 static void
7226 expandmeta(struct strlist *str /*, int flag*/)
7227 {
7228         /* TODO - EXP_REDIR */
7229
7230         while (str) {
7231                 char *p;
7232                 glob_t pglob;
7233                 int i;
7234
7235                 if (fflag)
7236                         goto nometa;
7237
7238                 if (!hasmeta(str->text))
7239                         goto nometa;
7240
7241                 INT_OFF;
7242                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7243 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7244 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7245 //
7246 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7247 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7248 // Which means you need to unescape the string, right? Not so fast:
7249 // if there _is_ a file named "file\?" (with backslash), it is returned
7250 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7251 // You DON'T KNOW by looking at the result whether you need to unescape it.
7252 //
7253 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7254 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7255 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7256 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7257 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7258 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7259                 i = glob(p, 0, NULL, &pglob);
7260                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7261                 if (p != str->text)
7262                         free(p);
7263                 switch (i) {
7264                 case 0:
7265 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7266                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7267                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7268                                 goto nometa2;
7269 #endif
7270                         addglob(&pglob);
7271                         globfree(&pglob);
7272                         INT_ON;
7273                         break;
7274                 case GLOB_NOMATCH:
7275  //nometa2:
7276                         globfree(&pglob);
7277                         INT_ON;
7278  nometa:
7279                         *exparg.lastp = str;
7280                         rmescapes(str->text, 0);
7281                         exparg.lastp = &str->next;
7282                         break;
7283                 default:        /* GLOB_NOSPACE */
7284                         globfree(&pglob);
7285                         INT_ON;
7286                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7287                 }
7288                 str = str->next;
7289         }
7290 }
7291
7292 #else
7293 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7294
7295 /*
7296  * Do metacharacter (i.e. *, ?, [...]) expansion.
7297  */
7298 static void
7299 expmeta(char *expdir, char *enddir, char *name)
7300 {
7301         char *p;
7302         const char *cp;
7303         char *start;
7304         char *endname;
7305         int metaflag;
7306         struct stat statb;
7307         DIR *dirp;
7308         struct dirent *dp;
7309         int atend;
7310         int matchdot;
7311         int esc;
7312
7313         metaflag = 0;
7314         start = name;
7315         for (p = name; esc = 0, *p; p += esc + 1) {
7316                 if (*p == '*' || *p == '?')
7317                         metaflag = 1;
7318                 else if (*p == '[') {
7319                         char *q = p + 1;
7320                         if (*q == '!')
7321                                 q++;
7322                         for (;;) {
7323                                 if (*q == '\\')
7324                                         q++;
7325                                 if (*q == '/' || *q == '\0')
7326                                         break;
7327                                 if (*++q == ']') {
7328                                         metaflag = 1;
7329                                         break;
7330                                 }
7331                         }
7332                 } else {
7333                         if (*p == '\\')
7334                                 esc++;
7335                         if (p[esc] == '/') {
7336                                 if (metaflag)
7337                                         break;
7338                                 start = p + esc + 1;
7339                         }
7340                 }
7341         }
7342         if (metaflag == 0) {    /* we've reached the end of the file name */
7343                 if (enddir != expdir)
7344                         metaflag++;
7345                 p = name;
7346                 do {
7347                         if (*p == '\\')
7348                                 p++;
7349                         *enddir++ = *p;
7350                 } while (*p++);
7351                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7352                         addfname(expdir);
7353                 return;
7354         }
7355         endname = p;
7356         if (name < start) {
7357                 p = name;
7358                 do {
7359                         if (*p == '\\')
7360                                 p++;
7361                         *enddir++ = *p++;
7362                 } while (p < start);
7363         }
7364         if (enddir == expdir) {
7365                 cp = ".";
7366         } else if (enddir == expdir + 1 && *expdir == '/') {
7367                 cp = "/";
7368         } else {
7369                 cp = expdir;
7370                 enddir[-1] = '\0';
7371         }
7372         dirp = opendir(cp);
7373         if (dirp == NULL)
7374                 return;
7375         if (enddir != expdir)
7376                 enddir[-1] = '/';
7377         if (*endname == 0) {
7378                 atend = 1;
7379         } else {
7380                 atend = 0;
7381                 *endname = '\0';
7382                 endname += esc + 1;
7383         }
7384         matchdot = 0;
7385         p = start;
7386         if (*p == '\\')
7387                 p++;
7388         if (*p == '.')
7389                 matchdot++;
7390         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7391                 if (dp->d_name[0] == '.' && !matchdot)
7392                         continue;
7393                 if (pmatch(start, dp->d_name)) {
7394                         if (atend) {
7395                                 strcpy(enddir, dp->d_name);
7396                                 addfname(expdir);
7397                         } else {
7398                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7399                                         continue;
7400                                 p[-1] = '/';
7401                                 expmeta(expdir, p, endname);
7402                         }
7403                 }
7404         }
7405         closedir(dirp);
7406         if (!atend)
7407                 endname[-esc - 1] = esc ? '\\' : '/';
7408 }
7409
7410 static struct strlist *
7411 msort(struct strlist *list, int len)
7412 {
7413         struct strlist *p, *q = NULL;
7414         struct strlist **lpp;
7415         int half;
7416         int n;
7417
7418         if (len <= 1)
7419                 return list;
7420         half = len >> 1;
7421         p = list;
7422         for (n = half; --n >= 0;) {
7423                 q = p;
7424                 p = p->next;
7425         }
7426         q->next = NULL;                 /* terminate first half of list */
7427         q = msort(list, half);          /* sort first half of list */
7428         p = msort(p, len - half);               /* sort second half */
7429         lpp = &list;
7430         for (;;) {
7431 #if ENABLE_LOCALE_SUPPORT
7432                 if (strcoll(p->text, q->text) < 0)
7433 #else
7434                 if (strcmp(p->text, q->text) < 0)
7435 #endif
7436                                                 {
7437                         *lpp = p;
7438                         lpp = &p->next;
7439                         p = *lpp;
7440                         if (p == NULL) {
7441                                 *lpp = q;
7442                                 break;
7443                         }
7444                 } else {
7445                         *lpp = q;
7446                         lpp = &q->next;
7447                         q = *lpp;
7448                         if (q == NULL) {
7449                                 *lpp = p;
7450                                 break;
7451                         }
7452                 }
7453         }
7454         return list;
7455 }
7456
7457 /*
7458  * Sort the results of file name expansion.  It calculates the number of
7459  * strings to sort and then calls msort (short for merge sort) to do the
7460  * work.
7461  */
7462 static struct strlist *
7463 expsort(struct strlist *str)
7464 {
7465         int len;
7466         struct strlist *sp;
7467
7468         len = 0;
7469         for (sp = str; sp; sp = sp->next)
7470                 len++;
7471         return msort(str, len);
7472 }
7473
7474 static void
7475 expandmeta(struct strlist *str /*, int flag*/)
7476 {
7477         /* TODO - EXP_REDIR */
7478
7479         while (str) {
7480                 char *expdir;
7481                 struct strlist **savelastp;
7482                 struct strlist *sp;
7483                 char *p;
7484
7485                 if (fflag)
7486                         goto nometa;
7487                 if (!hasmeta(str->text))
7488                         goto nometa;
7489                 savelastp = exparg.lastp;
7490
7491                 INT_OFF;
7492                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7493                 {
7494                         int i = strlen(str->text);
7495 //BUGGY estimation of how long expanded name can be
7496                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7497                 }
7498                 expmeta(expdir, expdir, p);
7499                 free(expdir);
7500                 if (p != str->text)
7501                         free(p);
7502                 INT_ON;
7503                 if (exparg.lastp == savelastp) {
7504                         /*
7505                          * no matches
7506                          */
7507  nometa:
7508                         *exparg.lastp = str;
7509                         rmescapes(str->text, 0);
7510                         exparg.lastp = &str->next;
7511                 } else {
7512                         *exparg.lastp = NULL;
7513                         *savelastp = sp = expsort(*savelastp);
7514                         while (sp->next != NULL)
7515                                 sp = sp->next;
7516                         exparg.lastp = &sp->next;
7517                 }
7518                 str = str->next;
7519         }
7520 }
7521 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7522
7523 /*
7524  * Perform variable substitution and command substitution on an argument,
7525  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7526  * perform splitting and file name expansion.  When arglist is NULL, perform
7527  * here document expansion.
7528  */
7529 static void
7530 expandarg(union node *arg, struct arglist *arglist, int flag)
7531 {
7532         struct strlist *sp;
7533         char *p;
7534
7535         argbackq = arg->narg.backquote;
7536         STARTSTACKSTR(expdest);
7537         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7538         argstr(arg->narg.text, flag,
7539                         /* var_str_list: */ arglist ? arglist->list : NULL);
7540         p = _STPUTC('\0', expdest);
7541         expdest = p - 1;
7542         if (arglist == NULL) {
7543                 /* here document expanded */
7544                 goto out;
7545         }
7546         p = grabstackstr(p);
7547         TRACE(("expandarg: p:'%s'\n", p));
7548         exparg.lastp = &exparg.list;
7549         /*
7550          * TODO - EXP_REDIR
7551          */
7552         if (flag & EXP_FULL) {
7553                 ifsbreakup(p, &exparg);
7554                 *exparg.lastp = NULL;
7555                 exparg.lastp = &exparg.list;
7556                 expandmeta(exparg.list /*, flag*/);
7557         } else {
7558                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7559                         rmescapes(p, 0);
7560                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7561                 }
7562                 sp = stzalloc(sizeof(*sp));
7563                 sp->text = p;
7564                 *exparg.lastp = sp;
7565                 exparg.lastp = &sp->next;
7566         }
7567         *exparg.lastp = NULL;
7568         if (exparg.list) {
7569                 *arglist->lastp = exparg.list;
7570                 arglist->lastp = exparg.lastp;
7571         }
7572
7573  out:
7574         ifsfree();
7575 }
7576
7577 /*
7578  * Expand shell variables and backquotes inside a here document.
7579  */
7580 static void
7581 expandhere(union node *arg, int fd)
7582 {
7583         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7584         full_write(fd, stackblock(), expdest - (char *)stackblock());
7585 }
7586
7587 /*
7588  * Returns true if the pattern matches the string.
7589  */
7590 static int
7591 patmatch(char *pattern, const char *string)
7592 {
7593         return pmatch(preglob(pattern, 0), string);
7594 }
7595
7596 /*
7597  * See if a pattern matches in a case statement.
7598  */
7599 static int
7600 casematch(union node *pattern, char *val)
7601 {
7602         struct stackmark smark;
7603         int result;
7604
7605         setstackmark(&smark);
7606         argbackq = pattern->narg.backquote;
7607         STARTSTACKSTR(expdest);
7608         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7609                         /* var_str_list: */ NULL);
7610         STACKSTRNUL(expdest);
7611         ifsfree();
7612         result = patmatch(stackblock(), val);
7613         popstackmark(&smark);
7614         return result;
7615 }
7616
7617
7618 /* ============ find_command */
7619
7620 struct builtincmd {
7621         const char *name;
7622         int (*builtin)(int, char **) FAST_FUNC;
7623         /* unsigned flags; */
7624 };
7625 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7626 /* "regular" builtins always take precedence over commands,
7627  * regardless of PATH=....%builtin... position */
7628 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7629 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7630
7631 struct cmdentry {
7632         smallint cmdtype;       /* CMDxxx */
7633         union param {
7634                 int index;
7635                 /* index >= 0 for commands without path (slashes) */
7636                 /* (TODO: what exactly does the value mean? PATH position?) */
7637                 /* index == -1 for commands with slashes */
7638                 /* index == (-2 - applet_no) for NOFORK applets */
7639                 const struct builtincmd *cmd;
7640                 struct funcnode *func;
7641         } u;
7642 };
7643 /* values of cmdtype */
7644 #define CMDUNKNOWN      -1      /* no entry in table for command */
7645 #define CMDNORMAL       0       /* command is an executable program */
7646 #define CMDFUNCTION     1       /* command is a shell function */
7647 #define CMDBUILTIN      2       /* command is a shell builtin */
7648
7649 /* action to find_command() */
7650 #define DO_ERR          0x01    /* prints errors */
7651 #define DO_ABS          0x02    /* checks absolute paths */
7652 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7653 #define DO_ALTPATH      0x08    /* using alternate path */
7654 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7655
7656 static void find_command(char *, struct cmdentry *, int, const char *);
7657
7658
7659 /* ============ Hashing commands */
7660
7661 /*
7662  * When commands are first encountered, they are entered in a hash table.
7663  * This ensures that a full path search will not have to be done for them
7664  * on each invocation.
7665  *
7666  * We should investigate converting to a linear search, even though that
7667  * would make the command name "hash" a misnomer.
7668  */
7669
7670 struct tblentry {
7671         struct tblentry *next;  /* next entry in hash chain */
7672         union param param;      /* definition of builtin function */
7673         smallint cmdtype;       /* CMDxxx */
7674         char rehash;            /* if set, cd done since entry created */
7675         char cmdname[1];        /* name of command */
7676 };
7677
7678 static struct tblentry **cmdtable;
7679 #define INIT_G_cmdtable() do { \
7680         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7681 } while (0)
7682
7683 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7684
7685
7686 static void
7687 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7688 {
7689 #if ENABLE_FEATURE_SH_STANDALONE
7690         if (applet_no >= 0) {
7691                 if (APPLET_IS_NOEXEC(applet_no)) {
7692                         clearenv();
7693                         while (*envp)
7694                                 putenv(*envp++);
7695                         run_applet_no_and_exit(applet_no, argv);
7696                 }
7697                 /* re-exec ourselves with the new arguments */
7698                 execve(bb_busybox_exec_path, argv, envp);
7699                 /* If they called chroot or otherwise made the binary no longer
7700                  * executable, fall through */
7701         }
7702 #endif
7703
7704  repeat:
7705 #ifdef SYSV
7706         do {
7707                 execve(cmd, argv, envp);
7708         } while (errno == EINTR);
7709 #else
7710         execve(cmd, argv, envp);
7711 #endif
7712         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7713                 /* Run "cmd" as a shell script:
7714                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7715                  * "If the execve() function fails with ENOEXEC, the shell
7716                  * shall execute a command equivalent to having a shell invoked
7717                  * with the command name as its first operand,
7718                  * with any remaining arguments passed to the new shell"
7719                  *
7720                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7721                  * just call ourselves.
7722                  *
7723                  * Note that bash reads ~80 chars of the file, and if it sees
7724                  * a zero byte before it sees newline, it doesn't try to
7725                  * interpret it, but fails with "cannot execute binary file"
7726                  * message and exit code 126. For one, this prevents attempts
7727                  * to interpret foreign ELF binaries as shell scripts.
7728                  */
7729                 argv[0] = cmd;
7730                 cmd = (char*) bb_busybox_exec_path;
7731                 /* NB: this is only possible because all callers of shellexec()
7732                  * ensure that the argv[-1] slot exists!
7733                  */
7734                 argv--;
7735                 argv[0] = (char*) "ash";
7736                 goto repeat;
7737         }
7738 }
7739
7740 /*
7741  * Exec a program.  Never returns.  If you change this routine, you may
7742  * have to change the find_command routine as well.
7743  * argv[-1] must exist and be writable! See tryexec() for why.
7744  */
7745 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7746 static void shellexec(char *prog, char **argv, const char *path, int idx)
7747 {
7748         char *cmdname;
7749         int e;
7750         char **envp;
7751         int exerrno;
7752         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7753
7754         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7755         if (strchr(prog, '/') != NULL
7756 #if ENABLE_FEATURE_SH_STANDALONE
7757          || (applet_no = find_applet_by_name(prog)) >= 0
7758 #endif
7759         ) {
7760                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7761                 if (applet_no >= 0) {
7762                         /* We tried execing ourself, but it didn't work.
7763                          * Maybe /proc/self/exe doesn't exist?
7764                          * Try $PATH search.
7765                          */
7766                         goto try_PATH;
7767                 }
7768                 e = errno;
7769         } else {
7770  try_PATH:
7771                 e = ENOENT;
7772                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7773                         if (--idx < 0 && pathopt == NULL) {
7774                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7775                                 if (errno != ENOENT && errno != ENOTDIR)
7776                                         e = errno;
7777                         }
7778                         stunalloc(cmdname);
7779                 }
7780         }
7781
7782         /* Map to POSIX errors */
7783         switch (e) {
7784         case EACCES:
7785                 exerrno = 126;
7786                 break;
7787         case ENOENT:
7788                 exerrno = 127;
7789                 break;
7790         default:
7791                 exerrno = 2;
7792                 break;
7793         }
7794         exitstatus = exerrno;
7795         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7796                 prog, e, suppress_int));
7797         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7798         /* NOTREACHED */
7799 }
7800
7801 static void
7802 printentry(struct tblentry *cmdp)
7803 {
7804         int idx;
7805         const char *path;
7806         char *name;
7807
7808         idx = cmdp->param.index;
7809         path = pathval();
7810         do {
7811                 name = path_advance(&path, cmdp->cmdname);
7812                 stunalloc(name);
7813         } while (--idx >= 0);
7814         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7815 }
7816
7817 /*
7818  * Clear out command entries.  The argument specifies the first entry in
7819  * PATH which has changed.
7820  */
7821 static void
7822 clearcmdentry(int firstchange)
7823 {
7824         struct tblentry **tblp;
7825         struct tblentry **pp;
7826         struct tblentry *cmdp;
7827
7828         INT_OFF;
7829         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7830                 pp = tblp;
7831                 while ((cmdp = *pp) != NULL) {
7832                         if ((cmdp->cmdtype == CMDNORMAL &&
7833                              cmdp->param.index >= firstchange)
7834                          || (cmdp->cmdtype == CMDBUILTIN &&
7835                              builtinloc >= firstchange)
7836                         ) {
7837                                 *pp = cmdp->next;
7838                                 free(cmdp);
7839                         } else {
7840                                 pp = &cmdp->next;
7841                         }
7842                 }
7843         }
7844         INT_ON;
7845 }
7846
7847 /*
7848  * Locate a command in the command hash table.  If "add" is nonzero,
7849  * add the command to the table if it is not already present.  The
7850  * variable "lastcmdentry" is set to point to the address of the link
7851  * pointing to the entry, so that delete_cmd_entry can delete the
7852  * entry.
7853  *
7854  * Interrupts must be off if called with add != 0.
7855  */
7856 static struct tblentry **lastcmdentry;
7857
7858 static struct tblentry *
7859 cmdlookup(const char *name, int add)
7860 {
7861         unsigned int hashval;
7862         const char *p;
7863         struct tblentry *cmdp;
7864         struct tblentry **pp;
7865
7866         p = name;
7867         hashval = (unsigned char)*p << 4;
7868         while (*p)
7869                 hashval += (unsigned char)*p++;
7870         hashval &= 0x7FFF;
7871         pp = &cmdtable[hashval % CMDTABLESIZE];
7872         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7873                 if (strcmp(cmdp->cmdname, name) == 0)
7874                         break;
7875                 pp = &cmdp->next;
7876         }
7877         if (add && cmdp == NULL) {
7878                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7879                                 + strlen(name)
7880                                 /* + 1 - already done because
7881                                  * tblentry::cmdname is char[1] */);
7882                 /*cmdp->next = NULL; - ckzalloc did it */
7883                 cmdp->cmdtype = CMDUNKNOWN;
7884                 strcpy(cmdp->cmdname, name);
7885         }
7886         lastcmdentry = pp;
7887         return cmdp;
7888 }
7889
7890 /*
7891  * Delete the command entry returned on the last lookup.
7892  */
7893 static void
7894 delete_cmd_entry(void)
7895 {
7896         struct tblentry *cmdp;
7897
7898         INT_OFF;
7899         cmdp = *lastcmdentry;
7900         *lastcmdentry = cmdp->next;
7901         if (cmdp->cmdtype == CMDFUNCTION)
7902                 freefunc(cmdp->param.func);
7903         free(cmdp);
7904         INT_ON;
7905 }
7906
7907 /*
7908  * Add a new command entry, replacing any existing command entry for
7909  * the same name - except special builtins.
7910  */
7911 static void
7912 addcmdentry(char *name, struct cmdentry *entry)
7913 {
7914         struct tblentry *cmdp;
7915
7916         cmdp = cmdlookup(name, 1);
7917         if (cmdp->cmdtype == CMDFUNCTION) {
7918                 freefunc(cmdp->param.func);
7919         }
7920         cmdp->cmdtype = entry->cmdtype;
7921         cmdp->param = entry->u;
7922         cmdp->rehash = 0;
7923 }
7924
7925 static int FAST_FUNC
7926 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7927 {
7928         struct tblentry **pp;
7929         struct tblentry *cmdp;
7930         int c;
7931         struct cmdentry entry;
7932         char *name;
7933
7934         if (nextopt("r") != '\0') {
7935                 clearcmdentry(0);
7936                 return 0;
7937         }
7938
7939         if (*argptr == NULL) {
7940                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7941                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7942                                 if (cmdp->cmdtype == CMDNORMAL)
7943                                         printentry(cmdp);
7944                         }
7945                 }
7946                 return 0;
7947         }
7948
7949         c = 0;
7950         while ((name = *argptr) != NULL) {
7951                 cmdp = cmdlookup(name, 0);
7952                 if (cmdp != NULL
7953                  && (cmdp->cmdtype == CMDNORMAL
7954                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7955                 ) {
7956                         delete_cmd_entry();
7957                 }
7958                 find_command(name, &entry, DO_ERR, pathval());
7959                 if (entry.cmdtype == CMDUNKNOWN)
7960                         c = 1;
7961                 argptr++;
7962         }
7963         return c;
7964 }
7965
7966 /*
7967  * Called when a cd is done.  Marks all commands so the next time they
7968  * are executed they will be rehashed.
7969  */
7970 static void
7971 hashcd(void)
7972 {
7973         struct tblentry **pp;
7974         struct tblentry *cmdp;
7975
7976         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7977                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7978                         if (cmdp->cmdtype == CMDNORMAL
7979                          || (cmdp->cmdtype == CMDBUILTIN
7980                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7981                              && builtinloc > 0)
7982                         ) {
7983                                 cmdp->rehash = 1;
7984                         }
7985                 }
7986         }
7987 }
7988
7989 /*
7990  * Fix command hash table when PATH changed.
7991  * Called before PATH is changed.  The argument is the new value of PATH;
7992  * pathval() still returns the old value at this point.
7993  * Called with interrupts off.
7994  */
7995 static void FAST_FUNC
7996 changepath(const char *new)
7997 {
7998         const char *old;
7999         int firstchange;
8000         int idx;
8001         int idx_bltin;
8002
8003         old = pathval();
8004         firstchange = 9999;     /* assume no change */
8005         idx = 0;
8006         idx_bltin = -1;
8007         for (;;) {
8008                 if (*old != *new) {
8009                         firstchange = idx;
8010                         if ((*old == '\0' && *new == ':')
8011                          || (*old == ':' && *new == '\0')
8012                         ) {
8013                                 firstchange++;
8014                         }
8015                         old = new;      /* ignore subsequent differences */
8016                 }
8017                 if (*new == '\0')
8018                         break;
8019                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8020                         idx_bltin = idx;
8021                 if (*new == ':')
8022                         idx++;
8023                 new++;
8024                 old++;
8025         }
8026         if (builtinloc < 0 && idx_bltin >= 0)
8027                 builtinloc = idx_bltin;             /* zap builtins */
8028         if (builtinloc >= 0 && idx_bltin < 0)
8029                 firstchange = 0;
8030         clearcmdentry(firstchange);
8031         builtinloc = idx_bltin;
8032 }
8033 enum {
8034         TEOF,
8035         TNL,
8036         TREDIR,
8037         TWORD,
8038         TSEMI,
8039         TBACKGND,
8040         TAND,
8041         TOR,
8042         TPIPE,
8043         TLP,
8044         TRP,
8045         TENDCASE,
8046         TENDBQUOTE,
8047         TNOT,
8048         TCASE,
8049         TDO,
8050         TDONE,
8051         TELIF,
8052         TELSE,
8053         TESAC,
8054         TFI,
8055         TFOR,
8056 #if BASH_FUNCTION
8057         TFUNCTION,
8058 #endif
8059         TIF,
8060         TIN,
8061         TTHEN,
8062         TUNTIL,
8063         TWHILE,
8064         TBEGIN,
8065         TEND
8066 };
8067 typedef smallint token_id_t;
8068
8069 /* Nth bit indicates if token marks the end of a list */
8070 enum {
8071         tokendlist = 0
8072         /*  0 */ | (1u << TEOF)
8073         /*  1 */ | (0u << TNL)
8074         /*  2 */ | (0u << TREDIR)
8075         /*  3 */ | (0u << TWORD)
8076         /*  4 */ | (0u << TSEMI)
8077         /*  5 */ | (0u << TBACKGND)
8078         /*  6 */ | (0u << TAND)
8079         /*  7 */ | (0u << TOR)
8080         /*  8 */ | (0u << TPIPE)
8081         /*  9 */ | (0u << TLP)
8082         /* 10 */ | (1u << TRP)
8083         /* 11 */ | (1u << TENDCASE)
8084         /* 12 */ | (1u << TENDBQUOTE)
8085         /* 13 */ | (0u << TNOT)
8086         /* 14 */ | (0u << TCASE)
8087         /* 15 */ | (1u << TDO)
8088         /* 16 */ | (1u << TDONE)
8089         /* 17 */ | (1u << TELIF)
8090         /* 18 */ | (1u << TELSE)
8091         /* 19 */ | (1u << TESAC)
8092         /* 20 */ | (1u << TFI)
8093         /* 21 */ | (0u << TFOR)
8094 #if BASH_FUNCTION
8095         /* 22 */ | (0u << TFUNCTION)
8096 #endif
8097         /* 23 */ | (0u << TIF)
8098         /* 24 */ | (0u << TIN)
8099         /* 25 */ | (1u << TTHEN)
8100         /* 26 */ | (0u << TUNTIL)
8101         /* 27 */ | (0u << TWHILE)
8102         /* 28 */ | (0u << TBEGIN)
8103         /* 29 */ | (1u << TEND)
8104         , /* thus far 29 bits used */
8105 };
8106
8107 static const char *const tokname_array[] = {
8108         "end of file",
8109         "newline",
8110         "redirection",
8111         "word",
8112         ";",
8113         "&",
8114         "&&",
8115         "||",
8116         "|",
8117         "(",
8118         ")",
8119         ";;",
8120         "`",
8121 #define KWDOFFSET 13
8122         /* the following are keywords */
8123         "!",
8124         "case",
8125         "do",
8126         "done",
8127         "elif",
8128         "else",
8129         "esac",
8130         "fi",
8131         "for",
8132 #if BASH_FUNCTION
8133         "function",
8134 #endif
8135         "if",
8136         "in",
8137         "then",
8138         "until",
8139         "while",
8140         "{",
8141         "}",
8142 };
8143
8144 /* Wrapper around strcmp for qsort/bsearch/... */
8145 static int
8146 pstrcmp(const void *a, const void *b)
8147 {
8148         return strcmp((char*)a, *(char**)b);
8149 }
8150
8151 static const char *const *
8152 findkwd(const char *s)
8153 {
8154         return bsearch(s, tokname_array + KWDOFFSET,
8155                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8156                         sizeof(tokname_array[0]), pstrcmp);
8157 }
8158
8159 /*
8160  * Locate and print what a word is...
8161  */
8162 static int
8163 describe_command(char *command, const char *path, int describe_command_verbose)
8164 {
8165         struct cmdentry entry;
8166         struct tblentry *cmdp;
8167 #if ENABLE_ASH_ALIAS
8168         const struct alias *ap;
8169 #endif
8170
8171         path = path ? path : pathval();
8172
8173         if (describe_command_verbose) {
8174                 out1str(command);
8175         }
8176
8177         /* First look at the keywords */
8178         if (findkwd(command)) {
8179                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8180                 goto out;
8181         }
8182
8183 #if ENABLE_ASH_ALIAS
8184         /* Then look at the aliases */
8185         ap = lookupalias(command, 0);
8186         if (ap != NULL) {
8187                 if (!describe_command_verbose) {
8188                         out1str("alias ");
8189                         printalias(ap);
8190                         return 0;
8191                 }
8192                 out1fmt(" is an alias for %s", ap->val);
8193                 goto out;
8194         }
8195 #endif
8196         /* Then check if it is a tracked alias */
8197         cmdp = cmdlookup(command, 0);
8198         if (cmdp != NULL) {
8199                 entry.cmdtype = cmdp->cmdtype;
8200                 entry.u = cmdp->param;
8201         } else {
8202                 /* Finally use brute force */
8203                 find_command(command, &entry, DO_ABS, path);
8204         }
8205
8206         switch (entry.cmdtype) {
8207         case CMDNORMAL: {
8208                 int j = entry.u.index;
8209                 char *p;
8210                 if (j < 0) {
8211                         p = command;
8212                 } else {
8213                         do {
8214                                 p = path_advance(&path, command);
8215                                 stunalloc(p);
8216                         } while (--j >= 0);
8217                 }
8218                 if (describe_command_verbose) {
8219                         out1fmt(" is%s %s",
8220                                 (cmdp ? " a tracked alias for" : nullstr), p
8221                         );
8222                 } else {
8223                         out1str(p);
8224                 }
8225                 break;
8226         }
8227
8228         case CMDFUNCTION:
8229                 if (describe_command_verbose) {
8230                         out1str(" is a shell function");
8231                 } else {
8232                         out1str(command);
8233                 }
8234                 break;
8235
8236         case CMDBUILTIN:
8237                 if (describe_command_verbose) {
8238                         out1fmt(" is a %sshell builtin",
8239                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8240                                         "special " : nullstr
8241                         );
8242                 } else {
8243                         out1str(command);
8244                 }
8245                 break;
8246
8247         default:
8248                 if (describe_command_verbose) {
8249                         out1str(": not found\n");
8250                 }
8251                 return 127;
8252         }
8253  out:
8254         out1str("\n");
8255         return 0;
8256 }
8257
8258 static int FAST_FUNC
8259 typecmd(int argc UNUSED_PARAM, char **argv)
8260 {
8261         int i = 1;
8262         int err = 0;
8263         int verbose = 1;
8264
8265         /* type -p ... ? (we don't bother checking for 'p') */
8266         if (argv[1] && argv[1][0] == '-') {
8267                 i++;
8268                 verbose = 0;
8269         }
8270         while (argv[i]) {
8271                 err |= describe_command(argv[i++], NULL, verbose);
8272         }
8273         return err;
8274 }
8275
8276 #if ENABLE_ASH_CMDCMD
8277 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8278 static char **
8279 parse_command_args(char **argv, const char **path)
8280 {
8281         char *cp, c;
8282
8283         for (;;) {
8284                 cp = *++argv;
8285                 if (!cp)
8286                         return NULL;
8287                 if (*cp++ != '-')
8288                         break;
8289                 c = *cp++;
8290                 if (!c)
8291                         break;
8292                 if (c == '-' && !*cp) {
8293                         if (!*++argv)
8294                                 return NULL;
8295                         break;
8296                 }
8297                 do {
8298                         switch (c) {
8299                         case 'p':
8300                                 *path = bb_default_path;
8301                                 break;
8302                         default:
8303                                 /* run 'typecmd' for other options */
8304                                 return NULL;
8305                         }
8306                         c = *cp++;
8307                 } while (c);
8308         }
8309         return argv;
8310 }
8311
8312 static int FAST_FUNC
8313 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8314 {
8315         char *cmd;
8316         int c;
8317         enum {
8318                 VERIFY_BRIEF = 1,
8319                 VERIFY_VERBOSE = 2,
8320         } verify = 0;
8321         const char *path = NULL;
8322
8323         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8324          * never reaches this function.
8325          */
8326
8327         while ((c = nextopt("pvV")) != '\0')
8328                 if (c == 'V')
8329                         verify |= VERIFY_VERBOSE;
8330                 else if (c == 'v')
8331                         /*verify |= VERIFY_BRIEF*/;
8332 #if DEBUG
8333                 else if (c != 'p')
8334                         abort();
8335 #endif
8336                 else
8337                         path = bb_default_path;
8338
8339         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8340         cmd = *argptr;
8341         if (/*verify && */ cmd)
8342                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8343
8344         return 0;
8345 }
8346 #endif
8347
8348
8349 /*static int funcblocksize;     // size of structures in function */
8350 /*static int funcstringsize;    // size of strings in node */
8351 static void *funcblock;         /* block to allocate function from */
8352 static char *funcstring_end;    /* end of block to allocate strings from */
8353
8354 /* flags in argument to evaltree */
8355 #define EV_EXIT    01           /* exit after evaluating tree */
8356 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8357
8358 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8359         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8360         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8361         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8362         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8363         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8364         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8365         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8366         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8367         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8368         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8369         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8370         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8371         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8372         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8373         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8374         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8375         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8376 #if BASH_REDIR_OUTPUT
8377         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8378 #endif
8379         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8380         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8381         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8382         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8383         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8384         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8385         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8386         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8387         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8388 };
8389
8390 static int calcsize(int funcblocksize, union node *n);
8391
8392 static int
8393 sizenodelist(int funcblocksize, struct nodelist *lp)
8394 {
8395         while (lp) {
8396                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8397                 funcblocksize = calcsize(funcblocksize, lp->n);
8398                 lp = lp->next;
8399         }
8400         return funcblocksize;
8401 }
8402
8403 static int
8404 calcsize(int funcblocksize, union node *n)
8405 {
8406         if (n == NULL)
8407                 return funcblocksize;
8408         funcblocksize += nodesize[n->type];
8409         switch (n->type) {
8410         case NCMD:
8411                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8412                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8413                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8414                 break;
8415         case NPIPE:
8416                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8417                 break;
8418         case NREDIR:
8419         case NBACKGND:
8420         case NSUBSHELL:
8421                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8422                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8423                 break;
8424         case NAND:
8425         case NOR:
8426         case NSEMI:
8427         case NWHILE:
8428         case NUNTIL:
8429                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8430                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8431                 break;
8432         case NIF:
8433                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8434                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8435                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8436                 break;
8437         case NFOR:
8438                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8439                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8440                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8441                 break;
8442         case NCASE:
8443                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8444                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8445                 break;
8446         case NCLIST:
8447                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8448                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8449                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8450                 break;
8451         case NDEFUN:
8452         case NARG:
8453                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8454                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8455                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8456                 break;
8457         case NTO:
8458 #if BASH_REDIR_OUTPUT
8459         case NTO2:
8460 #endif
8461         case NCLOBBER:
8462         case NFROM:
8463         case NFROMTO:
8464         case NAPPEND:
8465                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8466                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8467                 break;
8468         case NTOFD:
8469         case NFROMFD:
8470                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8471                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8472         break;
8473         case NHERE:
8474         case NXHERE:
8475                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8476                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8477                 break;
8478         case NNOT:
8479                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8480                 break;
8481         };
8482         return funcblocksize;
8483 }
8484
8485 static char *
8486 nodeckstrdup(char *s)
8487 {
8488         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8489         return strcpy(funcstring_end, s);
8490 }
8491
8492 static union node *copynode(union node *);
8493
8494 static struct nodelist *
8495 copynodelist(struct nodelist *lp)
8496 {
8497         struct nodelist *start;
8498         struct nodelist **lpp;
8499
8500         lpp = &start;
8501         while (lp) {
8502                 *lpp = funcblock;
8503                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8504                 (*lpp)->n = copynode(lp->n);
8505                 lp = lp->next;
8506                 lpp = &(*lpp)->next;
8507         }
8508         *lpp = NULL;
8509         return start;
8510 }
8511
8512 static union node *
8513 copynode(union node *n)
8514 {
8515         union node *new;
8516
8517         if (n == NULL)
8518                 return NULL;
8519         new = funcblock;
8520         funcblock = (char *) funcblock + nodesize[n->type];
8521
8522         switch (n->type) {
8523         case NCMD:
8524                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8525                 new->ncmd.args = copynode(n->ncmd.args);
8526                 new->ncmd.assign = copynode(n->ncmd.assign);
8527                 break;
8528         case NPIPE:
8529                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8530                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8531                 break;
8532         case NREDIR:
8533         case NBACKGND:
8534         case NSUBSHELL:
8535                 new->nredir.redirect = copynode(n->nredir.redirect);
8536                 new->nredir.n = copynode(n->nredir.n);
8537                 break;
8538         case NAND:
8539         case NOR:
8540         case NSEMI:
8541         case NWHILE:
8542         case NUNTIL:
8543                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8544                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8545                 break;
8546         case NIF:
8547                 new->nif.elsepart = copynode(n->nif.elsepart);
8548                 new->nif.ifpart = copynode(n->nif.ifpart);
8549                 new->nif.test = copynode(n->nif.test);
8550                 break;
8551         case NFOR:
8552                 new->nfor.var = nodeckstrdup(n->nfor.var);
8553                 new->nfor.body = copynode(n->nfor.body);
8554                 new->nfor.args = copynode(n->nfor.args);
8555                 break;
8556         case NCASE:
8557                 new->ncase.cases = copynode(n->ncase.cases);
8558                 new->ncase.expr = copynode(n->ncase.expr);
8559                 break;
8560         case NCLIST:
8561                 new->nclist.body = copynode(n->nclist.body);
8562                 new->nclist.pattern = copynode(n->nclist.pattern);
8563                 new->nclist.next = copynode(n->nclist.next);
8564                 break;
8565         case NDEFUN:
8566         case NARG:
8567                 new->narg.backquote = copynodelist(n->narg.backquote);
8568                 new->narg.text = nodeckstrdup(n->narg.text);
8569                 new->narg.next = copynode(n->narg.next);
8570                 break;
8571         case NTO:
8572 #if BASH_REDIR_OUTPUT
8573         case NTO2:
8574 #endif
8575         case NCLOBBER:
8576         case NFROM:
8577         case NFROMTO:
8578         case NAPPEND:
8579                 new->nfile.fname = copynode(n->nfile.fname);
8580                 new->nfile.fd = n->nfile.fd;
8581                 new->nfile.next = copynode(n->nfile.next);
8582                 break;
8583         case NTOFD:
8584         case NFROMFD:
8585                 new->ndup.vname = copynode(n->ndup.vname);
8586                 new->ndup.dupfd = n->ndup.dupfd;
8587                 new->ndup.fd = n->ndup.fd;
8588                 new->ndup.next = copynode(n->ndup.next);
8589                 break;
8590         case NHERE:
8591         case NXHERE:
8592                 new->nhere.doc = copynode(n->nhere.doc);
8593                 new->nhere.fd = n->nhere.fd;
8594                 new->nhere.next = copynode(n->nhere.next);
8595                 break;
8596         case NNOT:
8597                 new->nnot.com = copynode(n->nnot.com);
8598                 break;
8599         };
8600         new->type = n->type;
8601         return new;
8602 }
8603
8604 /*
8605  * Make a copy of a parse tree.
8606  */
8607 static struct funcnode *
8608 copyfunc(union node *n)
8609 {
8610         struct funcnode *f;
8611         size_t blocksize;
8612
8613         /*funcstringsize = 0;*/
8614         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8615         f = ckzalloc(blocksize /* + funcstringsize */);
8616         funcblock = (char *) f + offsetof(struct funcnode, n);
8617         funcstring_end = (char *) f + blocksize;
8618         copynode(n);
8619         /* f->count = 0; - ckzalloc did it */
8620         return f;
8621 }
8622
8623 /*
8624  * Define a shell function.
8625  */
8626 static void
8627 defun(union node *func)
8628 {
8629         struct cmdentry entry;
8630
8631         INT_OFF;
8632         entry.cmdtype = CMDFUNCTION;
8633         entry.u.func = copyfunc(func);
8634         addcmdentry(func->narg.text, &entry);
8635         INT_ON;
8636 }
8637
8638 /* Reasons for skipping commands (see comment on breakcmd routine) */
8639 #define SKIPBREAK      (1 << 0)
8640 #define SKIPCONT       (1 << 1)
8641 #define SKIPFUNC       (1 << 2)
8642 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8643 static int skipcount;           /* number of levels to skip */
8644 static int funcnest;            /* depth of function calls */
8645 static int loopnest;            /* current loop nesting level */
8646
8647 /* Forward decl way out to parsing code - dotrap needs it */
8648 static int evalstring(char *s, int flags);
8649
8650 /* Called to execute a trap.
8651  * Single callsite - at the end of evaltree().
8652  * If we return non-zero, evaltree raises EXEXIT exception.
8653  *
8654  * Perhaps we should avoid entering new trap handlers
8655  * while we are executing a trap handler. [is it a TODO?]
8656  */
8657 static void
8658 dotrap(void)
8659 {
8660         uint8_t *g;
8661         int sig;
8662         uint8_t last_status;
8663
8664         if (!pending_sig)
8665                 return;
8666
8667         last_status = exitstatus;
8668         pending_sig = 0;
8669         barrier();
8670
8671         TRACE(("dotrap entered\n"));
8672         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8673                 char *p;
8674
8675                 if (!*g)
8676                         continue;
8677
8678                 if (evalskip) {
8679                         pending_sig = sig;
8680                         break;
8681                 }
8682
8683                 p = trap[sig];
8684                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8685                  * don't upset it by resetting gotsig[SIGINT-1] */
8686                 if (sig == SIGINT && !p)
8687                         continue;
8688
8689                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8690                 *g = 0;
8691                 if (!p)
8692                         continue;
8693                 evalstring(p, 0);
8694         }
8695         exitstatus = last_status;
8696         TRACE(("dotrap returns\n"));
8697 }
8698
8699 /* forward declarations - evaluation is fairly recursive business... */
8700 static int evalloop(union node *, int);
8701 static int evalfor(union node *, int);
8702 static int evalcase(union node *, int);
8703 static int evalsubshell(union node *, int);
8704 static void expredir(union node *);
8705 static int evalpipe(union node *, int);
8706 static int evalcommand(union node *, int);
8707 static int evalbltin(const struct builtincmd *, int, char **, int);
8708 static void prehash(union node *);
8709
8710 /*
8711  * Evaluate a parse tree.  The value is left in the global variable
8712  * exitstatus.
8713  */
8714 static int
8715 evaltree(union node *n, int flags)
8716 {
8717         int checkexit = 0;
8718         int (*evalfn)(union node *, int);
8719         int status = 0;
8720
8721         if (n == NULL) {
8722                 TRACE(("evaltree(NULL) called\n"));
8723                 goto out;
8724         }
8725         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8726
8727         dotrap();
8728
8729         switch (n->type) {
8730         default:
8731 #if DEBUG
8732                 out1fmt("Node type = %d\n", n->type);
8733                 fflush_all();
8734                 break;
8735 #endif
8736         case NNOT:
8737                 status = !evaltree(n->nnot.com, EV_TESTED);
8738                 goto setstatus;
8739         case NREDIR:
8740                 expredir(n->nredir.redirect);
8741                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8742                 if (!status) {
8743                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8744                 }
8745                 if (n->nredir.redirect)
8746                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8747                 goto setstatus;
8748         case NCMD:
8749                 evalfn = evalcommand;
8750  checkexit:
8751                 if (eflag && !(flags & EV_TESTED))
8752                         checkexit = ~0;
8753                 goto calleval;
8754         case NFOR:
8755                 evalfn = evalfor;
8756                 goto calleval;
8757         case NWHILE:
8758         case NUNTIL:
8759                 evalfn = evalloop;
8760                 goto calleval;
8761         case NSUBSHELL:
8762         case NBACKGND:
8763                 evalfn = evalsubshell;
8764                 goto checkexit;
8765         case NPIPE:
8766                 evalfn = evalpipe;
8767                 goto checkexit;
8768         case NCASE:
8769                 evalfn = evalcase;
8770                 goto calleval;
8771         case NAND:
8772         case NOR:
8773         case NSEMI: {
8774
8775 #if NAND + 1 != NOR
8776 #error NAND + 1 != NOR
8777 #endif
8778 #if NOR + 1 != NSEMI
8779 #error NOR + 1 != NSEMI
8780 #endif
8781                 unsigned is_or = n->type - NAND;
8782                 status = evaltree(
8783                         n->nbinary.ch1,
8784                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8785                 );
8786                 if ((!status) == is_or || evalskip)
8787                         break;
8788                 n = n->nbinary.ch2;
8789  evaln:
8790                 evalfn = evaltree;
8791  calleval:
8792                 status = evalfn(n, flags);
8793                 goto setstatus;
8794         }
8795         case NIF:
8796                 status = evaltree(n->nif.test, EV_TESTED);
8797                 if (evalskip)
8798                         break;
8799                 if (!status) {
8800                         n = n->nif.ifpart;
8801                         goto evaln;
8802                 }
8803                 if (n->nif.elsepart) {
8804                         n = n->nif.elsepart;
8805                         goto evaln;
8806                 }
8807                 status = 0;
8808                 goto setstatus;
8809         case NDEFUN:
8810                 defun(n);
8811                 /* Not necessary. To test it:
8812                  * "false; f() { qwerty; }; echo $?" should print 0.
8813                  */
8814                 /* status = 0; */
8815  setstatus:
8816                 exitstatus = status;
8817                 break;
8818         }
8819  out:
8820         /* Order of checks below is important:
8821          * signal handlers trigger before exit caused by "set -e".
8822          */
8823         dotrap();
8824
8825         if (checkexit & status)
8826                 raise_exception(EXEXIT);
8827         if (flags & EV_EXIT)
8828                 raise_exception(EXEXIT);
8829
8830         TRACE(("leaving evaltree (no interrupts)\n"));
8831         return exitstatus;
8832 }
8833
8834 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8835 static
8836 #endif
8837 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8838
8839 static int
8840 skiploop(void)
8841 {
8842         int skip = evalskip;
8843
8844         switch (skip) {
8845         case 0:
8846                 break;
8847         case SKIPBREAK:
8848         case SKIPCONT:
8849                 if (--skipcount <= 0) {
8850                         evalskip = 0;
8851                         break;
8852                 }
8853                 skip = SKIPBREAK;
8854                 break;
8855         }
8856         return skip;
8857 }
8858
8859 static int
8860 evalloop(union node *n, int flags)
8861 {
8862         int skip;
8863         int status;
8864
8865         loopnest++;
8866         status = 0;
8867         flags &= EV_TESTED;
8868         do {
8869                 int i;
8870
8871                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8872                 skip = skiploop();
8873                 if (skip == SKIPFUNC)
8874                         status = i;
8875                 if (skip)
8876                         continue;
8877                 if (n->type != NWHILE)
8878                         i = !i;
8879                 if (i != 0)
8880                         break;
8881                 status = evaltree(n->nbinary.ch2, flags);
8882                 skip = skiploop();
8883         } while (!(skip & ~SKIPCONT));
8884         loopnest--;
8885
8886         return status;
8887 }
8888
8889 static int
8890 evalfor(union node *n, int flags)
8891 {
8892         struct arglist arglist;
8893         union node *argp;
8894         struct strlist *sp;
8895         struct stackmark smark;
8896         int status = 0;
8897
8898         setstackmark(&smark);
8899         arglist.list = NULL;
8900         arglist.lastp = &arglist.list;
8901         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8902                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8903         }
8904         *arglist.lastp = NULL;
8905
8906         loopnest++;
8907         flags &= EV_TESTED;
8908         for (sp = arglist.list; sp; sp = sp->next) {
8909                 setvar0(n->nfor.var, sp->text);
8910                 status = evaltree(n->nfor.body, flags);
8911                 if (skiploop() & ~SKIPCONT)
8912                         break;
8913         }
8914         loopnest--;
8915         popstackmark(&smark);
8916
8917         return status;
8918 }
8919
8920 static int
8921 evalcase(union node *n, int flags)
8922 {
8923         union node *cp;
8924         union node *patp;
8925         struct arglist arglist;
8926         struct stackmark smark;
8927         int status = 0;
8928
8929         setstackmark(&smark);
8930         arglist.list = NULL;
8931         arglist.lastp = &arglist.list;
8932         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8933         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8934                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8935                         if (casematch(patp, arglist.list->text)) {
8936                                 /* Ensure body is non-empty as otherwise
8937                                  * EV_EXIT may prevent us from setting the
8938                                  * exit status.
8939                                  */
8940                                 if (evalskip == 0 && cp->nclist.body) {
8941                                         status = evaltree(cp->nclist.body, flags);
8942                                 }
8943                                 goto out;
8944                         }
8945                 }
8946         }
8947  out:
8948         popstackmark(&smark);
8949
8950         return status;
8951 }
8952
8953 /*
8954  * Kick off a subshell to evaluate a tree.
8955  */
8956 static int
8957 evalsubshell(union node *n, int flags)
8958 {
8959         struct job *jp;
8960         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8961         int status;
8962
8963         expredir(n->nredir.redirect);
8964         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8965                 goto nofork;
8966         INT_OFF;
8967         if (backgnd == FORK_FG)
8968                 get_tty_state();
8969         jp = makejob(/*n,*/ 1);
8970         if (forkshell(jp, n, backgnd) == 0) {
8971                 /* child */
8972                 INT_ON;
8973                 flags |= EV_EXIT;
8974                 if (backgnd)
8975                         flags &= ~EV_TESTED;
8976  nofork:
8977                 redirect(n->nredir.redirect, 0);
8978                 evaltreenr(n->nredir.n, flags);
8979                 /* never returns */
8980         }
8981         /* parent */
8982         status = 0;
8983         if (backgnd == FORK_FG)
8984                 status = waitforjob(jp);
8985         INT_ON;
8986         return status;
8987 }
8988
8989 /*
8990  * Compute the names of the files in a redirection list.
8991  */
8992 static void fixredir(union node *, const char *, int);
8993 static void
8994 expredir(union node *n)
8995 {
8996         union node *redir;
8997
8998         for (redir = n; redir; redir = redir->nfile.next) {
8999                 struct arglist fn;
9000
9001                 fn.list = NULL;
9002                 fn.lastp = &fn.list;
9003                 switch (redir->type) {
9004                 case NFROMTO:
9005                 case NFROM:
9006                 case NTO:
9007 #if BASH_REDIR_OUTPUT
9008                 case NTO2:
9009 #endif
9010                 case NCLOBBER:
9011                 case NAPPEND:
9012                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9013                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9014 #if BASH_REDIR_OUTPUT
9015  store_expfname:
9016 #endif
9017 #if 0
9018 // By the design of stack allocator, the loop of this kind:
9019 //      while true; do while true; do break; done </dev/null; done
9020 // will look like a memory leak: ash plans to free expfname's
9021 // of "/dev/null" as soon as it finishes running the loop
9022 // (in this case, never).
9023 // This "fix" is wrong:
9024                         if (redir->nfile.expfname)
9025                                 stunalloc(redir->nfile.expfname);
9026 // It results in corrupted state of stacked allocations.
9027 #endif
9028                         redir->nfile.expfname = fn.list->text;
9029                         break;
9030                 case NFROMFD:
9031                 case NTOFD: /* >& */
9032                         if (redir->ndup.vname) {
9033                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9034                                 if (fn.list == NULL)
9035                                         ash_msg_and_raise_error("redir error");
9036 #if BASH_REDIR_OUTPUT
9037 //FIXME: we used expandarg with different args!
9038                                 if (!isdigit_str9(fn.list->text)) {
9039                                         /* >&file, not >&fd */
9040                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9041                                                 ash_msg_and_raise_error("redir error");
9042                                         redir->type = NTO2;
9043                                         goto store_expfname;
9044                                 }
9045 #endif
9046                                 fixredir(redir, fn.list->text, 1);
9047                         }
9048                         break;
9049                 }
9050         }
9051 }
9052
9053 /*
9054  * Evaluate a pipeline.  All the processes in the pipeline are children
9055  * of the process creating the pipeline.  (This differs from some versions
9056  * of the shell, which make the last process in a pipeline the parent
9057  * of all the rest.)
9058  */
9059 static int
9060 evalpipe(union node *n, int flags)
9061 {
9062         struct job *jp;
9063         struct nodelist *lp;
9064         int pipelen;
9065         int prevfd;
9066         int pip[2];
9067         int status = 0;
9068
9069         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9070         pipelen = 0;
9071         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9072                 pipelen++;
9073         flags |= EV_EXIT;
9074         INT_OFF;
9075         if (n->npipe.pipe_backgnd == 0)
9076                 get_tty_state();
9077         jp = makejob(/*n,*/ pipelen);
9078         prevfd = -1;
9079         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9080                 prehash(lp->n);
9081                 pip[1] = -1;
9082                 if (lp->next) {
9083                         if (pipe(pip) < 0) {
9084                                 close(prevfd);
9085                                 ash_msg_and_raise_error("pipe call failed");
9086                         }
9087                 }
9088                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9089                         /* child */
9090                         INT_ON;
9091                         if (pip[1] >= 0) {
9092                                 close(pip[0]);
9093                         }
9094                         if (prevfd > 0) {
9095                                 dup2(prevfd, 0);
9096                                 close(prevfd);
9097                         }
9098                         if (pip[1] > 1) {
9099                                 dup2(pip[1], 1);
9100                                 close(pip[1]);
9101                         }
9102                         evaltreenr(lp->n, flags);
9103                         /* never returns */
9104                 }
9105                 /* parent */
9106                 if (prevfd >= 0)
9107                         close(prevfd);
9108                 prevfd = pip[0];
9109                 /* Don't want to trigger debugging */
9110                 if (pip[1] != -1)
9111                         close(pip[1]);
9112         }
9113         if (n->npipe.pipe_backgnd == 0) {
9114                 status = waitforjob(jp);
9115                 TRACE(("evalpipe:  job done exit status %d\n", status));
9116         }
9117         INT_ON;
9118
9119         return status;
9120 }
9121
9122 /*
9123  * Controls whether the shell is interactive or not.
9124  */
9125 static void
9126 setinteractive(int on)
9127 {
9128         static smallint is_interactive;
9129
9130         if (++on == is_interactive)
9131                 return;
9132         is_interactive = on;
9133         setsignal(SIGINT);
9134         setsignal(SIGQUIT);
9135         setsignal(SIGTERM);
9136 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9137         if (is_interactive > 1) {
9138                 /* Looks like they want an interactive shell */
9139                 static smallint did_banner;
9140
9141                 if (!did_banner) {
9142                         /* note: ash and hush share this string */
9143                         out1fmt("\n\n%s %s\n"
9144                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9145                                 "\n",
9146                                 bb_banner,
9147                                 "built-in shell (ash)"
9148                         );
9149                         did_banner = 1;
9150                 }
9151         }
9152 #endif
9153 }
9154
9155 static void
9156 optschanged(void)
9157 {
9158 #if DEBUG
9159         opentrace();
9160 #endif
9161         setinteractive(iflag);
9162         setjobctl(mflag);
9163 #if ENABLE_FEATURE_EDITING_VI
9164         if (viflag)
9165                 line_input_state->flags |= VI_MODE;
9166         else
9167                 line_input_state->flags &= ~VI_MODE;
9168 #else
9169         viflag = 0; /* forcibly keep the option off */
9170 #endif
9171 }
9172
9173 static struct localvar *localvars;
9174
9175 /*
9176  * Called after a function returns.
9177  * Interrupts must be off.
9178  */
9179 static void
9180 poplocalvars(void)
9181 {
9182         struct localvar *lvp;
9183         struct var *vp;
9184
9185         while ((lvp = localvars) != NULL) {
9186                 localvars = lvp->next;
9187                 vp = lvp->vp;
9188                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9189                 if (vp == NULL) {       /* $- saved */
9190                         memcpy(optlist, lvp->text, sizeof(optlist));
9191                         free((char*)lvp->text);
9192                         optschanged();
9193                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9194                         unsetvar(vp->var_text);
9195                 } else {
9196                         if (vp->var_func)
9197                                 vp->var_func(var_end(lvp->text));
9198                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9199                                 free((char*)vp->var_text);
9200                         vp->flags = lvp->flags;
9201                         vp->var_text = lvp->text;
9202                 }
9203                 free(lvp);
9204         }
9205 }
9206
9207 static int
9208 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9209 {
9210         volatile struct shparam saveparam;
9211         struct localvar *volatile savelocalvars;
9212         struct jmploc *volatile savehandler;
9213         struct jmploc jmploc;
9214         int e;
9215
9216         saveparam = shellparam;
9217         savelocalvars = localvars;
9218         savehandler = exception_handler;
9219         e = setjmp(jmploc.loc);
9220         if (e) {
9221                 goto funcdone;
9222         }
9223         INT_OFF;
9224         exception_handler = &jmploc;
9225         localvars = NULL;
9226         shellparam.malloced = 0;
9227         func->count++;
9228         funcnest++;
9229         INT_ON;
9230         shellparam.nparam = argc - 1;
9231         shellparam.p = argv + 1;
9232 #if ENABLE_ASH_GETOPTS
9233         shellparam.optind = 1;
9234         shellparam.optoff = -1;
9235 #endif
9236         evaltree(func->n.narg.next, flags & EV_TESTED);
9237  funcdone:
9238         INT_OFF;
9239         funcnest--;
9240         freefunc(func);
9241         poplocalvars();
9242         localvars = savelocalvars;
9243         freeparam(&shellparam);
9244         shellparam = saveparam;
9245         exception_handler = savehandler;
9246         INT_ON;
9247         evalskip &= ~SKIPFUNC;
9248         return e;
9249 }
9250
9251 /*
9252  * Make a variable a local variable.  When a variable is made local, it's
9253  * value and flags are saved in a localvar structure.  The saved values
9254  * will be restored when the shell function returns.  We handle the name
9255  * "-" as a special case: it makes changes to "set +-options" local
9256  * (options will be restored on return from the function).
9257  */
9258 static void
9259 mklocal(char *name)
9260 {
9261         struct localvar *lvp;
9262         struct var **vpp;
9263         struct var *vp;
9264         char *eq = strchr(name, '=');
9265
9266         INT_OFF;
9267         /* Cater for duplicate "local". Examples:
9268          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9269          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9270          */
9271         lvp = localvars;
9272         while (lvp) {
9273                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9274                         if (eq)
9275                                 setvareq(name, 0);
9276                         /* else:
9277                          * it's a duplicate "local VAR" declaration, do nothing
9278                          */
9279                         goto ret;
9280                 }
9281                 lvp = lvp->next;
9282         }
9283
9284         lvp = ckzalloc(sizeof(*lvp));
9285         if (LONE_DASH(name)) {
9286                 char *p;
9287                 p = ckmalloc(sizeof(optlist));
9288                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9289                 vp = NULL;
9290         } else {
9291                 vpp = hashvar(name);
9292                 vp = *findvar(vpp, name);
9293                 if (vp == NULL) {
9294                         /* variable did not exist yet */
9295                         if (eq)
9296                                 setvareq(name, VSTRFIXED);
9297                         else
9298                                 setvar(name, NULL, VSTRFIXED);
9299                         vp = *vpp;      /* the new variable */
9300                         lvp->flags = VUNSET;
9301                 } else {
9302                         lvp->text = vp->var_text;
9303                         lvp->flags = vp->flags;
9304                         /* make sure neither "struct var" nor string gets freed
9305                          * during (un)setting:
9306                          */
9307                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9308                         if (eq)
9309                                 setvareq(name, 0);
9310                         else
9311                                 /* "local VAR" unsets VAR: */
9312                                 setvar0(name, NULL);
9313                 }
9314         }
9315         lvp->vp = vp;
9316         lvp->next = localvars;
9317         localvars = lvp;
9318  ret:
9319         INT_ON;
9320 }
9321
9322 /*
9323  * The "local" command.
9324  */
9325 static int FAST_FUNC
9326 localcmd(int argc UNUSED_PARAM, char **argv)
9327 {
9328         char *name;
9329
9330         if (!funcnest)
9331                 ash_msg_and_raise_error("not in a function");
9332
9333         argv = argptr;
9334         while ((name = *argv++) != NULL) {
9335                 mklocal(name);
9336         }
9337         return 0;
9338 }
9339
9340 static int FAST_FUNC
9341 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9342 {
9343         return 1;
9344 }
9345
9346 static int FAST_FUNC
9347 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9348 {
9349         return 0;
9350 }
9351
9352 static int FAST_FUNC
9353 execcmd(int argc UNUSED_PARAM, char **argv)
9354 {
9355         optionarg = NULL;
9356         while (nextopt("a:") != '\0')
9357                 /* nextopt() sets optionarg to "-a ARGV0" */;
9358
9359         argv = argptr;
9360         if (argv[0]) {
9361                 char *prog;
9362
9363                 iflag = 0;              /* exit on error */
9364                 mflag = 0;
9365                 optschanged();
9366                 /* We should set up signals for "exec CMD"
9367                  * the same way as for "CMD" without "exec".
9368                  * But optschanged->setinteractive->setsignal
9369                  * still thought we are a root shell. Therefore, for example,
9370                  * SIGQUIT is still set to IGN. Fix it:
9371                  */
9372                 shlvl++;
9373                 setsignal(SIGQUIT);
9374                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9375                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9376                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9377
9378                 prog = argv[0];
9379                 if (optionarg)
9380                         argv[0] = optionarg;
9381                 shellexec(prog, argv, pathval(), 0);
9382                 /* NOTREACHED */
9383         }
9384         return 0;
9385 }
9386
9387 /*
9388  * The return command.
9389  */
9390 static int FAST_FUNC
9391 returncmd(int argc UNUSED_PARAM, char **argv)
9392 {
9393         /*
9394          * If called outside a function, do what ksh does;
9395          * skip the rest of the file.
9396          */
9397         evalskip = SKIPFUNC;
9398         return argv[1] ? number(argv[1]) : exitstatus;
9399 }
9400
9401 /* Forward declarations for builtintab[] */
9402 static int breakcmd(int, char **) FAST_FUNC;
9403 static int dotcmd(int, char **) FAST_FUNC;
9404 static int evalcmd(int, char **, int) FAST_FUNC;
9405 static int exitcmd(int, char **) FAST_FUNC;
9406 static int exportcmd(int, char **) FAST_FUNC;
9407 #if ENABLE_ASH_GETOPTS
9408 static int getoptscmd(int, char **) FAST_FUNC;
9409 #endif
9410 #if ENABLE_ASH_HELP
9411 static int helpcmd(int, char **) FAST_FUNC;
9412 #endif
9413 #if MAX_HISTORY
9414 static int historycmd(int, char **) FAST_FUNC;
9415 #endif
9416 #if ENABLE_FEATURE_SH_MATH
9417 static int letcmd(int, char **) FAST_FUNC;
9418 #endif
9419 static int readcmd(int, char **) FAST_FUNC;
9420 static int setcmd(int, char **) FAST_FUNC;
9421 static int shiftcmd(int, char **) FAST_FUNC;
9422 static int timescmd(int, char **) FAST_FUNC;
9423 static int trapcmd(int, char **) FAST_FUNC;
9424 static int umaskcmd(int, char **) FAST_FUNC;
9425 static int unsetcmd(int, char **) FAST_FUNC;
9426 static int ulimitcmd(int, char **) FAST_FUNC;
9427
9428 #define BUILTIN_NOSPEC          "0"
9429 #define BUILTIN_SPECIAL         "1"
9430 #define BUILTIN_REGULAR         "2"
9431 #define BUILTIN_SPEC_REG        "3"
9432 #define BUILTIN_ASSIGN          "4"
9433 #define BUILTIN_SPEC_ASSG       "5"
9434 #define BUILTIN_REG_ASSG        "6"
9435 #define BUILTIN_SPEC_REG_ASSG   "7"
9436
9437 /* Stubs for calling non-FAST_FUNC's */
9438 #if ENABLE_ASH_ECHO
9439 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9440 #endif
9441 #if ENABLE_ASH_PRINTF
9442 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9443 #endif
9444 #if ENABLE_ASH_TEST || BASH_TEST2
9445 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9446 #endif
9447
9448 /* Keep these in proper order since it is searched via bsearch() */
9449 static const struct builtincmd builtintab[] = {
9450         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9451         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9452 #if ENABLE_ASH_TEST
9453         { BUILTIN_REGULAR       "["       , testcmd    },
9454 #endif
9455 #if BASH_TEST2
9456         { BUILTIN_REGULAR       "[["      , testcmd    },
9457 #endif
9458 #if ENABLE_ASH_ALIAS
9459         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9460 #endif
9461 #if JOBS
9462         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9463 #endif
9464         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9465         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9466         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9467 #if ENABLE_ASH_CMDCMD
9468         { BUILTIN_REGULAR       "command" , commandcmd },
9469 #endif
9470         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9471 #if ENABLE_ASH_ECHO
9472         { BUILTIN_REGULAR       "echo"    , echocmd    },
9473 #endif
9474         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9475         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9476         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9477         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9478         { BUILTIN_REGULAR       "false"   , falsecmd   },
9479 #if JOBS
9480         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9481 #endif
9482 #if ENABLE_ASH_GETOPTS
9483         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9484 #endif
9485         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9486 #if ENABLE_ASH_HELP
9487         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9488 #endif
9489 #if MAX_HISTORY
9490         { BUILTIN_NOSPEC        "history" , historycmd },
9491 #endif
9492 #if JOBS
9493         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9494         { BUILTIN_REGULAR       "kill"    , killcmd    },
9495 #endif
9496 #if ENABLE_FEATURE_SH_MATH
9497         { BUILTIN_NOSPEC        "let"     , letcmd     },
9498 #endif
9499         { BUILTIN_ASSIGN        "local"   , localcmd   },
9500 #if ENABLE_ASH_PRINTF
9501         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9502 #endif
9503         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9504         { BUILTIN_REGULAR       "read"    , readcmd    },
9505         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9506         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9507         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9508         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9509 #if BASH_SOURCE
9510         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9511 #endif
9512 #if ENABLE_ASH_TEST
9513         { BUILTIN_REGULAR       "test"    , testcmd    },
9514 #endif
9515         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9516         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9517         { BUILTIN_REGULAR       "true"    , truecmd    },
9518         { BUILTIN_NOSPEC        "type"    , typecmd    },
9519         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9520         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9521 #if ENABLE_ASH_ALIAS
9522         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9523 #endif
9524         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9525         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9526 };
9527
9528 /* Should match the above table! */
9529 #define COMMANDCMD (builtintab + \
9530         /* . : */       2 + \
9531         /* [ */         1 * ENABLE_ASH_TEST + \
9532         /* [[ */        1 * BASH_TEST2 + \
9533         /* alias */     1 * ENABLE_ASH_ALIAS + \
9534         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9535         /* break cd cddir  */   3)
9536 #define EVALCMD (COMMANDCMD + \
9537         /* command */   1 * ENABLE_ASH_CMDCMD + \
9538         /* continue */  1 + \
9539         /* echo */      1 * ENABLE_ASH_ECHO + \
9540         0)
9541 #define EXECCMD (EVALCMD + \
9542         /* eval */      1)
9543
9544 /*
9545  * Search the table of builtin commands.
9546  */
9547 static int
9548 pstrcmp1(const void *a, const void *b)
9549 {
9550         return strcmp((char*)a, *(char**)b + 1);
9551 }
9552 static struct builtincmd *
9553 find_builtin(const char *name)
9554 {
9555         struct builtincmd *bp;
9556
9557         bp = bsearch(
9558                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9559                 pstrcmp1
9560         );
9561         return bp;
9562 }
9563
9564 /*
9565  * Execute a simple command.
9566  */
9567 static int
9568 isassignment(const char *p)
9569 {
9570         const char *q = endofname(p);
9571         if (p == q)
9572                 return 0;
9573         return *q == '=';
9574 }
9575 static int FAST_FUNC
9576 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9577 {
9578         /* Preserve exitstatus of a previous possible redirection
9579          * as POSIX mandates */
9580         return back_exitstatus;
9581 }
9582 static int
9583 evalcommand(union node *cmd, int flags)
9584 {
9585         static const struct builtincmd null_bltin = {
9586                 "\0\0", bltincmd /* why three NULs? */
9587         };
9588         struct stackmark smark;
9589         union node *argp;
9590         struct arglist arglist;
9591         struct arglist varlist;
9592         char **argv;
9593         int argc;
9594         const struct strlist *sp;
9595         struct cmdentry cmdentry;
9596         struct job *jp;
9597         char *lastarg;
9598         const char *path;
9599         int spclbltin;
9600         int status;
9601         char **nargv;
9602         struct builtincmd *bcmd;
9603         smallint cmd_is_exec;
9604         smallint pseudovarflag = 0;
9605
9606         /* First expand the arguments. */
9607         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9608         setstackmark(&smark);
9609         back_exitstatus = 0;
9610
9611         cmdentry.cmdtype = CMDBUILTIN;
9612         cmdentry.u.cmd = &null_bltin;
9613         varlist.lastp = &varlist.list;
9614         *varlist.lastp = NULL;
9615         arglist.lastp = &arglist.list;
9616         *arglist.lastp = NULL;
9617
9618         argc = 0;
9619         if (cmd->ncmd.args) {
9620                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9621                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9622         }
9623
9624         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9625                 struct strlist **spp;
9626
9627                 spp = arglist.lastp;
9628                 if (pseudovarflag && isassignment(argp->narg.text))
9629                         expandarg(argp, &arglist, EXP_VARTILDE);
9630                 else
9631                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9632
9633                 for (sp = *spp; sp; sp = sp->next)
9634                         argc++;
9635         }
9636
9637         /* Reserve one extra spot at the front for shellexec. */
9638         nargv = stalloc(sizeof(char *) * (argc + 2));
9639         argv = ++nargv;
9640         for (sp = arglist.list; sp; sp = sp->next) {
9641                 TRACE(("evalcommand arg: %s\n", sp->text));
9642                 *nargv++ = sp->text;
9643         }
9644         *nargv = NULL;
9645
9646         lastarg = NULL;
9647         if (iflag && funcnest == 0 && argc > 0)
9648                 lastarg = nargv[-1];
9649
9650         preverrout_fd = 2;
9651         expredir(cmd->ncmd.redirect);
9652         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9653
9654         path = vpath.var_text;
9655         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9656                 struct strlist **spp;
9657                 char *p;
9658
9659                 spp = varlist.lastp;
9660                 expandarg(argp, &varlist, EXP_VARTILDE);
9661
9662                 /*
9663                  * Modify the command lookup path, if a PATH= assignment
9664                  * is present
9665                  */
9666                 p = (*spp)->text;
9667                 if (varcmp(p, path) == 0)
9668                         path = p;
9669         }
9670
9671         /* Print the command if xflag is set. */
9672         if (xflag) {
9673                 int n;
9674                 const char *p = " %s" + 1;
9675
9676                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9677                 sp = varlist.list;
9678                 for (n = 0; n < 2; n++) {
9679                         while (sp) {
9680                                 fdprintf(preverrout_fd, p, sp->text);
9681                                 sp = sp->next;
9682                                 p = " %s";
9683                         }
9684                         sp = arglist.list;
9685                 }
9686                 safe_write(preverrout_fd, "\n", 1);
9687         }
9688
9689         cmd_is_exec = 0;
9690         spclbltin = -1;
9691
9692         /* Now locate the command. */
9693         if (argc) {
9694                 int cmd_flag = DO_ERR;
9695 #if ENABLE_ASH_CMDCMD
9696                 const char *oldpath = path + 5;
9697 #endif
9698                 path += 5;
9699                 for (;;) {
9700                         find_command(argv[0], &cmdentry, cmd_flag, path);
9701                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9702                                 flush_stdout_stderr();
9703                                 status = 127;
9704                                 goto bail;
9705                         }
9706
9707                         /* implement bltin and command here */
9708                         if (cmdentry.cmdtype != CMDBUILTIN)
9709                                 break;
9710                         if (spclbltin < 0)
9711                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9712                         if (cmdentry.u.cmd == EXECCMD)
9713                                 cmd_is_exec = 1;
9714 #if ENABLE_ASH_CMDCMD
9715                         if (cmdentry.u.cmd == COMMANDCMD) {
9716                                 path = oldpath;
9717                                 nargv = parse_command_args(argv, &path);
9718                                 if (!nargv)
9719                                         break;
9720                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9721                                  * nargv => "PROG". path is updated if -p.
9722                                  */
9723                                 argc -= nargv - argv;
9724                                 argv = nargv;
9725                                 cmd_flag |= DO_NOFUNC;
9726                         } else
9727 #endif
9728                                 break;
9729                 }
9730         }
9731
9732         if (status) {
9733  bail:
9734                 exitstatus = status;
9735
9736                 /* We have a redirection error. */
9737                 if (spclbltin > 0)
9738                         raise_exception(EXERROR);
9739
9740                 goto out;
9741         }
9742
9743         /* Execute the command. */
9744         switch (cmdentry.cmdtype) {
9745         default: {
9746
9747 #if ENABLE_FEATURE_SH_NOFORK
9748 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9749  *     around run_nofork_applet() call.
9750  * (2) Should this check also be done in forkshell()?
9751  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9752  */
9753                 /* find_command() encodes applet_no as (-2 - applet_no) */
9754                 int applet_no = (- cmdentry.u.index - 2);
9755                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9756                         listsetvar(varlist.list, VEXPORT|VSTACK);
9757                         /* run <applet>_main() */
9758                         status = run_nofork_applet(applet_no, argv);
9759                         break;
9760                 }
9761 #endif
9762                 /* Can we avoid forking off? For example, very last command
9763                  * in a script or a subshell does not need forking,
9764                  * we can just exec it.
9765                  */
9766                 if (!(flags & EV_EXIT) || may_have_traps) {
9767                         /* No, forking off a child is necessary */
9768                         INT_OFF;
9769                         get_tty_state();
9770                         jp = makejob(/*cmd,*/ 1);
9771                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9772                                 /* parent */
9773                                 status = waitforjob(jp);
9774                                 INT_ON;
9775                                 TRACE(("forked child exited with %d\n", status));
9776                                 break;
9777                         }
9778                         /* child */
9779                         FORCE_INT_ON;
9780                         /* fall through to exec'ing external program */
9781                 }
9782                 listsetvar(varlist.list, VEXPORT|VSTACK);
9783                 shellexec(argv[0], argv, path, cmdentry.u.index);
9784                 /* NOTREACHED */
9785         } /* default */
9786         case CMDBUILTIN:
9787                 cmdenviron = varlist.list;
9788                 if (cmdenviron) {
9789                         struct strlist *list = cmdenviron;
9790                         int i = VNOSET;
9791                         if (spclbltin > 0 || argc == 0) {
9792                                 i = 0;
9793                                 if (cmd_is_exec && argc > 1)
9794                                         i = VEXPORT;
9795                         }
9796                         listsetvar(list, i);
9797                 }
9798                 /* Tight loop with builtins only:
9799                  * "while kill -0 $child; do true; done"
9800                  * will never exit even if $child died, unless we do this
9801                  * to reap the zombie and make kill detect that it's gone: */
9802                 dowait(DOWAIT_NONBLOCK, NULL);
9803
9804                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9805                         if (exception_type == EXERROR && spclbltin <= 0) {
9806                                 FORCE_INT_ON;
9807                                 goto readstatus;
9808                         }
9809  raise:
9810                         longjmp(exception_handler->loc, 1);
9811                 }
9812                 goto readstatus;
9813
9814         case CMDFUNCTION:
9815                 listsetvar(varlist.list, 0);
9816                 /* See above for the rationale */
9817                 dowait(DOWAIT_NONBLOCK, NULL);
9818                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9819                         goto raise;
9820  readstatus:
9821                 status = exitstatus;
9822                 break;
9823         } /* switch */
9824
9825  out:
9826         if (cmd->ncmd.redirect)
9827                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9828         if (lastarg) {
9829                 /* dsl: I think this is intended to be used to support
9830                  * '_' in 'vi' command mode during line editing...
9831                  * However I implemented that within libedit itself.
9832                  */
9833                 setvar0("_", lastarg);
9834         }
9835         popstackmark(&smark);
9836
9837         return status;
9838 }
9839
9840 static int
9841 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9842 {
9843         char *volatile savecmdname;
9844         struct jmploc *volatile savehandler;
9845         struct jmploc jmploc;
9846         int status;
9847         int i;
9848
9849         savecmdname = commandname;
9850         savehandler = exception_handler;
9851         i = setjmp(jmploc.loc);
9852         if (i)
9853                 goto cmddone;
9854         exception_handler = &jmploc;
9855         commandname = argv[0];
9856         argptr = argv + 1;
9857         optptr = NULL;                  /* initialize nextopt */
9858         if (cmd == EVALCMD)
9859                 status = evalcmd(argc, argv, flags);
9860         else
9861                 status = (*cmd->builtin)(argc, argv);
9862         flush_stdout_stderr();
9863         status |= ferror(stdout);
9864         exitstatus = status;
9865  cmddone:
9866         clearerr(stdout);
9867         commandname = savecmdname;
9868         exception_handler = savehandler;
9869
9870         return i;
9871 }
9872
9873 static int
9874 goodname(const char *p)
9875 {
9876         return endofname(p)[0] == '\0';
9877 }
9878
9879
9880 /*
9881  * Search for a command.  This is called before we fork so that the
9882  * location of the command will be available in the parent as well as
9883  * the child.  The check for "goodname" is an overly conservative
9884  * check that the name will not be subject to expansion.
9885  */
9886 static void
9887 prehash(union node *n)
9888 {
9889         struct cmdentry entry;
9890
9891         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9892                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9893 }
9894
9895
9896 /* ============ Builtin commands
9897  *
9898  * Builtin commands whose functions are closely tied to evaluation
9899  * are implemented here.
9900  */
9901
9902 /*
9903  * Handle break and continue commands.  Break, continue, and return are
9904  * all handled by setting the evalskip flag.  The evaluation routines
9905  * above all check this flag, and if it is set they start skipping
9906  * commands rather than executing them.  The variable skipcount is
9907  * the number of loops to break/continue, or the number of function
9908  * levels to return.  (The latter is always 1.)  It should probably
9909  * be an error to break out of more loops than exist, but it isn't
9910  * in the standard shell so we don't make it one here.
9911  */
9912 static int FAST_FUNC
9913 breakcmd(int argc UNUSED_PARAM, char **argv)
9914 {
9915         int n = argv[1] ? number(argv[1]) : 1;
9916
9917         if (n <= 0)
9918                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9919         if (n > loopnest)
9920                 n = loopnest;
9921         if (n > 0) {
9922                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9923                 skipcount = n;
9924         }
9925         return 0;
9926 }
9927
9928
9929 /*
9930  * This implements the input routines used by the parser.
9931  */
9932
9933 enum {
9934         INPUT_PUSH_FILE = 1,
9935         INPUT_NOFILE_OK = 2,
9936 };
9937
9938 static smallint checkkwd;
9939 /* values of checkkwd variable */
9940 #define CHKALIAS        0x1
9941 #define CHKKWD          0x2
9942 #define CHKNL           0x4
9943
9944 /*
9945  * Push a string back onto the input at this current parsefile level.
9946  * We handle aliases this way.
9947  */
9948 #if !ENABLE_ASH_ALIAS
9949 #define pushstring(s, ap) pushstring(s)
9950 #endif
9951 static void
9952 pushstring(char *s, struct alias *ap)
9953 {
9954         struct strpush *sp;
9955         int len;
9956
9957         len = strlen(s);
9958         INT_OFF;
9959         if (g_parsefile->strpush) {
9960                 sp = ckzalloc(sizeof(*sp));
9961                 sp->prev = g_parsefile->strpush;
9962         } else {
9963                 sp = &(g_parsefile->basestrpush);
9964         }
9965         g_parsefile->strpush = sp;
9966         sp->prev_string = g_parsefile->next_to_pgetc;
9967         sp->prev_left_in_line = g_parsefile->left_in_line;
9968         sp->unget = g_parsefile->unget;
9969         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
9970 #if ENABLE_ASH_ALIAS
9971         sp->ap = ap;
9972         if (ap) {
9973                 ap->flag |= ALIASINUSE;
9974                 sp->string = s;
9975         }
9976 #endif
9977         g_parsefile->next_to_pgetc = s;
9978         g_parsefile->left_in_line = len;
9979         g_parsefile->unget = 0;
9980         INT_ON;
9981 }
9982
9983 static void
9984 popstring(void)
9985 {
9986         struct strpush *sp = g_parsefile->strpush;
9987
9988         INT_OFF;
9989 #if ENABLE_ASH_ALIAS
9990         if (sp->ap) {
9991                 if (g_parsefile->next_to_pgetc[-1] == ' '
9992                  || g_parsefile->next_to_pgetc[-1] == '\t'
9993                 ) {
9994                         checkkwd |= CHKALIAS;
9995                 }
9996                 if (sp->string != sp->ap->val) {
9997                         free(sp->string);
9998                 }
9999                 sp->ap->flag &= ~ALIASINUSE;
10000                 if (sp->ap->flag & ALIASDEAD) {
10001                         unalias(sp->ap->name);
10002                 }
10003         }
10004 #endif
10005         g_parsefile->next_to_pgetc = sp->prev_string;
10006         g_parsefile->left_in_line = sp->prev_left_in_line;
10007         g_parsefile->unget = sp->unget;
10008         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10009         g_parsefile->strpush = sp->prev;
10010         if (sp != &(g_parsefile->basestrpush))
10011                 free(sp);
10012         INT_ON;
10013 }
10014
10015 static int
10016 preadfd(void)
10017 {
10018         int nr;
10019         char *buf = g_parsefile->buf;
10020
10021         g_parsefile->next_to_pgetc = buf;
10022 #if ENABLE_FEATURE_EDITING
10023  retry:
10024         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10025                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10026         else {
10027                 int timeout = -1;
10028 # if ENABLE_ASH_IDLE_TIMEOUT
10029                 if (iflag) {
10030                         const char *tmout_var = lookupvar("TMOUT");
10031                         if (tmout_var) {
10032                                 timeout = atoi(tmout_var) * 1000;
10033                                 if (timeout <= 0)
10034                                         timeout = -1;
10035                         }
10036                 }
10037 # endif
10038 # if ENABLE_FEATURE_TAB_COMPLETION
10039                 line_input_state->path_lookup = pathval();
10040 # endif
10041                 reinit_unicode_for_ash();
10042                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10043                 if (nr == 0) {
10044                         /* ^C pressed, "convert" to SIGINT */
10045                         write(STDOUT_FILENO, "^C", 2);
10046                         if (trap[SIGINT]) {
10047                                 buf[0] = '\n';
10048                                 buf[1] = '\0';
10049                                 raise(SIGINT);
10050                                 return 1;
10051                         }
10052                         exitstatus = 128 + SIGINT;
10053                         bb_putchar('\n');
10054                         goto retry;
10055                 }
10056                 if (nr < 0) {
10057                         if (errno == 0) {
10058                                 /* Ctrl+D pressed */
10059                                 nr = 0;
10060                         }
10061 # if ENABLE_ASH_IDLE_TIMEOUT
10062                         else if (errno == EAGAIN && timeout > 0) {
10063                                 puts("\007timed out waiting for input: auto-logout");
10064                                 exitshell();
10065                         }
10066 # endif
10067                 }
10068         }
10069 #else
10070         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10071 #endif
10072
10073 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10074         if (nr < 0) {
10075                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10076                         int flags = fcntl(0, F_GETFL);
10077                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10078                                 flags &= ~O_NONBLOCK;
10079                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10080                                         out2str("sh: turning off NDELAY mode\n");
10081                                         goto retry;
10082                                 }
10083                         }
10084                 }
10085         }
10086 #endif
10087         return nr;
10088 }
10089
10090 /*
10091  * Refill the input buffer and return the next input character:
10092  *
10093  * 1) If a string was pushed back on the input, pop it;
10094  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10095  *    or we are reading from a string so we can't refill the buffer,
10096  *    return EOF.
10097  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10098  * 4) Process input up to the next newline, deleting nul characters.
10099  */
10100 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10101 #define pgetc_debug(...) ((void)0)
10102 static int pgetc(void);
10103 static int
10104 preadbuffer(void)
10105 {
10106         char *q;
10107         int more;
10108
10109         if (g_parsefile->strpush) {
10110 #if ENABLE_ASH_ALIAS
10111                 if (g_parsefile->left_in_line == -1
10112                  && g_parsefile->strpush->ap
10113                  && g_parsefile->next_to_pgetc[-1] != ' '
10114                  && g_parsefile->next_to_pgetc[-1] != '\t'
10115                 ) {
10116                         pgetc_debug("preadbuffer PEOA");
10117                         return PEOA;
10118                 }
10119 #endif
10120                 popstring();
10121                 return pgetc();
10122         }
10123         /* on both branches above g_parsefile->left_in_line < 0.
10124          * "pgetc" needs refilling.
10125          */
10126
10127         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10128          * pungetc() may increment it a few times.
10129          * Assuming it won't increment it to less than -90.
10130          */
10131         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10132                 pgetc_debug("preadbuffer PEOF1");
10133                 /* even in failure keep left_in_line and next_to_pgetc
10134                  * in lock step, for correct multi-layer pungetc.
10135                  * left_in_line was decremented before preadbuffer(),
10136                  * must inc next_to_pgetc: */
10137                 g_parsefile->next_to_pgetc++;
10138                 return PEOF;
10139         }
10140
10141         more = g_parsefile->left_in_buffer;
10142         if (more <= 0) {
10143                 flush_stdout_stderr();
10144  again:
10145                 more = preadfd();
10146                 if (more <= 0) {
10147                         /* don't try reading again */
10148                         g_parsefile->left_in_line = -99;
10149                         pgetc_debug("preadbuffer PEOF2");
10150                         g_parsefile->next_to_pgetc++;
10151                         return PEOF;
10152                 }
10153         }
10154
10155         /* Find out where's the end of line.
10156          * Set g_parsefile->left_in_line
10157          * and g_parsefile->left_in_buffer acordingly.
10158          * NUL chars are deleted.
10159          */
10160         q = g_parsefile->next_to_pgetc;
10161         for (;;) {
10162                 char c;
10163
10164                 more--;
10165
10166                 c = *q;
10167                 if (c == '\0') {
10168                         memmove(q, q + 1, more);
10169                 } else {
10170                         q++;
10171                         if (c == '\n') {
10172                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10173                                 break;
10174                         }
10175                 }
10176
10177                 if (more <= 0) {
10178                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10179                         if (g_parsefile->left_in_line < 0)
10180                                 goto again;
10181                         break;
10182                 }
10183         }
10184         g_parsefile->left_in_buffer = more;
10185
10186         if (vflag) {
10187                 char save = *q;
10188                 *q = '\0';
10189                 out2str(g_parsefile->next_to_pgetc);
10190                 *q = save;
10191         }
10192
10193         pgetc_debug("preadbuffer at %d:%p'%s'",
10194                         g_parsefile->left_in_line,
10195                         g_parsefile->next_to_pgetc,
10196                         g_parsefile->next_to_pgetc);
10197         return (unsigned char)*g_parsefile->next_to_pgetc++;
10198 }
10199
10200 static void
10201 nlprompt(void)
10202 {
10203         g_parsefile->linno++;
10204         setprompt_if(doprompt, 2);
10205 }
10206 static void
10207 nlnoprompt(void)
10208 {
10209         g_parsefile->linno++;
10210         needprompt = doprompt;
10211 }
10212
10213 static int
10214 pgetc(void)
10215 {
10216         int c;
10217
10218         pgetc_debug("pgetc at %d:%p'%s'",
10219                         g_parsefile->left_in_line,
10220                         g_parsefile->next_to_pgetc,
10221                         g_parsefile->next_to_pgetc);
10222         if (g_parsefile->unget)
10223                 return g_parsefile->lastc[--g_parsefile->unget];
10224
10225         if (--g_parsefile->left_in_line >= 0)
10226                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10227         else
10228                 c = preadbuffer();
10229
10230         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10231         g_parsefile->lastc[0] = c;
10232
10233         return c;
10234 }
10235
10236 #if ENABLE_ASH_ALIAS
10237 static int
10238 pgetc_without_PEOA(void)
10239 {
10240         int c;
10241         do {
10242                 pgetc_debug("pgetc at %d:%p'%s'",
10243                                 g_parsefile->left_in_line,
10244                                 g_parsefile->next_to_pgetc,
10245                                 g_parsefile->next_to_pgetc);
10246                 c = pgetc();
10247         } while (c == PEOA);
10248         return c;
10249 }
10250 #else
10251 # define pgetc_without_PEOA() pgetc()
10252 #endif
10253
10254 /*
10255  * Read a line from the script.
10256  */
10257 static char *
10258 pfgets(char *line, int len)
10259 {
10260         char *p = line;
10261         int nleft = len;
10262         int c;
10263
10264         while (--nleft > 0) {
10265                 c = pgetc_without_PEOA();
10266                 if (c == PEOF) {
10267                         if (p == line)
10268                                 return NULL;
10269                         break;
10270                 }
10271                 *p++ = c;
10272                 if (c == '\n')
10273                         break;
10274         }
10275         *p = '\0';
10276         return line;
10277 }
10278
10279 /*
10280  * Undo a call to pgetc.  Only two characters may be pushed back.
10281  * PEOF may be pushed back.
10282  */
10283 static void
10284 pungetc(void)
10285 {
10286         g_parsefile->unget++;
10287 }
10288
10289 /* This one eats backslash+newline */
10290 static int
10291 pgetc_eatbnl(void)
10292 {
10293         int c;
10294
10295         while ((c = pgetc()) == '\\') {
10296                 if (pgetc() != '\n') {
10297                         pungetc();
10298                         break;
10299                 }
10300
10301                 nlprompt();
10302         }
10303
10304         return c;
10305 }
10306
10307 /*
10308  * To handle the "." command, a stack of input files is used.  Pushfile
10309  * adds a new entry to the stack and popfile restores the previous level.
10310  */
10311 static void
10312 pushfile(void)
10313 {
10314         struct parsefile *pf;
10315
10316         pf = ckzalloc(sizeof(*pf));
10317         pf->prev = g_parsefile;
10318         pf->pf_fd = -1;
10319         /*pf->strpush = NULL; - ckzalloc did it */
10320         /*pf->basestrpush.prev = NULL;*/
10321         /*pf->unget = 0;*/
10322         g_parsefile = pf;
10323 }
10324
10325 static void
10326 popfile(void)
10327 {
10328         struct parsefile *pf = g_parsefile;
10329
10330         if (pf == &basepf)
10331                 return;
10332
10333         INT_OFF;
10334         if (pf->pf_fd >= 0)
10335                 close(pf->pf_fd);
10336         free(pf->buf);
10337         while (pf->strpush)
10338                 popstring();
10339         g_parsefile = pf->prev;
10340         free(pf);
10341         INT_ON;
10342 }
10343
10344 /*
10345  * Return to top level.
10346  */
10347 static void
10348 popallfiles(void)
10349 {
10350         while (g_parsefile != &basepf)
10351                 popfile();
10352 }
10353
10354 /*
10355  * Close the file(s) that the shell is reading commands from.  Called
10356  * after a fork is done.
10357  */
10358 static void
10359 closescript(void)
10360 {
10361         popallfiles();
10362         if (g_parsefile->pf_fd > 0) {
10363                 close(g_parsefile->pf_fd);
10364                 g_parsefile->pf_fd = 0;
10365         }
10366 }
10367
10368 /*
10369  * Like setinputfile, but takes an open file descriptor.  Call this with
10370  * interrupts off.
10371  */
10372 static void
10373 setinputfd(int fd, int push)
10374 {
10375         if (push) {
10376                 pushfile();
10377                 g_parsefile->buf = NULL;
10378         }
10379         g_parsefile->pf_fd = fd;
10380         if (g_parsefile->buf == NULL)
10381                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10382         g_parsefile->left_in_buffer = 0;
10383         g_parsefile->left_in_line = 0;
10384         g_parsefile->linno = 1;
10385 }
10386
10387 /*
10388  * Set the input to take input from a file.  If push is set, push the
10389  * old input onto the stack first.
10390  */
10391 static int
10392 setinputfile(const char *fname, int flags)
10393 {
10394         int fd;
10395
10396         INT_OFF;
10397         fd = open(fname, O_RDONLY);
10398         if (fd < 0) {
10399                 if (flags & INPUT_NOFILE_OK)
10400                         goto out;
10401                 exitstatus = 127;
10402                 ash_msg_and_raise_error("can't open '%s'", fname);
10403         }
10404         if (fd < 10)
10405                 fd = savefd(fd);
10406         else
10407                 close_on_exec_on(fd);
10408         setinputfd(fd, flags & INPUT_PUSH_FILE);
10409  out:
10410         INT_ON;
10411         return fd;
10412 }
10413
10414 /*
10415  * Like setinputfile, but takes input from a string.
10416  */
10417 static void
10418 setinputstring(char *string)
10419 {
10420         INT_OFF;
10421         pushfile();
10422         g_parsefile->next_to_pgetc = string;
10423         g_parsefile->left_in_line = strlen(string);
10424         g_parsefile->buf = NULL;
10425         g_parsefile->linno = 1;
10426         INT_ON;
10427 }
10428
10429
10430 /*
10431  * Routines to check for mail.
10432  */
10433
10434 #if ENABLE_ASH_MAIL
10435
10436 /* Hash of mtimes of mailboxes */
10437 static unsigned mailtime_hash;
10438 /* Set if MAIL or MAILPATH is changed. */
10439 static smallint mail_var_path_changed;
10440
10441 /*
10442  * Print appropriate message(s) if mail has arrived.
10443  * If mail_var_path_changed is set,
10444  * then the value of MAIL has mail_var_path_changed,
10445  * so we just update the values.
10446  */
10447 static void
10448 chkmail(void)
10449 {
10450         const char *mpath;
10451         char *p;
10452         char *q;
10453         unsigned new_hash;
10454         struct stackmark smark;
10455         struct stat statb;
10456
10457         setstackmark(&smark);
10458         mpath = mpathset() ? mpathval() : mailval();
10459         new_hash = 0;
10460         for (;;) {
10461                 p = path_advance(&mpath, nullstr);
10462                 if (p == NULL)
10463                         break;
10464                 if (*p == '\0')
10465                         continue;
10466                 for (q = p; *q; q++)
10467                         continue;
10468 #if DEBUG
10469                 if (q[-1] != '/')
10470                         abort();
10471 #endif
10472                 q[-1] = '\0';                   /* delete trailing '/' */
10473                 if (stat(p, &statb) < 0) {
10474                         continue;
10475                 }
10476                 /* Very simplistic "hash": just a sum of all mtimes */
10477                 new_hash += (unsigned)statb.st_mtime;
10478         }
10479         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10480                 if (mailtime_hash != 0)
10481                         out2str("you have mail\n");
10482                 mailtime_hash = new_hash;
10483         }
10484         mail_var_path_changed = 0;
10485         popstackmark(&smark);
10486 }
10487
10488 static void FAST_FUNC
10489 changemail(const char *val UNUSED_PARAM)
10490 {
10491         mail_var_path_changed = 1;
10492 }
10493
10494 #endif /* ASH_MAIL */
10495
10496
10497 /* ============ ??? */
10498
10499 /*
10500  * Set the shell parameters.
10501  */
10502 static void
10503 setparam(char **argv)
10504 {
10505         char **newparam;
10506         char **ap;
10507         int nparam;
10508
10509         for (nparam = 0; argv[nparam]; nparam++)
10510                 continue;
10511         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10512         while (*argv) {
10513                 *ap++ = ckstrdup(*argv++);
10514         }
10515         *ap = NULL;
10516         freeparam(&shellparam);
10517         shellparam.malloced = 1;
10518         shellparam.nparam = nparam;
10519         shellparam.p = newparam;
10520 #if ENABLE_ASH_GETOPTS
10521         shellparam.optind = 1;
10522         shellparam.optoff = -1;
10523 #endif
10524 }
10525
10526 /*
10527  * Process shell options.  The global variable argptr contains a pointer
10528  * to the argument list; we advance it past the options.
10529  *
10530  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10531  * For a non-interactive shell, an error condition encountered
10532  * by a special built-in ... shall cause the shell to write a diagnostic message
10533  * to standard error and exit as shown in the following table:
10534  * Error                                           Special Built-In
10535  * ...
10536  * Utility syntax error (option or operand error)  Shall exit
10537  * ...
10538  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10539  * we see that bash does not do that (set "finishes" with error code 1 instead,
10540  * and shell continues), and people rely on this behavior!
10541  * Testcase:
10542  * set -o barfoo 2>/dev/null
10543  * echo $?
10544  *
10545  * Oh well. Let's mimic that.
10546  */
10547 static int
10548 plus_minus_o(char *name, int val)
10549 {
10550         int i;
10551
10552         if (name) {
10553                 for (i = 0; i < NOPTS; i++) {
10554                         if (strcmp(name, optnames(i)) == 0) {
10555                                 optlist[i] = val;
10556                                 return 0;
10557                         }
10558                 }
10559                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10560                 return 1;
10561         }
10562         for (i = 0; i < NOPTS; i++) {
10563                 if (val) {
10564                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10565                 } else {
10566                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10567                 }
10568         }
10569         return 0;
10570 }
10571 static void
10572 setoption(int flag, int val)
10573 {
10574         int i;
10575
10576         for (i = 0; i < NOPTS; i++) {
10577                 if (optletters(i) == flag) {
10578                         optlist[i] = val;
10579                         return;
10580                 }
10581         }
10582         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10583         /* NOTREACHED */
10584 }
10585 static int
10586 options(int cmdline)
10587 {
10588         char *p;
10589         int val;
10590         int c;
10591
10592         if (cmdline)
10593                 minusc = NULL;
10594         while ((p = *argptr) != NULL) {
10595                 c = *p++;
10596                 if (c != '-' && c != '+')
10597                         break;
10598                 argptr++;
10599                 val = 0; /* val = 0 if c == '+' */
10600                 if (c == '-') {
10601                         val = 1;
10602                         if (p[0] == '\0' || LONE_DASH(p)) {
10603                                 if (!cmdline) {
10604                                         /* "-" means turn off -x and -v */
10605                                         if (p[0] == '\0')
10606                                                 xflag = vflag = 0;
10607                                         /* "--" means reset params */
10608                                         else if (*argptr == NULL)
10609                                                 setparam(argptr);
10610                                 }
10611                                 break;    /* "-" or "--" terminates options */
10612                         }
10613                 }
10614                 /* first char was + or - */
10615                 while ((c = *p++) != '\0') {
10616                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10617                         if (c == 'c' && cmdline) {
10618                                 minusc = p;     /* command is after shell args */
10619                         } else if (c == 'o') {
10620                                 if (plus_minus_o(*argptr, val)) {
10621                                         /* it already printed err message */
10622                                         return 1; /* error */
10623                                 }
10624                                 if (*argptr)
10625                                         argptr++;
10626                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10627                                 isloginsh = 1;
10628                         /* bash does not accept +-login, we also won't */
10629                         } else if (cmdline && val && (c == '-')) { /* long options */
10630                                 if (strcmp(p, "login") == 0)
10631                                         isloginsh = 1;
10632                                 break;
10633                         } else {
10634                                 setoption(c, val);
10635                         }
10636                 }
10637         }
10638         return 0;
10639 }
10640
10641 /*
10642  * The shift builtin command.
10643  */
10644 static int FAST_FUNC
10645 shiftcmd(int argc UNUSED_PARAM, char **argv)
10646 {
10647         int n;
10648         char **ap1, **ap2;
10649
10650         n = 1;
10651         if (argv[1])
10652                 n = number(argv[1]);
10653         if (n > shellparam.nparam)
10654                 n = 0; /* bash compat, was = shellparam.nparam; */
10655         INT_OFF;
10656         shellparam.nparam -= n;
10657         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10658                 if (shellparam.malloced)
10659                         free(*ap1);
10660         }
10661         ap2 = shellparam.p;
10662         while ((*ap2++ = *ap1++) != NULL)
10663                 continue;
10664 #if ENABLE_ASH_GETOPTS
10665         shellparam.optind = 1;
10666         shellparam.optoff = -1;
10667 #endif
10668         INT_ON;
10669         return 0;
10670 }
10671
10672 /*
10673  * POSIX requires that 'set' (but not export or readonly) output the
10674  * variables in lexicographic order - by the locale's collating order (sigh).
10675  * Maybe we could keep them in an ordered balanced binary tree
10676  * instead of hashed lists.
10677  * For now just roll 'em through qsort for printing...
10678  */
10679 static int
10680 showvars(const char *sep_prefix, int on, int off)
10681 {
10682         const char *sep;
10683         char **ep, **epend;
10684
10685         ep = listvars(on, off, &epend);
10686         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10687
10688         sep = *sep_prefix ? " " : sep_prefix;
10689
10690         for (; ep < epend; ep++) {
10691                 const char *p;
10692                 const char *q;
10693
10694                 p = strchrnul(*ep, '=');
10695                 q = nullstr;
10696                 if (*p)
10697                         q = single_quote(++p);
10698                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10699         }
10700         return 0;
10701 }
10702
10703 /*
10704  * The set command builtin.
10705  */
10706 static int FAST_FUNC
10707 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10708 {
10709         int retval;
10710
10711         if (!argv[1])
10712                 return showvars(nullstr, 0, VUNSET);
10713
10714         INT_OFF;
10715         retval = options(/*cmdline:*/ 0);
10716         if (retval == 0) { /* if no parse error... */
10717                 optschanged();
10718                 if (*argptr != NULL) {
10719                         setparam(argptr);
10720                 }
10721         }
10722         INT_ON;
10723         return retval;
10724 }
10725
10726 #if ENABLE_ASH_RANDOM_SUPPORT
10727 static void FAST_FUNC
10728 change_random(const char *value)
10729 {
10730         uint32_t t;
10731
10732         if (value == NULL) {
10733                 /* "get", generate */
10734                 t = next_random(&random_gen);
10735                 /* set without recursion */
10736                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10737                 vrandom.flags &= ~VNOFUNC;
10738         } else {
10739                 /* set/reset */
10740                 t = strtoul(value, NULL, 10);
10741                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10742         }
10743 }
10744 #endif
10745
10746 #if ENABLE_ASH_GETOPTS
10747 static int
10748 getopts(char *optstr, char *optvar, char **optfirst)
10749 {
10750         char *p, *q;
10751         char c = '?';
10752         int done = 0;
10753         char sbuf[2];
10754         char **optnext;
10755         int ind = shellparam.optind;
10756         int off = shellparam.optoff;
10757
10758         sbuf[1] = '\0';
10759
10760         shellparam.optind = -1;
10761         optnext = optfirst + ind - 1;
10762
10763         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10764                 p = NULL;
10765         else
10766                 p = optnext[-1] + off;
10767         if (p == NULL || *p == '\0') {
10768                 /* Current word is done, advance */
10769                 p = *optnext;
10770                 if (p == NULL || *p != '-' || *++p == '\0') {
10771  atend:
10772                         p = NULL;
10773                         done = 1;
10774                         goto out;
10775                 }
10776                 optnext++;
10777                 if (LONE_DASH(p))        /* check for "--" */
10778                         goto atend;
10779         }
10780
10781         c = *p++;
10782         for (q = optstr; *q != c;) {
10783                 if (*q == '\0') {
10784                         if (optstr[0] == ':') {
10785                                 sbuf[0] = c;
10786                                 /*sbuf[1] = '\0'; - already is */
10787                                 setvar0("OPTARG", sbuf);
10788                         } else {
10789                                 fprintf(stderr, "Illegal option -%c\n", c);
10790                                 unsetvar("OPTARG");
10791                         }
10792                         c = '?';
10793                         goto out;
10794                 }
10795                 if (*++q == ':')
10796                         q++;
10797         }
10798
10799         if (*++q == ':') {
10800                 if (*p == '\0' && (p = *optnext) == NULL) {
10801                         if (optstr[0] == ':') {
10802                                 sbuf[0] = c;
10803                                 /*sbuf[1] = '\0'; - already is */
10804                                 setvar0("OPTARG", sbuf);
10805                                 c = ':';
10806                         } else {
10807                                 fprintf(stderr, "No arg for -%c option\n", c);
10808                                 unsetvar("OPTARG");
10809                                 c = '?';
10810                         }
10811                         goto out;
10812                 }
10813
10814                 if (p == *optnext)
10815                         optnext++;
10816                 setvar0("OPTARG", p);
10817                 p = NULL;
10818         } else
10819                 setvar0("OPTARG", nullstr);
10820  out:
10821         ind = optnext - optfirst + 1;
10822         setvar("OPTIND", itoa(ind), VNOFUNC);
10823         sbuf[0] = c;
10824         /*sbuf[1] = '\0'; - already is */
10825         setvar0(optvar, sbuf);
10826
10827         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10828         shellparam.optind = ind;
10829
10830         return done;
10831 }
10832
10833 /*
10834  * The getopts builtin.  Shellparam.optnext points to the next argument
10835  * to be processed.  Shellparam.optptr points to the next character to
10836  * be processed in the current argument.  If shellparam.optnext is NULL,
10837  * then it's the first time getopts has been called.
10838  */
10839 static int FAST_FUNC
10840 getoptscmd(int argc, char **argv)
10841 {
10842         char **optbase;
10843
10844         if (argc < 3)
10845                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10846         if (argc == 3) {
10847                 optbase = shellparam.p;
10848                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10849                         shellparam.optind = 1;
10850                         shellparam.optoff = -1;
10851                 }
10852         } else {
10853                 optbase = &argv[3];
10854                 if ((unsigned)shellparam.optind > argc - 2) {
10855                         shellparam.optind = 1;
10856                         shellparam.optoff = -1;
10857                 }
10858         }
10859
10860         return getopts(argv[1], argv[2], optbase);
10861 }
10862 #endif /* ASH_GETOPTS */
10863
10864
10865 /* ============ Shell parser */
10866
10867 struct heredoc {
10868         struct heredoc *next;   /* next here document in list */
10869         union node *here;       /* redirection node */
10870         char *eofmark;          /* string indicating end of input */
10871         smallint striptabs;     /* if set, strip leading tabs */
10872 };
10873
10874 static smallint tokpushback;           /* last token pushed back */
10875 static smallint quoteflag;             /* set if (part of) last token was quoted */
10876 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10877 static struct heredoc *heredoclist;    /* list of here documents to read */
10878 static char *wordtext;                 /* text of last word returned by readtoken */
10879 static struct nodelist *backquotelist;
10880 static union node *redirnode;
10881 static struct heredoc *heredoc;
10882
10883 static const char *
10884 tokname(char *buf, int tok)
10885 {
10886         if (tok < TSEMI)
10887                 return tokname_array[tok];
10888         sprintf(buf, "\"%s\"", tokname_array[tok]);
10889         return buf;
10890 }
10891
10892 /* raise_error_unexpected_syntax:
10893  * Called when an unexpected token is read during the parse.  The argument
10894  * is the token that is expected, or -1 if more than one type of token can
10895  * occur at this point.
10896  */
10897 static void raise_error_unexpected_syntax(int) NORETURN;
10898 static void
10899 raise_error_unexpected_syntax(int token)
10900 {
10901         char msg[64];
10902         char buf[16];
10903         int l;
10904
10905         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10906         if (token >= 0)
10907                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10908         raise_error_syntax(msg);
10909         /* NOTREACHED */
10910 }
10911
10912 #define EOFMARKLEN 79
10913
10914 /* parsing is heavily cross-recursive, need these forward decls */
10915 static union node *andor(void);
10916 static union node *pipeline(void);
10917 static union node *parse_command(void);
10918 static void parseheredoc(void);
10919 static int peektoken(void);
10920 static int readtoken(void);
10921
10922 static union node *
10923 list(int nlflag)
10924 {
10925         union node *n1, *n2, *n3;
10926         int tok;
10927
10928         n1 = NULL;
10929         for (;;) {
10930                 switch (peektoken()) {
10931                 case TNL:
10932                         if (!(nlflag & 1))
10933                                 break;
10934                         parseheredoc();
10935                         return n1;
10936
10937                 case TEOF:
10938                         if (!n1 && (nlflag & 1))
10939                                 n1 = NODE_EOF;
10940                         parseheredoc();
10941                         return n1;
10942                 }
10943
10944                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10945                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10946                         return n1;
10947                 nlflag |= 2;
10948
10949                 n2 = andor();
10950                 tok = readtoken();
10951                 if (tok == TBACKGND) {
10952                         if (n2->type == NPIPE) {
10953                                 n2->npipe.pipe_backgnd = 1;
10954                         } else {
10955                                 if (n2->type != NREDIR) {
10956                                         n3 = stzalloc(sizeof(struct nredir));
10957                                         n3->nredir.n = n2;
10958                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10959                                         n2 = n3;
10960                                 }
10961                                 n2->type = NBACKGND;
10962                         }
10963                 }
10964                 if (n1 == NULL) {
10965                         n1 = n2;
10966                 } else {
10967                         n3 = stzalloc(sizeof(struct nbinary));
10968                         n3->type = NSEMI;
10969                         n3->nbinary.ch1 = n1;
10970                         n3->nbinary.ch2 = n2;
10971                         n1 = n3;
10972                 }
10973                 switch (tok) {
10974                 case TNL:
10975                 case TEOF:
10976                         tokpushback = 1;
10977                         /* fall through */
10978                 case TBACKGND:
10979                 case TSEMI:
10980                         break;
10981                 default:
10982                         if ((nlflag & 1))
10983                                 raise_error_unexpected_syntax(-1);
10984                         tokpushback = 1;
10985                         return n1;
10986                 }
10987         }
10988 }
10989
10990 static union node *
10991 andor(void)
10992 {
10993         union node *n1, *n2, *n3;
10994         int t;
10995
10996         n1 = pipeline();
10997         for (;;) {
10998                 t = readtoken();
10999                 if (t == TAND) {
11000                         t = NAND;
11001                 } else if (t == TOR) {
11002                         t = NOR;
11003                 } else {
11004                         tokpushback = 1;
11005                         return n1;
11006                 }
11007                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11008                 n2 = pipeline();
11009                 n3 = stzalloc(sizeof(struct nbinary));
11010                 n3->type = t;
11011                 n3->nbinary.ch1 = n1;
11012                 n3->nbinary.ch2 = n2;
11013                 n1 = n3;
11014         }
11015 }
11016
11017 static union node *
11018 pipeline(void)
11019 {
11020         union node *n1, *n2, *pipenode;
11021         struct nodelist *lp, *prev;
11022         int negate;
11023
11024         negate = 0;
11025         TRACE(("pipeline: entered\n"));
11026         if (readtoken() == TNOT) {
11027                 negate = !negate;
11028                 checkkwd = CHKKWD | CHKALIAS;
11029         } else
11030                 tokpushback = 1;
11031         n1 = parse_command();
11032         if (readtoken() == TPIPE) {
11033                 pipenode = stzalloc(sizeof(struct npipe));
11034                 pipenode->type = NPIPE;
11035                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11036                 lp = stzalloc(sizeof(struct nodelist));
11037                 pipenode->npipe.cmdlist = lp;
11038                 lp->n = n1;
11039                 do {
11040                         prev = lp;
11041                         lp = stzalloc(sizeof(struct nodelist));
11042                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11043                         lp->n = parse_command();
11044                         prev->next = lp;
11045                 } while (readtoken() == TPIPE);
11046                 lp->next = NULL;
11047                 n1 = pipenode;
11048         }
11049         tokpushback = 1;
11050         if (negate) {
11051                 n2 = stzalloc(sizeof(struct nnot));
11052                 n2->type = NNOT;
11053                 n2->nnot.com = n1;
11054                 return n2;
11055         }
11056         return n1;
11057 }
11058
11059 static union node *
11060 makename(void)
11061 {
11062         union node *n;
11063
11064         n = stzalloc(sizeof(struct narg));
11065         n->type = NARG;
11066         /*n->narg.next = NULL; - stzalloc did it */
11067         n->narg.text = wordtext;
11068         n->narg.backquote = backquotelist;
11069         return n;
11070 }
11071
11072 static void
11073 fixredir(union node *n, const char *text, int err)
11074 {
11075         int fd;
11076
11077         TRACE(("Fix redir %s %d\n", text, err));
11078         if (!err)
11079                 n->ndup.vname = NULL;
11080
11081         fd = bb_strtou(text, NULL, 10);
11082         if (!errno && fd >= 0)
11083                 n->ndup.dupfd = fd;
11084         else if (LONE_DASH(text))
11085                 n->ndup.dupfd = -1;
11086         else {
11087                 if (err)
11088                         raise_error_syntax("bad fd number");
11089                 n->ndup.vname = makename();
11090         }
11091 }
11092
11093 /*
11094  * Returns true if the text contains nothing to expand (no dollar signs
11095  * or backquotes).
11096  */
11097 static int
11098 noexpand(const char *text)
11099 {
11100         unsigned char c;
11101
11102         while ((c = *text++) != '\0') {
11103                 if (c == CTLQUOTEMARK)
11104                         continue;
11105                 if (c == CTLESC)
11106                         text++;
11107                 else if (SIT(c, BASESYNTAX) == CCTL)
11108                         return 0;
11109         }
11110         return 1;
11111 }
11112
11113 static void
11114 parsefname(void)
11115 {
11116         union node *n = redirnode;
11117
11118         if (readtoken() != TWORD)
11119                 raise_error_unexpected_syntax(-1);
11120         if (n->type == NHERE) {
11121                 struct heredoc *here = heredoc;
11122                 struct heredoc *p;
11123                 int i;
11124
11125                 if (quoteflag == 0)
11126                         n->type = NXHERE;
11127                 TRACE(("Here document %d\n", n->type));
11128                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11129                         raise_error_syntax("illegal eof marker for << redirection");
11130                 rmescapes(wordtext, 0);
11131                 here->eofmark = wordtext;
11132                 here->next = NULL;
11133                 if (heredoclist == NULL)
11134                         heredoclist = here;
11135                 else {
11136                         for (p = heredoclist; p->next; p = p->next)
11137                                 continue;
11138                         p->next = here;
11139                 }
11140         } else if (n->type == NTOFD || n->type == NFROMFD) {
11141                 fixredir(n, wordtext, 0);
11142         } else {
11143                 n->nfile.fname = makename();
11144         }
11145 }
11146
11147 static union node *
11148 simplecmd(void)
11149 {
11150         union node *args, **app;
11151         union node *n = NULL;
11152         union node *vars, **vpp;
11153         union node **rpp, *redir;
11154         int savecheckkwd;
11155 #if BASH_TEST2
11156         smallint double_brackets_flag = 0;
11157 #endif
11158         IF_BASH_FUNCTION(smallint function_flag = 0;)
11159
11160         args = NULL;
11161         app = &args;
11162         vars = NULL;
11163         vpp = &vars;
11164         redir = NULL;
11165         rpp = &redir;
11166
11167         savecheckkwd = CHKALIAS;
11168         for (;;) {
11169                 int t;
11170                 checkkwd = savecheckkwd;
11171                 t = readtoken();
11172                 switch (t) {
11173 #if BASH_FUNCTION
11174                 case TFUNCTION:
11175                         if (peektoken() != TWORD)
11176                                 raise_error_unexpected_syntax(TWORD);
11177                         function_flag = 1;
11178                         break;
11179 #endif
11180 #if BASH_TEST2
11181                 case TAND: /* "&&" */
11182                 case TOR: /* "||" */
11183                         if (!double_brackets_flag) {
11184                                 tokpushback = 1;
11185                                 goto out;
11186                         }
11187                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11188 #endif
11189                 case TWORD:
11190                         n = stzalloc(sizeof(struct narg));
11191                         n->type = NARG;
11192                         /*n->narg.next = NULL; - stzalloc did it */
11193                         n->narg.text = wordtext;
11194 #if BASH_TEST2
11195                         if (strcmp("[[", wordtext) == 0)
11196                                 double_brackets_flag = 1;
11197                         else if (strcmp("]]", wordtext) == 0)
11198                                 double_brackets_flag = 0;
11199 #endif
11200                         n->narg.backquote = backquotelist;
11201                         if (savecheckkwd && isassignment(wordtext)) {
11202                                 *vpp = n;
11203                                 vpp = &n->narg.next;
11204                         } else {
11205                                 *app = n;
11206                                 app = &n->narg.next;
11207                                 savecheckkwd = 0;
11208                         }
11209 #if BASH_FUNCTION
11210                         if (function_flag) {
11211                                 checkkwd = CHKNL | CHKKWD;
11212                                 switch (peektoken()) {
11213                                 case TBEGIN:
11214                                 case TIF:
11215                                 case TCASE:
11216                                 case TUNTIL:
11217                                 case TWHILE:
11218                                 case TFOR:
11219                                         goto do_func;
11220                                 case TLP:
11221                                         function_flag = 0;
11222                                         break;
11223                                 case TWORD:
11224                                         if (strcmp("[[", wordtext) == 0)
11225                                                 goto do_func;
11226                                         /* fall through */
11227                                 default:
11228                                         raise_error_unexpected_syntax(-1);
11229                                 }
11230                         }
11231 #endif
11232                         break;
11233                 case TREDIR:
11234                         *rpp = n = redirnode;
11235                         rpp = &n->nfile.next;
11236                         parsefname();   /* read name of redirection file */
11237                         break;
11238                 case TLP:
11239  IF_BASH_FUNCTION(do_func:)
11240                         if (args && app == &args->narg.next
11241                          && !vars && !redir
11242                         ) {
11243                                 struct builtincmd *bcmd;
11244                                 const char *name;
11245
11246                                 /* We have a function */
11247                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11248                                         raise_error_unexpected_syntax(TRP);
11249                                 name = n->narg.text;
11250                                 if (!goodname(name)
11251                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11252                                 ) {
11253                                         raise_error_syntax("bad function name");
11254                                 }
11255                                 n->type = NDEFUN;
11256                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11257                                 n->narg.next = parse_command();
11258                                 return n;
11259                         }
11260                         IF_BASH_FUNCTION(function_flag = 0;)
11261                         /* fall through */
11262                 default:
11263                         tokpushback = 1;
11264                         goto out;
11265                 }
11266         }
11267  out:
11268         *app = NULL;
11269         *vpp = NULL;
11270         *rpp = NULL;
11271         n = stzalloc(sizeof(struct ncmd));
11272         n->type = NCMD;
11273         n->ncmd.args = args;
11274         n->ncmd.assign = vars;
11275         n->ncmd.redirect = redir;
11276         return n;
11277 }
11278
11279 static union node *
11280 parse_command(void)
11281 {
11282         union node *n1, *n2;
11283         union node *ap, **app;
11284         union node *cp, **cpp;
11285         union node *redir, **rpp;
11286         union node **rpp2;
11287         int t;
11288
11289         redir = NULL;
11290         rpp2 = &redir;
11291
11292         switch (readtoken()) {
11293         default:
11294                 raise_error_unexpected_syntax(-1);
11295                 /* NOTREACHED */
11296         case TIF:
11297                 n1 = stzalloc(sizeof(struct nif));
11298                 n1->type = NIF;
11299                 n1->nif.test = list(0);
11300                 if (readtoken() != TTHEN)
11301                         raise_error_unexpected_syntax(TTHEN);
11302                 n1->nif.ifpart = list(0);
11303                 n2 = n1;
11304                 while (readtoken() == TELIF) {
11305                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11306                         n2 = n2->nif.elsepart;
11307                         n2->type = NIF;
11308                         n2->nif.test = list(0);
11309                         if (readtoken() != TTHEN)
11310                                 raise_error_unexpected_syntax(TTHEN);
11311                         n2->nif.ifpart = list(0);
11312                 }
11313                 if (lasttoken == TELSE)
11314                         n2->nif.elsepart = list(0);
11315                 else {
11316                         n2->nif.elsepart = NULL;
11317                         tokpushback = 1;
11318                 }
11319                 t = TFI;
11320                 break;
11321         case TWHILE:
11322         case TUNTIL: {
11323                 int got;
11324                 n1 = stzalloc(sizeof(struct nbinary));
11325                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11326                 n1->nbinary.ch1 = list(0);
11327                 got = readtoken();
11328                 if (got != TDO) {
11329                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11330                                         got == TWORD ? wordtext : ""));
11331                         raise_error_unexpected_syntax(TDO);
11332                 }
11333                 n1->nbinary.ch2 = list(0);
11334                 t = TDONE;
11335                 break;
11336         }
11337         case TFOR:
11338                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11339                         raise_error_syntax("bad for loop variable");
11340                 n1 = stzalloc(sizeof(struct nfor));
11341                 n1->type = NFOR;
11342                 n1->nfor.var = wordtext;
11343                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11344                 if (readtoken() == TIN) {
11345                         app = &ap;
11346                         while (readtoken() == TWORD) {
11347                                 n2 = stzalloc(sizeof(struct narg));
11348                                 n2->type = NARG;
11349                                 /*n2->narg.next = NULL; - stzalloc did it */
11350                                 n2->narg.text = wordtext;
11351                                 n2->narg.backquote = backquotelist;
11352                                 *app = n2;
11353                                 app = &n2->narg.next;
11354                         }
11355                         *app = NULL;
11356                         n1->nfor.args = ap;
11357                         if (lasttoken != TNL && lasttoken != TSEMI)
11358                                 raise_error_unexpected_syntax(-1);
11359                 } else {
11360                         n2 = stzalloc(sizeof(struct narg));
11361                         n2->type = NARG;
11362                         /*n2->narg.next = NULL; - stzalloc did it */
11363                         n2->narg.text = (char *)dolatstr;
11364                         /*n2->narg.backquote = NULL;*/
11365                         n1->nfor.args = n2;
11366                         /*
11367                          * Newline or semicolon here is optional (but note
11368                          * that the original Bourne shell only allowed NL).
11369                          */
11370                         if (lasttoken != TSEMI)
11371                                 tokpushback = 1;
11372                 }
11373                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11374                 if (readtoken() != TDO)
11375                         raise_error_unexpected_syntax(TDO);
11376                 n1->nfor.body = list(0);
11377                 t = TDONE;
11378                 break;
11379         case TCASE:
11380                 n1 = stzalloc(sizeof(struct ncase));
11381                 n1->type = NCASE;
11382                 if (readtoken() != TWORD)
11383                         raise_error_unexpected_syntax(TWORD);
11384                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11385                 n2->type = NARG;
11386                 /*n2->narg.next = NULL; - stzalloc did it */
11387                 n2->narg.text = wordtext;
11388                 n2->narg.backquote = backquotelist;
11389                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11390                 if (readtoken() != TIN)
11391                         raise_error_unexpected_syntax(TIN);
11392                 cpp = &n1->ncase.cases;
11393  next_case:
11394                 checkkwd = CHKNL | CHKKWD;
11395                 t = readtoken();
11396                 while (t != TESAC) {
11397                         if (lasttoken == TLP)
11398                                 readtoken();
11399                         *cpp = cp = stzalloc(sizeof(struct nclist));
11400                         cp->type = NCLIST;
11401                         app = &cp->nclist.pattern;
11402                         for (;;) {
11403                                 *app = ap = stzalloc(sizeof(struct narg));
11404                                 ap->type = NARG;
11405                                 /*ap->narg.next = NULL; - stzalloc did it */
11406                                 ap->narg.text = wordtext;
11407                                 ap->narg.backquote = backquotelist;
11408                                 if (readtoken() != TPIPE)
11409                                         break;
11410                                 app = &ap->narg.next;
11411                                 readtoken();
11412                         }
11413                         //ap->narg.next = NULL;
11414                         if (lasttoken != TRP)
11415                                 raise_error_unexpected_syntax(TRP);
11416                         cp->nclist.body = list(2);
11417
11418                         cpp = &cp->nclist.next;
11419
11420                         checkkwd = CHKNL | CHKKWD;
11421                         t = readtoken();
11422                         if (t != TESAC) {
11423                                 if (t != TENDCASE)
11424                                         raise_error_unexpected_syntax(TENDCASE);
11425                                 goto next_case;
11426                         }
11427                 }
11428                 *cpp = NULL;
11429                 goto redir;
11430         case TLP:
11431                 n1 = stzalloc(sizeof(struct nredir));
11432                 n1->type = NSUBSHELL;
11433                 n1->nredir.n = list(0);
11434                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11435                 t = TRP;
11436                 break;
11437         case TBEGIN:
11438                 n1 = list(0);
11439                 t = TEND;
11440                 break;
11441         IF_BASH_FUNCTION(case TFUNCTION:)
11442         case TWORD:
11443         case TREDIR:
11444                 tokpushback = 1;
11445                 return simplecmd();
11446         }
11447
11448         if (readtoken() != t)
11449                 raise_error_unexpected_syntax(t);
11450
11451  redir:
11452         /* Now check for redirection which may follow command */
11453         checkkwd = CHKKWD | CHKALIAS;
11454         rpp = rpp2;
11455         while (readtoken() == TREDIR) {
11456                 *rpp = n2 = redirnode;
11457                 rpp = &n2->nfile.next;
11458                 parsefname();
11459         }
11460         tokpushback = 1;
11461         *rpp = NULL;
11462         if (redir) {
11463                 if (n1->type != NSUBSHELL) {
11464                         n2 = stzalloc(sizeof(struct nredir));
11465                         n2->type = NREDIR;
11466                         n2->nredir.n = n1;
11467                         n1 = n2;
11468                 }
11469                 n1->nredir.redirect = redir;
11470         }
11471         return n1;
11472 }
11473
11474 #if BASH_DOLLAR_SQUOTE
11475 static int
11476 decode_dollar_squote(void)
11477 {
11478         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11479         int c, cnt;
11480         char *p;
11481         char buf[4];
11482
11483         c = pgetc();
11484         p = strchr(C_escapes, c);
11485         if (p) {
11486                 buf[0] = c;
11487                 p = buf;
11488                 cnt = 3;
11489                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11490                         do {
11491                                 c = pgetc();
11492                                 *++p = c;
11493                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11494                         pungetc();
11495                 } else if (c == 'x') { /* \xHH */
11496                         do {
11497                                 c = pgetc();
11498                                 *++p = c;
11499                         } while (isxdigit(c) && --cnt);
11500                         pungetc();
11501                         if (cnt == 3) { /* \x but next char is "bad" */
11502                                 c = 'x';
11503                                 goto unrecognized;
11504                         }
11505                 } else { /* simple seq like \\ or \t */
11506                         p++;
11507                 }
11508                 *p = '\0';
11509                 p = buf;
11510                 c = bb_process_escape_sequence((void*)&p);
11511         } else { /* unrecognized "\z": print both chars unless ' or " */
11512                 if (c != '\'' && c != '"') {
11513  unrecognized:
11514                         c |= 0x100; /* "please encode \, then me" */
11515                 }
11516         }
11517         return c;
11518 }
11519 #endif
11520
11521 /*
11522  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11523  * is not NULL, read a here document.  In the latter case, eofmark is the
11524  * word which marks the end of the document and striptabs is true if
11525  * leading tabs should be stripped from the document.  The argument c
11526  * is the first character of the input token or document.
11527  *
11528  * Because C does not have internal subroutines, I have simulated them
11529  * using goto's to implement the subroutine linkage.  The following macros
11530  * will run code that appears at the end of readtoken1.
11531  */
11532 #define CHECKEND()      {goto checkend; checkend_return:;}
11533 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11534 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11535 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11536 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11537 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11538 static int
11539 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11540 {
11541         /* NB: syntax parameter fits into smallint */
11542         /* c parameter is an unsigned char or PEOF or PEOA */
11543         char *out;
11544         size_t len;
11545         char line[EOFMARKLEN + 1];
11546         struct nodelist *bqlist;
11547         smallint quotef;
11548         smallint dblquote;
11549         smallint oldstyle;
11550         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11551 #if ENABLE_ASH_EXPAND_PRMT
11552         smallint pssyntax;   /* we are expanding a prompt string */
11553 #endif
11554         int varnest;         /* levels of variables expansion */
11555         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11556         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11557         int dqvarnest;       /* levels of variables expansion within double quotes */
11558
11559         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11560
11561         startlinno = g_parsefile->linno;
11562         bqlist = NULL;
11563         quotef = 0;
11564         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11565 #if ENABLE_ASH_EXPAND_PRMT
11566         pssyntax = (syntax == PSSYNTAX);
11567         if (pssyntax)
11568                 syntax = DQSYNTAX;
11569 #endif
11570         dblquote = (syntax == DQSYNTAX);
11571         varnest = 0;
11572         IF_FEATURE_SH_MATH(arinest = 0;)
11573         IF_FEATURE_SH_MATH(parenlevel = 0;)
11574         dqvarnest = 0;
11575
11576         STARTSTACKSTR(out);
11577  loop:
11578         /* For each line, until end of word */
11579         CHECKEND();     /* set c to PEOF if at end of here document */
11580         for (;;) {      /* until end of line or end of word */
11581                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11582                 switch (SIT(c, syntax)) {
11583                 case CNL:       /* '\n' */
11584                         if (syntax == BASESYNTAX)
11585                                 goto endword;   /* exit outer loop */
11586                         USTPUTC(c, out);
11587                         nlprompt();
11588                         c = pgetc();
11589                         goto loop;              /* continue outer loop */
11590                 case CWORD:
11591                         USTPUTC(c, out);
11592                         break;
11593                 case CCTL:
11594 #if BASH_DOLLAR_SQUOTE
11595                         if (c == '\\' && bash_dollar_squote) {
11596                                 c = decode_dollar_squote();
11597                                 if (c == '\0') {
11598                                         /* skip $'\000', $'\x00' (like bash) */
11599                                         break;
11600                                 }
11601                                 if (c & 0x100) {
11602                                         /* Unknown escape. Encode as '\z' */
11603                                         c = (unsigned char)c;
11604                                         if (eofmark == NULL || dblquote)
11605                                                 USTPUTC(CTLESC, out);
11606                                         USTPUTC('\\', out);
11607                                 }
11608                         }
11609 #endif
11610                         if (eofmark == NULL || dblquote)
11611                                 USTPUTC(CTLESC, out);
11612                         USTPUTC(c, out);
11613                         break;
11614                 case CBACK:     /* backslash */
11615                         c = pgetc_without_PEOA();
11616                         if (c == PEOF) {
11617                                 USTPUTC(CTLESC, out);
11618                                 USTPUTC('\\', out);
11619                                 pungetc();
11620                         } else if (c == '\n') {
11621                                 nlprompt();
11622                         } else {
11623 #if ENABLE_ASH_EXPAND_PRMT
11624                                 if (c == '$' && pssyntax) {
11625                                         USTPUTC(CTLESC, out);
11626                                         USTPUTC('\\', out);
11627                                 }
11628 #endif
11629                                 /* Backslash is retained if we are in "str" and next char isn't special */
11630                                 if (dblquote
11631                                  && c != '\\'
11632                                  && c != '`'
11633                                  && c != '$'
11634                                  && (c != '"' || eofmark != NULL)
11635                                 ) {
11636                                         USTPUTC('\\', out);
11637                                 }
11638                                 USTPUTC(CTLESC, out);
11639                                 USTPUTC(c, out);
11640                                 quotef = 1;
11641                         }
11642                         break;
11643                 case CSQUOTE:
11644                         syntax = SQSYNTAX;
11645  quotemark:
11646                         if (eofmark == NULL) {
11647                                 USTPUTC(CTLQUOTEMARK, out);
11648                         }
11649                         break;
11650                 case CDQUOTE:
11651                         syntax = DQSYNTAX;
11652                         dblquote = 1;
11653                         goto quotemark;
11654                 case CENDQUOTE:
11655                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11656                         if (eofmark != NULL && varnest == 0) {
11657                                 USTPUTC(c, out);
11658                         } else {
11659                                 if (dqvarnest == 0) {
11660                                         syntax = BASESYNTAX;
11661                                         dblquote = 0;
11662                                 }
11663                                 quotef = 1;
11664                                 goto quotemark;
11665                         }
11666                         break;
11667                 case CVAR:      /* '$' */
11668                         PARSESUB();             /* parse substitution */
11669                         break;
11670                 case CENDVAR:   /* '}' */
11671                         if (varnest > 0) {
11672                                 varnest--;
11673                                 if (dqvarnest > 0) {
11674                                         dqvarnest--;
11675                                 }
11676                                 c = CTLENDVAR;
11677                         }
11678                         USTPUTC(c, out);
11679                         break;
11680 #if ENABLE_FEATURE_SH_MATH
11681                 case CLP:       /* '(' in arithmetic */
11682                         parenlevel++;
11683                         USTPUTC(c, out);
11684                         break;
11685                 case CRP:       /* ')' in arithmetic */
11686                         if (parenlevel > 0) {
11687                                 parenlevel--;
11688                         } else {
11689                                 if (pgetc_eatbnl() == ')') {
11690                                         c = CTLENDARI;
11691                                         if (--arinest == 0) {
11692                                                 syntax = prevsyntax;
11693                                         }
11694                                 } else {
11695                                         /*
11696                                          * unbalanced parens
11697                                          * (don't 2nd guess - no error)
11698                                          */
11699                                         pungetc();
11700                                 }
11701                         }
11702                         USTPUTC(c, out);
11703                         break;
11704 #endif
11705                 case CBQUOTE:   /* '`' */
11706                         PARSEBACKQOLD();
11707                         break;
11708                 case CENDFILE:
11709                         goto endword;           /* exit outer loop */
11710                 case CIGN:
11711                         break;
11712                 default:
11713                         if (varnest == 0) {
11714 #if BASH_REDIR_OUTPUT
11715                                 if (c == '&') {
11716 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11717                                         if (pgetc() == '>')
11718                                                 c = 0x100 + '>'; /* flag &> */
11719                                         pungetc();
11720                                 }
11721 #endif
11722                                 goto endword;   /* exit outer loop */
11723                         }
11724                         IF_ASH_ALIAS(if (c != PEOA))
11725                                 USTPUTC(c, out);
11726                 }
11727                 c = pgetc();
11728         } /* for (;;) */
11729  endword:
11730
11731 #if ENABLE_FEATURE_SH_MATH
11732         if (syntax == ARISYNTAX)
11733                 raise_error_syntax("missing '))'");
11734 #endif
11735         if (syntax != BASESYNTAX && eofmark == NULL)
11736                 raise_error_syntax("unterminated quoted string");
11737         if (varnest != 0) {
11738                 startlinno = g_parsefile->linno;
11739                 /* { */
11740                 raise_error_syntax("missing '}'");
11741         }
11742         USTPUTC('\0', out);
11743         len = out - (char *)stackblock();
11744         out = stackblock();
11745         if (eofmark == NULL) {
11746                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11747                  && quotef == 0
11748                 ) {
11749                         if (isdigit_str9(out)) {
11750                                 PARSEREDIR(); /* passed as params: out, c */
11751                                 lasttoken = TREDIR;
11752                                 return lasttoken;
11753                         }
11754                         /* else: non-number X seen, interpret it
11755                          * as "NNNX>file" = "NNNX >file" */
11756                 }
11757                 pungetc();
11758         }
11759         quoteflag = quotef;
11760         backquotelist = bqlist;
11761         grabstackblock(len);
11762         wordtext = out;
11763         lasttoken = TWORD;
11764         return lasttoken;
11765 /* end of readtoken routine */
11766
11767 /*
11768  * Check to see whether we are at the end of the here document.  When this
11769  * is called, c is set to the first character of the next input line.  If
11770  * we are at the end of the here document, this routine sets the c to PEOF.
11771  */
11772 checkend: {
11773         if (eofmark) {
11774 #if ENABLE_ASH_ALIAS
11775                 if (c == PEOA)
11776                         c = pgetc_without_PEOA();
11777 #endif
11778                 if (striptabs) {
11779                         while (c == '\t') {
11780                                 c = pgetc_without_PEOA();
11781                         }
11782                 }
11783                 if (c == *eofmark) {
11784                         if (pfgets(line, sizeof(line)) != NULL) {
11785                                 char *p, *q;
11786                                 int cc;
11787
11788                                 p = line;
11789                                 for (q = eofmark + 1;; p++, q++) {
11790                                         cc = *p;
11791                                         if (cc == '\n')
11792                                                 cc = 0;
11793                                         if (!*q || cc != *q)
11794                                                 break;
11795                                 }
11796                                 if (cc == *q) {
11797                                         c = PEOF;
11798                                         nlnoprompt();
11799                                 } else {
11800                                         pushstring(line, NULL);
11801                                 }
11802                         }
11803                 }
11804         }
11805         goto checkend_return;
11806 }
11807
11808 /*
11809  * Parse a redirection operator.  The variable "out" points to a string
11810  * specifying the fd to be redirected.  The variable "c" contains the
11811  * first character of the redirection operator.
11812  */
11813 parseredir: {
11814         /* out is already checked to be a valid number or "" */
11815         int fd = (*out == '\0' ? -1 : atoi(out));
11816         union node *np;
11817
11818         np = stzalloc(sizeof(struct nfile));
11819         if (c == '>') {
11820                 np->nfile.fd = 1;
11821                 c = pgetc();
11822                 if (c == '>')
11823                         np->type = NAPPEND;
11824                 else if (c == '|')
11825                         np->type = NCLOBBER;
11826                 else if (c == '&')
11827                         np->type = NTOFD;
11828                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11829                 else {
11830                         np->type = NTO;
11831                         pungetc();
11832                 }
11833         }
11834 #if BASH_REDIR_OUTPUT
11835         else if (c == 0x100 + '>') { /* this flags &> redirection */
11836                 np->nfile.fd = 1;
11837                 pgetc(); /* this is '>', no need to check */
11838                 np->type = NTO2;
11839         }
11840 #endif
11841         else { /* c == '<' */
11842                 /*np->nfile.fd = 0; - stzalloc did it */
11843                 c = pgetc();
11844                 switch (c) {
11845                 case '<':
11846                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11847                                 np = stzalloc(sizeof(struct nhere));
11848                                 /*np->nfile.fd = 0; - stzalloc did it */
11849                         }
11850                         np->type = NHERE;
11851                         heredoc = stzalloc(sizeof(struct heredoc));
11852                         heredoc->here = np;
11853                         c = pgetc();
11854                         if (c == '-') {
11855                                 heredoc->striptabs = 1;
11856                         } else {
11857                                 /*heredoc->striptabs = 0; - stzalloc did it */
11858                                 pungetc();
11859                         }
11860                         break;
11861
11862                 case '&':
11863                         np->type = NFROMFD;
11864                         break;
11865
11866                 case '>':
11867                         np->type = NFROMTO;
11868                         break;
11869
11870                 default:
11871                         np->type = NFROM;
11872                         pungetc();
11873                         break;
11874                 }
11875         }
11876         if (fd >= 0)
11877                 np->nfile.fd = fd;
11878         redirnode = np;
11879         goto parseredir_return;
11880 }
11881
11882 /*
11883  * Parse a substitution.  At this point, we have read the dollar sign
11884  * and nothing else.
11885  */
11886
11887 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11888  * (assuming ascii char codes, as the original implementation did) */
11889 #define is_special(c) \
11890         (((unsigned)(c) - 33 < 32) \
11891                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11892 parsesub: {
11893         unsigned char subtype;
11894         int typeloc;
11895
11896         c = pgetc_eatbnl();
11897         if (c > 255 /* PEOA or PEOF */
11898          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11899         ) {
11900 #if BASH_DOLLAR_SQUOTE
11901                 if (syntax != DQSYNTAX && c == '\'')
11902                         bash_dollar_squote = 1;
11903                 else
11904 #endif
11905                         USTPUTC('$', out);
11906                 pungetc();
11907         } else if (c == '(') {
11908                 /* $(command) or $((arith)) */
11909                 if (pgetc_eatbnl() == '(') {
11910 #if ENABLE_FEATURE_SH_MATH
11911                         PARSEARITH();
11912 #else
11913                         raise_error_syntax("you disabled math support for $((arith)) syntax");
11914 #endif
11915                 } else {
11916                         pungetc();
11917                         PARSEBACKQNEW();
11918                 }
11919         } else {
11920                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11921                 USTPUTC(CTLVAR, out);
11922                 typeloc = out - (char *)stackblock();
11923                 STADJUST(1, out);
11924                 subtype = VSNORMAL;
11925                 if (c == '{') {
11926                         c = pgetc_eatbnl();
11927                         subtype = 0;
11928                 }
11929  varname:
11930                 if (is_name(c)) {
11931                         /* $[{[#]]NAME[}] */
11932                         do {
11933                                 STPUTC(c, out);
11934                                 c = pgetc_eatbnl();
11935                         } while (is_in_name(c));
11936                 } else if (isdigit(c)) {
11937                         /* $[{[#]]NUM[}] */
11938                         do {
11939                                 STPUTC(c, out);
11940                                 c = pgetc_eatbnl();
11941                         } while (isdigit(c));
11942                 } else if (is_special(c)) {
11943                         /* $[{[#]]<specialchar>[}] */
11944                         int cc = c;
11945
11946                         c = pgetc_eatbnl();
11947                         if (!subtype && cc == '#') {
11948                                 subtype = VSLENGTH;
11949                                 if (c == '_' || isalnum(c))
11950                                         goto varname;
11951                                 cc = c;
11952                                 c = pgetc_eatbnl();
11953                                 if (cc == '}' || c != '}') {
11954                                         pungetc();
11955                                         subtype = 0;
11956                                         c = cc;
11957                                         cc = '#';
11958                                 }
11959                         }
11960                         USTPUTC(cc, out);
11961                 } else {
11962                         goto badsub;
11963                 }
11964                 if (c != '}' && subtype == VSLENGTH) {
11965                         /* ${#VAR didn't end with } */
11966                         goto badsub;
11967                 }
11968
11969                 if (subtype == 0) {
11970                         static const char types[] ALIGN1 = "}-+?=";
11971                         /* ${VAR...} but not $VAR or ${#VAR} */
11972                         /* c == first char after VAR */
11973                         switch (c) {
11974                         case ':':
11975                                 c = pgetc_eatbnl();
11976 #if BASH_SUBSTR
11977                                 /* This check is only needed to not misinterpret
11978                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11979                                  * constructs.
11980                                  */
11981                                 if (!strchr(types, c)) {
11982                                         subtype = VSSUBSTR;
11983                                         pungetc();
11984                                         break; /* "goto badsub" is bigger (!) */
11985                                 }
11986 #endif
11987                                 subtype = VSNUL;
11988                                 /*FALLTHROUGH*/
11989                         default: {
11990                                 const char *p = strchr(types, c);
11991                                 if (p == NULL)
11992                                         break;
11993                                 subtype |= p - types + VSNORMAL;
11994                                 break;
11995                         }
11996                         case '%':
11997                         case '#': {
11998                                 int cc = c;
11999                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12000                                 c = pgetc_eatbnl();
12001                                 if (c != cc)
12002                                         goto badsub;
12003                                 subtype++;
12004                                 break;
12005                         }
12006 #if BASH_PATTERN_SUBST
12007                         case '/':
12008                                 /* ${v/[/]pattern/repl} */
12009 //TODO: encode pattern and repl separately.
12010 // Currently ${v/$var_with_slash/repl} is horribly broken
12011                                 subtype = VSREPLACE;
12012                                 c = pgetc_eatbnl();
12013                                 if (c != '/')
12014                                         goto badsub;
12015                                 subtype++; /* VSREPLACEALL */
12016                                 break;
12017 #endif
12018                         }
12019                 } else {
12020  badsub:
12021                         pungetc();
12022                 }
12023                 ((unsigned char *)stackblock())[typeloc] = subtype;
12024                 if (subtype != VSNORMAL) {
12025                         varnest++;
12026                         if (dblquote)
12027                                 dqvarnest++;
12028                 }
12029                 STPUTC('=', out);
12030         }
12031         goto parsesub_return;
12032 }
12033
12034 /*
12035  * Called to parse command substitutions.  Newstyle is set if the command
12036  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12037  * list of commands (passed by reference), and savelen is the number of
12038  * characters on the top of the stack which must be preserved.
12039  */
12040 parsebackq: {
12041         struct nodelist **nlpp;
12042         union node *n;
12043         char *str;
12044         size_t savelen;
12045         smallint saveprompt = 0;
12046
12047         str = NULL;
12048         savelen = out - (char *)stackblock();
12049         if (savelen > 0) {
12050                 /*
12051                  * FIXME: this can allocate very large block on stack and SEGV.
12052                  * Example:
12053                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12054                  * allocates 100kb for every command subst. With about
12055                  * a hundred command substitutions stack overflows.
12056                  * With larger prepended string, SEGV happens sooner.
12057                  */
12058                 str = alloca(savelen);
12059                 memcpy(str, stackblock(), savelen);
12060         }
12061
12062         if (oldstyle) {
12063                 /* We must read until the closing backquote, giving special
12064                  * treatment to some slashes, and then push the string and
12065                  * reread it as input, interpreting it normally.
12066                  */
12067                 char *pout;
12068                 size_t psavelen;
12069                 char *pstr;
12070
12071                 STARTSTACKSTR(pout);
12072                 for (;;) {
12073                         int pc;
12074
12075                         setprompt_if(needprompt, 2);
12076                         pc = pgetc();
12077                         switch (pc) {
12078                         case '`':
12079                                 goto done;
12080
12081                         case '\\':
12082                                 pc = pgetc();
12083                                 if (pc == '\n') {
12084                                         nlprompt();
12085                                         /*
12086                                          * If eating a newline, avoid putting
12087                                          * the newline into the new character
12088                                          * stream (via the STPUTC after the
12089                                          * switch).
12090                                          */
12091                                         continue;
12092                                 }
12093                                 if (pc != '\\' && pc != '`' && pc != '$'
12094                                  && (!dblquote || pc != '"')
12095                                 ) {
12096                                         STPUTC('\\', pout);
12097                                 }
12098                                 if (pc <= 255 /* not PEOA or PEOF */) {
12099                                         break;
12100                                 }
12101                                 /* fall through */
12102
12103                         case PEOF:
12104                         IF_ASH_ALIAS(case PEOA:)
12105                                 startlinno = g_parsefile->linno;
12106                                 raise_error_syntax("EOF in backquote substitution");
12107
12108                         case '\n':
12109                                 nlnoprompt();
12110                                 break;
12111
12112                         default:
12113                                 break;
12114                         }
12115                         STPUTC(pc, pout);
12116                 }
12117  done:
12118                 STPUTC('\0', pout);
12119                 psavelen = pout - (char *)stackblock();
12120                 if (psavelen > 0) {
12121                         pstr = grabstackstr(pout);
12122                         setinputstring(pstr);
12123                 }
12124         }
12125         nlpp = &bqlist;
12126         while (*nlpp)
12127                 nlpp = &(*nlpp)->next;
12128         *nlpp = stzalloc(sizeof(**nlpp));
12129         /* (*nlpp)->next = NULL; - stzalloc did it */
12130
12131         if (oldstyle) {
12132                 saveprompt = doprompt;
12133                 doprompt = 0;
12134         }
12135
12136         n = list(2);
12137
12138         if (oldstyle)
12139                 doprompt = saveprompt;
12140         else if (readtoken() != TRP)
12141                 raise_error_unexpected_syntax(TRP);
12142
12143         (*nlpp)->n = n;
12144         if (oldstyle) {
12145                 /*
12146                  * Start reading from old file again, ignoring any pushed back
12147                  * tokens left from the backquote parsing
12148                  */
12149                 popfile();
12150                 tokpushback = 0;
12151         }
12152         while (stackblocksize() <= savelen)
12153                 growstackblock();
12154         STARTSTACKSTR(out);
12155         if (str) {
12156                 memcpy(out, str, savelen);
12157                 STADJUST(savelen, out);
12158         }
12159         USTPUTC(CTLBACKQ, out);
12160         if (oldstyle)
12161                 goto parsebackq_oldreturn;
12162         goto parsebackq_newreturn;
12163 }
12164
12165 #if ENABLE_FEATURE_SH_MATH
12166 /*
12167  * Parse an arithmetic expansion (indicate start of one and set state)
12168  */
12169 parsearith: {
12170         if (++arinest == 1) {
12171                 prevsyntax = syntax;
12172                 syntax = ARISYNTAX;
12173         }
12174         USTPUTC(CTLARI, out);
12175         goto parsearith_return;
12176 }
12177 #endif
12178 } /* end of readtoken */
12179
12180 /*
12181  * Read the next input token.
12182  * If the token is a word, we set backquotelist to the list of cmds in
12183  *      backquotes.  We set quoteflag to true if any part of the word was
12184  *      quoted.
12185  * If the token is TREDIR, then we set redirnode to a structure containing
12186  *      the redirection.
12187  * In all cases, the variable startlinno is set to the number of the line
12188  *      on which the token starts.
12189  *
12190  * [Change comment:  here documents and internal procedures]
12191  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12192  *  word parsing code into a separate routine.  In this case, readtoken
12193  *  doesn't need to have any internal procedures, but parseword does.
12194  *  We could also make parseoperator in essence the main routine, and
12195  *  have parseword (readtoken1?) handle both words and redirection.]
12196  */
12197 #define NEW_xxreadtoken
12198 #ifdef NEW_xxreadtoken
12199 /* singles must be first! */
12200 static const char xxreadtoken_chars[7] ALIGN1 = {
12201         '\n', '(', ')', /* singles */
12202         '&', '|', ';',  /* doubles */
12203         0
12204 };
12205
12206 #define xxreadtoken_singles 3
12207 #define xxreadtoken_doubles 3
12208
12209 static const char xxreadtoken_tokens[] ALIGN1 = {
12210         TNL, TLP, TRP,          /* only single occurrence allowed */
12211         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12212         TEOF,                   /* corresponds to trailing nul */
12213         TAND, TOR, TENDCASE     /* if double occurrence */
12214 };
12215
12216 static int
12217 xxreadtoken(void)
12218 {
12219         int c;
12220
12221         if (tokpushback) {
12222                 tokpushback = 0;
12223                 return lasttoken;
12224         }
12225         setprompt_if(needprompt, 2);
12226         startlinno = g_parsefile->linno;
12227         for (;;) {                      /* until token or start of word found */
12228                 c = pgetc();
12229                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12230                         continue;
12231
12232                 if (c == '#') {
12233                         while ((c = pgetc()) != '\n' && c != PEOF)
12234                                 continue;
12235                         pungetc();
12236                 } else if (c == '\\') {
12237                         if (pgetc() != '\n') {
12238                                 pungetc();
12239                                 break; /* return readtoken1(...) */
12240                         }
12241                         nlprompt();
12242                 } else {
12243                         const char *p;
12244
12245                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12246                         if (c != PEOF) {
12247                                 if (c == '\n') {
12248                                         nlnoprompt();
12249                                 }
12250
12251                                 p = strchr(xxreadtoken_chars, c);
12252                                 if (p == NULL)
12253                                         break; /* return readtoken1(...) */
12254
12255                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12256                                         int cc = pgetc();
12257                                         if (cc == c) {    /* double occurrence? */
12258                                                 p += xxreadtoken_doubles + 1;
12259                                         } else {
12260                                                 pungetc();
12261 #if BASH_REDIR_OUTPUT
12262                                                 if (c == '&' && cc == '>') /* &> */
12263                                                         break; /* return readtoken1(...) */
12264 #endif
12265                                         }
12266                                 }
12267                         }
12268                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12269                         return lasttoken;
12270                 }
12271         } /* for (;;) */
12272
12273         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12274 }
12275 #else /* old xxreadtoken */
12276 #define RETURN(token)   return lasttoken = token
12277 static int
12278 xxreadtoken(void)
12279 {
12280         int c;
12281
12282         if (tokpushback) {
12283                 tokpushback = 0;
12284                 return lasttoken;
12285         }
12286         setprompt_if(needprompt, 2);
12287         startlinno = g_parsefile->linno;
12288         for (;;) {      /* until token or start of word found */
12289                 c = pgetc();
12290                 switch (c) {
12291                 case ' ': case '\t':
12292                 IF_ASH_ALIAS(case PEOA:)
12293                         continue;
12294                 case '#':
12295                         while ((c = pgetc()) != '\n' && c != PEOF)
12296                                 continue;
12297                         pungetc();
12298                         continue;
12299                 case '\\':
12300                         if (pgetc() == '\n') {
12301                                 nlprompt();
12302                                 continue;
12303                         }
12304                         pungetc();
12305                         goto breakloop;
12306                 case '\n':
12307                         nlnoprompt();
12308                         RETURN(TNL);
12309                 case PEOF:
12310                         RETURN(TEOF);
12311                 case '&':
12312                         if (pgetc() == '&')
12313                                 RETURN(TAND);
12314                         pungetc();
12315                         RETURN(TBACKGND);
12316                 case '|':
12317                         if (pgetc() == '|')
12318                                 RETURN(TOR);
12319                         pungetc();
12320                         RETURN(TPIPE);
12321                 case ';':
12322                         if (pgetc() == ';')
12323                                 RETURN(TENDCASE);
12324                         pungetc();
12325                         RETURN(TSEMI);
12326                 case '(':
12327                         RETURN(TLP);
12328                 case ')':
12329                         RETURN(TRP);
12330                 default:
12331                         goto breakloop;
12332                 }
12333         }
12334  breakloop:
12335         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12336 #undef RETURN
12337 }
12338 #endif /* old xxreadtoken */
12339
12340 static int
12341 readtoken(void)
12342 {
12343         int t;
12344         int kwd = checkkwd;
12345 #if DEBUG
12346         smallint alreadyseen = tokpushback;
12347 #endif
12348
12349 #if ENABLE_ASH_ALIAS
12350  top:
12351 #endif
12352
12353         t = xxreadtoken();
12354
12355         /*
12356          * eat newlines
12357          */
12358         if (kwd & CHKNL) {
12359                 while (t == TNL) {
12360                         parseheredoc();
12361                         t = xxreadtoken();
12362                 }
12363         }
12364
12365         if (t != TWORD || quoteflag) {
12366                 goto out;
12367         }
12368
12369         /*
12370          * check for keywords
12371          */
12372         if (kwd & CHKKWD) {
12373                 const char *const *pp;
12374
12375                 pp = findkwd(wordtext);
12376                 if (pp) {
12377                         lasttoken = t = pp - tokname_array;
12378                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12379                         goto out;
12380                 }
12381         }
12382
12383         if (checkkwd & CHKALIAS) {
12384 #if ENABLE_ASH_ALIAS
12385                 struct alias *ap;
12386                 ap = lookupalias(wordtext, 1);
12387                 if (ap != NULL) {
12388                         if (*ap->val) {
12389                                 pushstring(ap->val, ap);
12390                         }
12391                         goto top;
12392                 }
12393 #endif
12394         }
12395  out:
12396         checkkwd = 0;
12397 #if DEBUG
12398         if (!alreadyseen)
12399                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12400         else
12401                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12402 #endif
12403         return t;
12404 }
12405
12406 static int
12407 peektoken(void)
12408 {
12409         int t;
12410
12411         t = readtoken();
12412         tokpushback = 1;
12413         return t;
12414 }
12415
12416 /*
12417  * Read and parse a command.  Returns NODE_EOF on end of file.
12418  * (NULL is a valid parse tree indicating a blank line.)
12419  */
12420 static union node *
12421 parsecmd(int interact)
12422 {
12423         tokpushback = 0;
12424         checkkwd = 0;
12425         heredoclist = 0;
12426         doprompt = interact;
12427         setprompt_if(doprompt, doprompt);
12428         needprompt = 0;
12429         return list(1);
12430 }
12431
12432 /*
12433  * Input any here documents.
12434  */
12435 static void
12436 parseheredoc(void)
12437 {
12438         struct heredoc *here;
12439         union node *n;
12440
12441         here = heredoclist;
12442         heredoclist = NULL;
12443
12444         while (here) {
12445                 setprompt_if(needprompt, 2);
12446                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12447                                 here->eofmark, here->striptabs);
12448                 n = stzalloc(sizeof(struct narg));
12449                 n->narg.type = NARG;
12450                 /*n->narg.next = NULL; - stzalloc did it */
12451                 n->narg.text = wordtext;
12452                 n->narg.backquote = backquotelist;
12453                 here->here->nhere.doc = n;
12454                 here = here->next;
12455         }
12456 }
12457
12458
12459 /*
12460  * called by editline -- any expansions to the prompt should be added here.
12461  */
12462 #if ENABLE_ASH_EXPAND_PRMT
12463 static const char *
12464 expandstr(const char *ps)
12465 {
12466         union node n;
12467         int saveprompt;
12468
12469         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12470          * and token processing _can_ alter it (delete NULs etc). */
12471         setinputstring((char *)ps);
12472
12473         saveprompt = doprompt;
12474         doprompt = 0;
12475         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12476         doprompt = saveprompt;
12477
12478         popfile();
12479
12480         n.narg.type = NARG;
12481         n.narg.next = NULL;
12482         n.narg.text = wordtext;
12483         n.narg.backquote = backquotelist;
12484
12485         expandarg(&n, NULL, EXP_QUOTED);
12486         return stackblock();
12487 }
12488 #endif
12489
12490 /*
12491  * Execute a command or commands contained in a string.
12492  */
12493 static int
12494 evalstring(char *s, int flags)
12495 {
12496         struct jmploc *volatile savehandler;
12497         struct jmploc jmploc;
12498         int ex;
12499
12500         union node *n;
12501         struct stackmark smark;
12502         int status;
12503
12504         s = sstrdup(s);
12505         setinputstring(s);
12506         setstackmark(&smark);
12507
12508         status = 0;
12509         /* On exception inside execution loop, we must popfile().
12510          * Try interactively:
12511          *      readonly a=a
12512          *      command eval "a=b"  # throws "is read only" error
12513          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12514          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12515          */
12516         savehandler = exception_handler;
12517         ex = setjmp(jmploc.loc);
12518         if (ex)
12519                 goto out;
12520         exception_handler = &jmploc;
12521
12522         while ((n = parsecmd(0)) != NODE_EOF) {
12523                 int i;
12524
12525                 i = evaltree(n, flags);
12526                 if (n)
12527                         status = i;
12528                 popstackmark(&smark);
12529                 if (evalskip)
12530                         break;
12531         }
12532  out:
12533         popstackmark(&smark);
12534         popfile();
12535         stunalloc(s);
12536
12537         exception_handler = savehandler;
12538         if (ex)
12539                 longjmp(exception_handler->loc, ex);
12540
12541         return status;
12542 }
12543
12544 /*
12545  * The eval command.
12546  */
12547 static int FAST_FUNC
12548 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12549 {
12550         char *p;
12551         char *concat;
12552
12553         if (argv[1]) {
12554                 p = argv[1];
12555                 argv += 2;
12556                 if (argv[0]) {
12557                         STARTSTACKSTR(concat);
12558                         for (;;) {
12559                                 concat = stack_putstr(p, concat);
12560                                 p = *argv++;
12561                                 if (p == NULL)
12562                                         break;
12563                                 STPUTC(' ', concat);
12564                         }
12565                         STPUTC('\0', concat);
12566                         p = grabstackstr(concat);
12567                 }
12568                 return evalstring(p, flags & EV_TESTED);
12569         }
12570         return 0;
12571 }
12572
12573 /*
12574  * Read and execute commands.
12575  * "Top" is nonzero for the top level command loop;
12576  * it turns on prompting if the shell is interactive.
12577  */
12578 static int
12579 cmdloop(int top)
12580 {
12581         union node *n;
12582         struct stackmark smark;
12583         int inter;
12584         int status = 0;
12585         int numeof = 0;
12586
12587         TRACE(("cmdloop(%d) called\n", top));
12588         for (;;) {
12589                 int skip;
12590
12591                 setstackmark(&smark);
12592 #if JOBS
12593                 if (doing_jobctl)
12594                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12595 #endif
12596                 inter = 0;
12597                 if (iflag && top) {
12598                         inter++;
12599                         chkmail();
12600                 }
12601                 n = parsecmd(inter);
12602 #if DEBUG
12603                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12604                         showtree(n);
12605 #endif
12606                 if (n == NODE_EOF) {
12607                         if (!top || numeof >= 50)
12608                                 break;
12609                         if (!stoppedjobs()) {
12610                                 if (!Iflag)
12611                                         break;
12612                                 out2str("\nUse \"exit\" to leave shell.\n");
12613                         }
12614                         numeof++;
12615                 } else if (nflag == 0) {
12616                         int i;
12617
12618                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12619                         job_warning >>= 1;
12620                         numeof = 0;
12621                         i = evaltree(n, 0);
12622                         if (n)
12623                                 status = i;
12624                 }
12625                 popstackmark(&smark);
12626                 skip = evalskip;
12627
12628                 if (skip) {
12629                         evalskip &= ~SKIPFUNC;
12630                         break;
12631                 }
12632         }
12633         return status;
12634 }
12635
12636 /*
12637  * Take commands from a file.  To be compatible we should do a path
12638  * search for the file, which is necessary to find sub-commands.
12639  */
12640 static char *
12641 find_dot_file(char *name)
12642 {
12643         char *fullname;
12644         const char *path = pathval();
12645         struct stat statb;
12646
12647         /* don't try this for absolute or relative paths */
12648         if (strchr(name, '/'))
12649                 return name;
12650
12651         while ((fullname = path_advance(&path, name)) != NULL) {
12652                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12653                         /*
12654                          * Don't bother freeing here, since it will
12655                          * be freed by the caller.
12656                          */
12657                         return fullname;
12658                 }
12659                 if (fullname != name)
12660                         stunalloc(fullname);
12661         }
12662
12663         /* not found in the PATH */
12664         ash_msg_and_raise_error("%s: not found", name);
12665         /* NOTREACHED */
12666 }
12667
12668 static int FAST_FUNC
12669 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12670 {
12671         /* "false; . empty_file; echo $?" should print 0, not 1: */
12672         int status = 0;
12673         char *fullname;
12674         char **argv;
12675         char *args_need_save;
12676         struct strlist *sp;
12677         volatile struct shparam saveparam;
12678
12679         for (sp = cmdenviron; sp; sp = sp->next)
12680                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12681
12682         nextopt(nullstr); /* handle possible "--" */
12683         argv = argptr;
12684
12685         if (!argv[0]) {
12686                 /* bash says: "bash: .: filename argument required" */
12687                 return 2; /* bash compat */
12688         }
12689
12690         /* This aborts if file isn't found, which is POSIXly correct.
12691          * bash returns exitcode 1 instead.
12692          */
12693         fullname = find_dot_file(argv[0]);
12694         argv++;
12695         args_need_save = argv[0];
12696         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12697                 int argc;
12698                 saveparam = shellparam;
12699                 shellparam.malloced = 0;
12700                 argc = 1;
12701                 while (argv[argc])
12702                         argc++;
12703                 shellparam.nparam = argc;
12704                 shellparam.p = argv;
12705         };
12706
12707         /* This aborts if file can't be opened, which is POSIXly correct.
12708          * bash returns exitcode 1 instead.
12709          */
12710         setinputfile(fullname, INPUT_PUSH_FILE);
12711         commandname = fullname;
12712         status = cmdloop(0);
12713         popfile();
12714
12715         if (args_need_save) {
12716                 freeparam(&shellparam);
12717                 shellparam = saveparam;
12718         };
12719
12720         return status;
12721 }
12722
12723 static int FAST_FUNC
12724 exitcmd(int argc UNUSED_PARAM, char **argv)
12725 {
12726         if (stoppedjobs())
12727                 return 0;
12728         if (argv[1])
12729                 exitstatus = number(argv[1]);
12730         raise_exception(EXEXIT);
12731         /* NOTREACHED */
12732 }
12733
12734 /*
12735  * Read a file containing shell functions.
12736  */
12737 static void
12738 readcmdfile(char *name)
12739 {
12740         setinputfile(name, INPUT_PUSH_FILE);
12741         cmdloop(0);
12742         popfile();
12743 }
12744
12745
12746 /* ============ find_command inplementation */
12747
12748 /*
12749  * Resolve a command name.  If you change this routine, you may have to
12750  * change the shellexec routine as well.
12751  */
12752 static void
12753 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12754 {
12755         struct tblentry *cmdp;
12756         int idx;
12757         int prev;
12758         char *fullname;
12759         struct stat statb;
12760         int e;
12761         int updatetbl;
12762         struct builtincmd *bcmd;
12763
12764         /* If name contains a slash, don't use PATH or hash table */
12765         if (strchr(name, '/') != NULL) {
12766                 entry->u.index = -1;
12767                 if (act & DO_ABS) {
12768                         while (stat(name, &statb) < 0) {
12769 #ifdef SYSV
12770                                 if (errno == EINTR)
12771                                         continue;
12772 #endif
12773                                 entry->cmdtype = CMDUNKNOWN;
12774                                 return;
12775                         }
12776                 }
12777                 entry->cmdtype = CMDNORMAL;
12778                 return;
12779         }
12780
12781 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12782
12783         updatetbl = (path == pathval());
12784         if (!updatetbl) {
12785                 act |= DO_ALTPATH;
12786                 if (strstr(path, "%builtin") != NULL)
12787                         act |= DO_ALTBLTIN;
12788         }
12789
12790         /* If name is in the table, check answer will be ok */
12791         cmdp = cmdlookup(name, 0);
12792         if (cmdp != NULL) {
12793                 int bit;
12794
12795                 switch (cmdp->cmdtype) {
12796                 default:
12797 #if DEBUG
12798                         abort();
12799 #endif
12800                 case CMDNORMAL:
12801                         bit = DO_ALTPATH;
12802                         break;
12803                 case CMDFUNCTION:
12804                         bit = DO_NOFUNC;
12805                         break;
12806                 case CMDBUILTIN:
12807                         bit = DO_ALTBLTIN;
12808                         break;
12809                 }
12810                 if (act & bit) {
12811                         updatetbl = 0;
12812                         cmdp = NULL;
12813                 } else if (cmdp->rehash == 0)
12814                         /* if not invalidated by cd, we're done */
12815                         goto success;
12816         }
12817
12818         /* If %builtin not in path, check for builtin next */
12819         bcmd = find_builtin(name);
12820         if (bcmd) {
12821                 if (IS_BUILTIN_REGULAR(bcmd))
12822                         goto builtin_success;
12823                 if (act & DO_ALTPATH) {
12824                         if (!(act & DO_ALTBLTIN))
12825                                 goto builtin_success;
12826                 } else if (builtinloc <= 0) {
12827                         goto builtin_success;
12828                 }
12829         }
12830
12831 #if ENABLE_FEATURE_SH_STANDALONE
12832         {
12833                 int applet_no = find_applet_by_name(name);
12834                 if (applet_no >= 0) {
12835                         entry->cmdtype = CMDNORMAL;
12836                         entry->u.index = -2 - applet_no;
12837                         return;
12838                 }
12839         }
12840 #endif
12841
12842         /* We have to search path. */
12843         prev = -1;              /* where to start */
12844         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12845                 if (cmdp->cmdtype == CMDBUILTIN)
12846                         prev = builtinloc;
12847                 else
12848                         prev = cmdp->param.index;
12849         }
12850
12851         e = ENOENT;
12852         idx = -1;
12853  loop:
12854         while ((fullname = path_advance(&path, name)) != NULL) {
12855                 stunalloc(fullname);
12856                 /* NB: code below will still use fullname
12857                  * despite it being "unallocated" */
12858                 idx++;
12859                 if (pathopt) {
12860                         if (prefix(pathopt, "builtin")) {
12861                                 if (bcmd)
12862                                         goto builtin_success;
12863                                 continue;
12864                         }
12865                         if ((act & DO_NOFUNC)
12866                          || !prefix(pathopt, "func")
12867                         ) {     /* ignore unimplemented options */
12868                                 continue;
12869                         }
12870                 }
12871                 /* if rehash, don't redo absolute path names */
12872                 if (fullname[0] == '/' && idx <= prev) {
12873                         if (idx < prev)
12874                                 continue;
12875                         TRACE(("searchexec \"%s\": no change\n", name));
12876                         goto success;
12877                 }
12878                 while (stat(fullname, &statb) < 0) {
12879 #ifdef SYSV
12880                         if (errno == EINTR)
12881                                 continue;
12882 #endif
12883                         if (errno != ENOENT && errno != ENOTDIR)
12884                                 e = errno;
12885                         goto loop;
12886                 }
12887                 e = EACCES;     /* if we fail, this will be the error */
12888                 if (!S_ISREG(statb.st_mode))
12889                         continue;
12890                 if (pathopt) {          /* this is a %func directory */
12891                         stalloc(strlen(fullname) + 1);
12892                         /* NB: stalloc will return space pointed by fullname
12893                          * (because we don't have any intervening allocations
12894                          * between stunalloc above and this stalloc) */
12895                         readcmdfile(fullname);
12896                         cmdp = cmdlookup(name, 0);
12897                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12898                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12899                         stunalloc(fullname);
12900                         goto success;
12901                 }
12902                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12903                 if (!updatetbl) {
12904                         entry->cmdtype = CMDNORMAL;
12905                         entry->u.index = idx;
12906                         return;
12907                 }
12908                 INT_OFF;
12909                 cmdp = cmdlookup(name, 1);
12910                 cmdp->cmdtype = CMDNORMAL;
12911                 cmdp->param.index = idx;
12912                 INT_ON;
12913                 goto success;
12914         }
12915
12916         /* We failed.  If there was an entry for this command, delete it */
12917         if (cmdp && updatetbl)
12918                 delete_cmd_entry();
12919         if (act & DO_ERR)
12920                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12921         entry->cmdtype = CMDUNKNOWN;
12922         return;
12923
12924  builtin_success:
12925         if (!updatetbl) {
12926                 entry->cmdtype = CMDBUILTIN;
12927                 entry->u.cmd = bcmd;
12928                 return;
12929         }
12930         INT_OFF;
12931         cmdp = cmdlookup(name, 1);
12932         cmdp->cmdtype = CMDBUILTIN;
12933         cmdp->param.cmd = bcmd;
12934         INT_ON;
12935  success:
12936         cmdp->rehash = 0;
12937         entry->cmdtype = cmdp->cmdtype;
12938         entry->u = cmdp->param;
12939 }
12940
12941
12942 /*
12943  * The trap builtin.
12944  */
12945 static int FAST_FUNC
12946 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12947 {
12948         char *action;
12949         char **ap;
12950         int signo, exitcode;
12951
12952         nextopt(nullstr);
12953         ap = argptr;
12954         if (!*ap) {
12955                 for (signo = 0; signo < NSIG; signo++) {
12956                         char *tr = trap_ptr[signo];
12957                         if (tr) {
12958                                 /* note: bash adds "SIG", but only if invoked
12959                                  * as "bash". If called as "sh", or if set -o posix,
12960                                  * then it prints short signal names.
12961                                  * We are printing short names: */
12962                                 out1fmt("trap -- %s %s\n",
12963                                                 single_quote(tr),
12964                                                 get_signame(signo));
12965                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12966                  * In this case, we will exit very soon, no need to free(). */
12967                                 /* if (trap_ptr != trap && tp[0]) */
12968                                 /*      free(tr); */
12969                         }
12970                 }
12971                 /*
12972                 if (trap_ptr != trap) {
12973                         free(trap_ptr);
12974                         trap_ptr = trap;
12975                 }
12976                 */
12977                 return 0;
12978         }
12979
12980         action = NULL;
12981         if (ap[1])
12982                 action = *ap++;
12983         exitcode = 0;
12984         while (*ap) {
12985                 signo = get_signum(*ap);
12986                 if (signo < 0) {
12987                         /* Mimic bash message exactly */
12988                         ash_msg("%s: invalid signal specification", *ap);
12989                         exitcode = 1;
12990                         goto next;
12991                 }
12992                 INT_OFF;
12993                 if (action) {
12994                         if (LONE_DASH(action))
12995                                 action = NULL;
12996                         else {
12997                                 if (action[0]) /* not NULL and not "" and not "-" */
12998                                         may_have_traps = 1;
12999                                 action = ckstrdup(action);
13000                         }
13001                 }
13002                 free(trap[signo]);
13003                 trap[signo] = action;
13004                 if (signo != 0)
13005                         setsignal(signo);
13006                 INT_ON;
13007  next:
13008                 ap++;
13009         }
13010         return exitcode;
13011 }
13012
13013
13014 /* ============ Builtins */
13015
13016 #if ENABLE_ASH_HELP
13017 static int FAST_FUNC
13018 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13019 {
13020         unsigned col;
13021         unsigned i;
13022
13023         out1fmt(
13024                 "Built-in commands:\n"
13025                 "------------------\n");
13026         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13027                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13028                                         builtintab[i].name + 1);
13029                 if (col > 60) {
13030                         out1fmt("\n");
13031                         col = 0;
13032                 }
13033         }
13034 # if ENABLE_FEATURE_SH_STANDALONE
13035         {
13036                 const char *a = applet_names;
13037                 while (*a) {
13038                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13039                         if (col > 60) {
13040                                 out1fmt("\n");
13041                                 col = 0;
13042                         }
13043                         while (*a++ != '\0')
13044                                 continue;
13045                 }
13046         }
13047 # endif
13048         newline_and_flush(stdout);
13049         return EXIT_SUCCESS;
13050 }
13051 #endif
13052
13053 #if MAX_HISTORY
13054 static int FAST_FUNC
13055 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13056 {
13057         show_history(line_input_state);
13058         return EXIT_SUCCESS;
13059 }
13060 #endif
13061
13062 /*
13063  * The export and readonly commands.
13064  */
13065 static int FAST_FUNC
13066 exportcmd(int argc UNUSED_PARAM, char **argv)
13067 {
13068         struct var *vp;
13069         char *name;
13070         const char *p;
13071         char **aptr;
13072         char opt;
13073         int flag;
13074         int flag_off;
13075
13076         /* "readonly" in bash accepts, but ignores -n.
13077          * We do the same: it saves a conditional in nextopt's param.
13078          */
13079         flag_off = 0;
13080         while ((opt = nextopt("np")) != '\0') {
13081                 if (opt == 'n')
13082                         flag_off = VEXPORT;
13083         }
13084         flag = VEXPORT;
13085         if (argv[0][0] == 'r') {
13086                 flag = VREADONLY;
13087                 flag_off = 0; /* readonly ignores -n */
13088         }
13089         flag_off = ~flag_off;
13090
13091         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13092         {
13093                 aptr = argptr;
13094                 name = *aptr;
13095                 if (name) {
13096                         do {
13097                                 p = strchr(name, '=');
13098                                 if (p != NULL) {
13099                                         p++;
13100                                 } else {
13101                                         vp = *findvar(hashvar(name), name);
13102                                         if (vp) {
13103                                                 vp->flags = ((vp->flags | flag) & flag_off);
13104                                                 continue;
13105                                         }
13106                                 }
13107                                 setvar(name, p, (flag & flag_off));
13108                         } while ((name = *++aptr) != NULL);
13109                         return 0;
13110                 }
13111         }
13112
13113         /* No arguments. Show the list of exported or readonly vars.
13114          * -n is ignored.
13115          */
13116         showvars(argv[0], flag, 0);
13117         return 0;
13118 }
13119
13120 /*
13121  * Delete a function if it exists.
13122  */
13123 static void
13124 unsetfunc(const char *name)
13125 {
13126         struct tblentry *cmdp;
13127
13128         cmdp = cmdlookup(name, 0);
13129         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13130                 delete_cmd_entry();
13131 }
13132
13133 /*
13134  * The unset builtin command.  We unset the function before we unset the
13135  * variable to allow a function to be unset when there is a readonly variable
13136  * with the same name.
13137  */
13138 static int FAST_FUNC
13139 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13140 {
13141         char **ap;
13142         int i;
13143         int flag = 0;
13144         int ret = 0;
13145
13146         while ((i = nextopt("vf")) != 0) {
13147                 flag = i;
13148         }
13149
13150         for (ap = argptr; *ap; ap++) {
13151                 if (flag != 'f') {
13152                         i = unsetvar(*ap);
13153                         ret |= i;
13154                         if (!(i & 2))
13155                                 continue;
13156                 }
13157                 if (flag != 'v')
13158                         unsetfunc(*ap);
13159         }
13160         return ret & 1;
13161 }
13162
13163 static const unsigned char timescmd_str[] ALIGN1 = {
13164         ' ',  offsetof(struct tms, tms_utime),
13165         '\n', offsetof(struct tms, tms_stime),
13166         ' ',  offsetof(struct tms, tms_cutime),
13167         '\n', offsetof(struct tms, tms_cstime),
13168         0
13169 };
13170 static int FAST_FUNC
13171 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13172 {
13173         unsigned long clk_tck, s, t;
13174         const unsigned char *p;
13175         struct tms buf;
13176
13177         clk_tck = bb_clk_tck();
13178         times(&buf);
13179
13180         p = timescmd_str;
13181         do {
13182                 t = *(clock_t *)(((char *) &buf) + p[1]);
13183                 s = t / clk_tck;
13184                 t = t % clk_tck;
13185                 out1fmt("%lum%lu.%03lus%c",
13186                         s / 60, s % 60,
13187                         (t * 1000) / clk_tck,
13188                         p[0]);
13189                 p += 2;
13190         } while (*p);
13191
13192         return 0;
13193 }
13194
13195 #if ENABLE_FEATURE_SH_MATH
13196 /*
13197  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13198  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13199  *
13200  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13201  */
13202 static int FAST_FUNC
13203 letcmd(int argc UNUSED_PARAM, char **argv)
13204 {
13205         arith_t i;
13206
13207         argv++;
13208         if (!*argv)
13209                 ash_msg_and_raise_error("expression expected");
13210         do {
13211                 i = ash_arith(*argv);
13212         } while (*++argv);
13213
13214         return !i;
13215 }
13216 #endif
13217
13218 /*
13219  * The read builtin. Options:
13220  *      -r              Do not interpret '\' specially
13221  *      -s              Turn off echo (tty only)
13222  *      -n NCHARS       Read NCHARS max
13223  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13224  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13225  *      -u FD           Read from given FD instead of fd 0
13226  * This uses unbuffered input, which may be avoidable in some cases.
13227  * TODO: bash also has:
13228  *      -a ARRAY        Read into array[0],[1],etc
13229  *      -d DELIM        End on DELIM char, not newline
13230  *      -e              Use line editing (tty only)
13231  */
13232 static int FAST_FUNC
13233 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13234 {
13235         char *opt_n = NULL;
13236         char *opt_p = NULL;
13237         char *opt_t = NULL;
13238         char *opt_u = NULL;
13239         int read_flags = 0;
13240         const char *r;
13241         int i;
13242
13243         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13244                 switch (i) {
13245                 case 'p':
13246                         opt_p = optionarg;
13247                         break;
13248                 case 'n':
13249                         opt_n = optionarg;
13250                         break;
13251                 case 's':
13252                         read_flags |= BUILTIN_READ_SILENT;
13253                         break;
13254                 case 't':
13255                         opt_t = optionarg;
13256                         break;
13257                 case 'r':
13258                         read_flags |= BUILTIN_READ_RAW;
13259                         break;
13260                 case 'u':
13261                         opt_u = optionarg;
13262                         break;
13263                 default:
13264                         break;
13265                 }
13266         }
13267
13268         /* "read -s" needs to save/restore termios, can't allow ^C
13269          * to jump out of it.
13270          */
13271         INT_OFF;
13272         r = shell_builtin_read(setvar0,
13273                 argptr,
13274                 bltinlookup("IFS"), /* can be NULL */
13275                 read_flags,
13276                 opt_n,
13277                 opt_p,
13278                 opt_t,
13279                 opt_u
13280         );
13281         INT_ON;
13282
13283         if ((uintptr_t)r > 1)
13284                 ash_msg_and_raise_error(r);
13285
13286         return (uintptr_t)r;
13287 }
13288
13289 static int FAST_FUNC
13290 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13291 {
13292         static const char permuser[3] ALIGN1 = "ogu";
13293
13294         mode_t mask;
13295         int symbolic_mode = 0;
13296
13297         while (nextopt("S") != '\0') {
13298                 symbolic_mode = 1;
13299         }
13300
13301         INT_OFF;
13302         mask = umask(0);
13303         umask(mask);
13304         INT_ON;
13305
13306         if (*argptr == NULL) {
13307                 if (symbolic_mode) {
13308                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13309                         char *p = buf;
13310                         int i;
13311
13312                         i = 2;
13313                         for (;;) {
13314                                 *p++ = ',';
13315                                 *p++ = permuser[i];
13316                                 *p++ = '=';
13317                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13318                                 if (!(mask & 0400)) *p++ = 'r';
13319                                 if (!(mask & 0200)) *p++ = 'w';
13320                                 if (!(mask & 0100)) *p++ = 'x';
13321                                 mask <<= 3;
13322                                 if (--i < 0)
13323                                         break;
13324                         }
13325                         *p = '\0';
13326                         puts(buf + 1);
13327                 } else {
13328                         out1fmt("%04o\n", mask);
13329                 }
13330         } else {
13331                 char *modestr = *argptr;
13332                 /* numeric umasks are taken as-is */
13333                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13334                 if (!isdigit(modestr[0]))
13335                         mask ^= 0777;
13336                 mask = bb_parse_mode(modestr, mask);
13337                 if ((unsigned)mask > 0777) {
13338                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13339                 }
13340                 if (!isdigit(modestr[0]))
13341                         mask ^= 0777;
13342                 umask(mask);
13343         }
13344         return 0;
13345 }
13346
13347 static int FAST_FUNC
13348 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13349 {
13350         return shell_builtin_ulimit(argv);
13351 }
13352
13353 /* ============ main() and helpers */
13354
13355 /*
13356  * Called to exit the shell.
13357  */
13358 static void
13359 exitshell(void)
13360 {
13361         struct jmploc loc;
13362         char *p;
13363         int status;
13364
13365 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13366         save_history(line_input_state);
13367 #endif
13368         status = exitstatus;
13369         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13370         if (setjmp(loc.loc)) {
13371                 if (exception_type == EXEXIT)
13372                         status = exitstatus;
13373                 goto out;
13374         }
13375         exception_handler = &loc;
13376         p = trap[0];
13377         if (p) {
13378                 trap[0] = NULL;
13379                 evalskip = 0;
13380                 evalstring(p, 0);
13381                 /*free(p); - we'll exit soon */
13382         }
13383  out:
13384         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13385          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13386          */
13387         setjobctl(0);
13388         flush_stdout_stderr();
13389         _exit(status);
13390         /* NOTREACHED */
13391 }
13392
13393 static void
13394 init(void)
13395 {
13396         /* we will never free this */
13397         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13398
13399         sigmode[SIGCHLD - 1] = S_DFL;
13400         setsignal(SIGCHLD);
13401
13402         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13403          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13404          */
13405         signal(SIGHUP, SIG_DFL);
13406
13407         {
13408                 char **envp;
13409                 const char *p;
13410                 struct stat st1, st2;
13411
13412                 initvar();
13413                 for (envp = environ; envp && *envp; envp++) {
13414                         p = endofname(*envp);
13415                         if (p != *envp && *p == '=') {
13416                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13417                         }
13418                 }
13419
13420                 setvareq((char*)defoptindvar, VTEXTFIXED);
13421
13422                 setvar0("PPID", utoa(getppid()));
13423 #if BASH_SHLVL_VAR
13424                 p = lookupvar("SHLVL");
13425                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13426 #endif
13427 #if BASH_HOSTNAME_VAR
13428                 if (!lookupvar("HOSTNAME")) {
13429                         struct utsname uts;
13430                         uname(&uts);
13431                         setvar0("HOSTNAME", uts.nodename);
13432                 }
13433 #endif
13434                 p = lookupvar("PWD");
13435                 if (p) {
13436                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13437                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13438                         ) {
13439                                 p = NULL;
13440                         }
13441                 }
13442                 setpwd(p, 0);
13443         }
13444 }
13445
13446
13447 //usage:#define ash_trivial_usage
13448 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13449 //usage:#define ash_full_usage "\n\n"
13450 //usage:        "Unix shell interpreter"
13451
13452 /*
13453  * Process the shell command line arguments.
13454  */
13455 static void
13456 procargs(char **argv)
13457 {
13458         int i;
13459         const char *xminusc;
13460         char **xargv;
13461
13462         xargv = argv;
13463         arg0 = xargv[0];
13464         /* if (xargv[0]) - mmm, this is always true! */
13465                 xargv++;
13466         for (i = 0; i < NOPTS; i++)
13467                 optlist[i] = 2;
13468         argptr = xargv;
13469         if (options(/*cmdline:*/ 1)) {
13470                 /* it already printed err message */
13471                 raise_exception(EXERROR);
13472         }
13473         xargv = argptr;
13474         xminusc = minusc;
13475         if (*xargv == NULL) {
13476                 if (xminusc)
13477                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13478                 sflag = 1;
13479         }
13480         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13481                 iflag = 1;
13482         if (mflag == 2)
13483                 mflag = iflag;
13484         for (i = 0; i < NOPTS; i++)
13485                 if (optlist[i] == 2)
13486                         optlist[i] = 0;
13487 #if DEBUG == 2
13488         debug = 1;
13489 #endif
13490         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13491         if (xminusc) {
13492                 minusc = *xargv++;
13493                 if (*xargv)
13494                         goto setarg0;
13495         } else if (!sflag) {
13496                 setinputfile(*xargv, 0);
13497  setarg0:
13498                 arg0 = *xargv++;
13499                 commandname = arg0;
13500         }
13501
13502         shellparam.p = xargv;
13503 #if ENABLE_ASH_GETOPTS
13504         shellparam.optind = 1;
13505         shellparam.optoff = -1;
13506 #endif
13507         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13508         while (*xargv) {
13509                 shellparam.nparam++;
13510                 xargv++;
13511         }
13512         optschanged();
13513 }
13514
13515 /*
13516  * Read /etc/profile, ~/.profile, $ENV.
13517  */
13518 static void
13519 read_profile(const char *name)
13520 {
13521         name = expandstr(name);
13522         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13523                 return;
13524         cmdloop(0);
13525         popfile();
13526 }
13527
13528 /*
13529  * This routine is called when an error or an interrupt occurs in an
13530  * interactive shell and control is returned to the main command loop.
13531  * (In dash, this function is auto-generated by build machinery).
13532  */
13533 static void
13534 reset(void)
13535 {
13536         /* from eval.c: */
13537         evalskip = 0;
13538         loopnest = 0;
13539
13540         /* from expand.c: */
13541         ifsfree();
13542
13543         /* from input.c: */
13544         g_parsefile->left_in_buffer = 0;
13545         g_parsefile->left_in_line = 0;      /* clear input buffer */
13546         popallfiles();
13547
13548         /* from redir.c: */
13549         while (redirlist)
13550                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13551 }
13552
13553 #if PROFILE
13554 static short profile_buf[16384];
13555 extern int etext();
13556 #endif
13557
13558 /*
13559  * Main routine.  We initialize things, parse the arguments, execute
13560  * profiles if we're a login shell, and then call cmdloop to execute
13561  * commands.  The setjmp call sets up the location to jump to when an
13562  * exception occurs.  When an exception occurs the variable "state"
13563  * is used to figure out how far we had gotten.
13564  */
13565 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13566 int ash_main(int argc UNUSED_PARAM, char **argv)
13567 {
13568         volatile smallint state;
13569         struct jmploc jmploc;
13570         struct stackmark smark;
13571
13572         /* Initialize global data */
13573         INIT_G_misc();
13574         INIT_G_memstack();
13575         INIT_G_var();
13576 #if ENABLE_ASH_ALIAS
13577         INIT_G_alias();
13578 #endif
13579         INIT_G_cmdtable();
13580
13581 #if PROFILE
13582         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13583 #endif
13584
13585 #if ENABLE_FEATURE_EDITING
13586         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13587 #endif
13588         state = 0;
13589         if (setjmp(jmploc.loc)) {
13590                 smallint e;
13591                 smallint s;
13592
13593                 reset();
13594
13595                 e = exception_type;
13596                 s = state;
13597                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13598                         exitshell();
13599                 }
13600                 if (e == EXINT) {
13601                         newline_and_flush(stderr);
13602                 }
13603
13604                 popstackmark(&smark);
13605                 FORCE_INT_ON; /* enable interrupts */
13606                 if (s == 1)
13607                         goto state1;
13608                 if (s == 2)
13609                         goto state2;
13610                 if (s == 3)
13611                         goto state3;
13612                 goto state4;
13613         }
13614         exception_handler = &jmploc;
13615         rootpid = getpid();
13616
13617         init();
13618         setstackmark(&smark);
13619         procargs(argv);
13620 #if DEBUG
13621         TRACE(("Shell args: "));
13622         trace_puts_args(argv);
13623 #endif
13624
13625         if (argv[0] && argv[0][0] == '-')
13626                 isloginsh = 1;
13627         if (isloginsh) {
13628                 const char *hp;
13629
13630                 state = 1;
13631                 read_profile("/etc/profile");
13632  state1:
13633                 state = 2;
13634                 hp = lookupvar("HOME");
13635                 if (hp)
13636                         read_profile("$HOME/.profile");
13637         }
13638  state2:
13639         state = 3;
13640         if (
13641 #ifndef linux
13642          getuid() == geteuid() && getgid() == getegid() &&
13643 #endif
13644          iflag
13645         ) {
13646                 const char *shinit = lookupvar("ENV");
13647                 if (shinit != NULL && *shinit != '\0')
13648                         read_profile(shinit);
13649         }
13650         popstackmark(&smark);
13651  state3:
13652         state = 4;
13653         if (minusc) {
13654                 /* evalstring pushes parsefile stack.
13655                  * Ensure we don't falsely claim that 0 (stdin)
13656                  * is one of stacked source fds.
13657                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13658                 // if (!sflag) g_parsefile->pf_fd = -1;
13659                 // ^^ not necessary since now we special-case fd 0
13660                 // in is_hidden_fd() to not be considered "hidden fd"
13661                 evalstring(minusc, 0);
13662         }
13663
13664         if (sflag || minusc == NULL) {
13665 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13666                 if (iflag) {
13667                         const char *hp = lookupvar("HISTFILE");
13668                         if (!hp) {
13669                                 hp = lookupvar("HOME");
13670                                 if (hp) {
13671                                         INT_OFF;
13672                                         hp = concat_path_file(hp, ".ash_history");
13673                                         setvar0("HISTFILE", hp);
13674                                         free((char*)hp);
13675                                         INT_ON;
13676                                         hp = lookupvar("HISTFILE");
13677                                 }
13678                         }
13679                         if (hp)
13680                                 line_input_state->hist_file = hp;
13681 # if ENABLE_FEATURE_SH_HISTFILESIZE
13682                         hp = lookupvar("HISTFILESIZE");
13683                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13684 # endif
13685                 }
13686 #endif
13687  state4: /* XXX ??? - why isn't this before the "if" statement */
13688                 cmdloop(1);
13689         }
13690 #if PROFILE
13691         monitor(0);
13692 #endif
13693 #ifdef GPROF
13694         {
13695                 extern void _mcleanup(void);
13696                 _mcleanup();
13697         }
13698 #endif
13699         TRACE(("End of main reached\n"));
13700         exitshell();
13701         /* NOTREACHED */
13702 }
13703
13704
13705 /*-
13706  * Copyright (c) 1989, 1991, 1993, 1994
13707  *      The Regents of the University of California.  All rights reserved.
13708  *
13709  * This code is derived from software contributed to Berkeley by
13710  * Kenneth Almquist.
13711  *
13712  * Redistribution and use in source and binary forms, with or without
13713  * modification, are permitted provided that the following conditions
13714  * are met:
13715  * 1. Redistributions of source code must retain the above copyright
13716  *    notice, this list of conditions and the following disclaimer.
13717  * 2. Redistributions in binary form must reproduce the above copyright
13718  *    notice, this list of conditions and the following disclaimer in the
13719  *    documentation and/or other materials provided with the distribution.
13720  * 3. Neither the name of the University nor the names of its contributors
13721  *    may be used to endorse or promote products derived from this software
13722  *    without specific prior written permission.
13723  *
13724  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13725  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13726  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13727  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13728  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13729  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13730  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13731  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13732  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13733  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13734  * SUCH DAMAGE.
13735  */