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