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