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