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