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