08bdfc3b3fd7e62b8f7919d509bcf713a9d89b06
[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         int type;
530         union node *assign;
531         union node *args;
532         union node *redirect;
533 };
534
535 struct npipe {
536         int type;
537         int backgnd;
538         struct nodelist *cmdlist;
539 };
540
541 struct nredir {
542         int type;
543         union node *n;
544         union node *redirect;
545 };
546
547 struct nbinary {
548         int type;
549         union node *ch1;
550         union node *ch2;
551 };
552
553 struct nif {
554         int type;
555         union node *test;
556         union node *ifpart;
557         union node *elsepart;
558 };
559
560 struct nfor {
561         int type;
562         union node *args;
563         union node *body;
564         char *var;
565 };
566
567 struct ncase {
568         int type;
569         union node *expr;
570         union node *cases;
571 };
572
573 struct nclist {
574         int type;
575         union node *next;
576         union node *pattern;
577         union node *body;
578 };
579
580 struct narg {
581         int type;
582         union node *next;
583         char *text;
584         struct nodelist *backquote;
585 };
586
587 struct nfile {
588         int type;
589         union node *next;
590         int fd;
591         union node *fname;
592         char *expfname;
593 };
594
595 struct ndup {
596         int type;
597         union node *next;
598         int fd;
599         int dupfd;
600         union node *vname;
601 };
602
603 struct nhere {
604         int type;
605         union node *next;
606         int fd;
607         union node *doc;
608 };
609
610 struct nnot {
611         int type;
612         union node *com;
613 };
614
615 union node {
616         int 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.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         char **ap;
1660
1661         if (param->malloced) {
1662                 for (ap = param->p; *ap; ap++)
1663                         free(*ap);
1664                 free(param->p);
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("cannot 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("cannot create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4848  eopen:
4849         ash_msg_and_raise_error("cannot 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         union node *n;
4903         struct redirtab *sv;
4904         int i;
4905         int fd;
4906         int newfd;
4907
4908         g_nullredirs++;
4909         if (!redir) {
4910                 return;
4911         }
4912         sv = NULL;
4913         INT_OFF;
4914         if (flags & REDIR_PUSH) {
4915                 sv = ckmalloc(sizeof(*sv));
4916                 sv->next = redirlist;
4917                 redirlist = sv;
4918                 sv->nullredirs = g_nullredirs - 1;
4919                 for (i = 0; i < 10; i++)
4920                         sv->renamed[i] = EMPTY;
4921                 g_nullredirs = 0;
4922         }
4923         n = redir;
4924         do {
4925                 fd = n->nfile.fd;
4926                 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD)
4927                  && n->ndup.dupfd == fd)
4928                         continue; /* redirect from/to same file descriptor */
4929
4930                 newfd = openredirect(n);
4931                 if (fd == newfd) {
4932                         /* Descriptor wasn't open before redirect.
4933                          * Mark it for close in the future */
4934                         if (sv && sv->renamed[fd] == EMPTY)
4935                                 sv->renamed[fd] = CLOSED;
4936                         continue;
4937                 }
4938                 if (sv && sv->renamed[fd] == EMPTY) {
4939                         i = fcntl(fd, F_DUPFD, 10);
4940
4941                         if (i == -1) {
4942                                 i = errno;
4943                                 if (i != EBADF) {
4944                                         close(newfd);
4945                                         errno = i;
4946                                         ash_msg_and_raise_error("%d: %m", fd);
4947                                         /* NOTREACHED */
4948                                 }
4949                         } else {
4950                                 sv->renamed[fd] = i;
4951                                 close(fd);
4952                         }
4953                 } else {
4954                         close(fd);
4955                 }
4956                 dupredirect(n, newfd);
4957         } while ((n = n->nfile.next));
4958         INT_ON;
4959         if ((flags & REDIR_SAVEFD2) && sv && sv->renamed[2] >= 0)
4960                 preverrout_fd = sv->renamed[2];
4961 }
4962
4963 /*
4964  * Undo the effects of the last redirection.
4965  */
4966 static void
4967 popredir(int drop)
4968 {
4969         struct redirtab *rp;
4970         int i;
4971
4972         if (--g_nullredirs >= 0)
4973                 return;
4974         INT_OFF;
4975         rp = redirlist;
4976         for (i = 0; i < 10; i++) {
4977                 if (rp->renamed[i] == CLOSED) {
4978                         if (!drop)
4979                                 close(i);
4980                         continue;
4981                 }
4982                 if (rp->renamed[i] != EMPTY) {
4983                         if (!drop) {
4984                                 close(i);
4985                                 copyfd(rp->renamed[i], i);
4986                         }
4987                         close(rp->renamed[i]);
4988                 }
4989         }
4990         redirlist = rp->next;
4991         g_nullredirs = rp->nullredirs;
4992         free(rp);
4993         INT_ON;
4994 }
4995
4996 /*
4997  * Undo all redirections.  Called on error or interrupt.
4998  */
4999
5000 /*
5001  * Discard all saved file descriptors.
5002  */
5003 static void
5004 clearredir(int drop)
5005 {
5006         for (;;) {
5007                 g_nullredirs = 0;
5008                 if (!redirlist)
5009                         break;
5010                 popredir(drop);
5011         }
5012 }
5013
5014 static int
5015 redirectsafe(union node *redir, int flags)
5016 {
5017         int err;
5018         volatile int saveint;
5019         struct jmploc *volatile savehandler = exception_handler;
5020         struct jmploc jmploc;
5021
5022         SAVE_INT(saveint);
5023         err = setjmp(jmploc.loc) * 2;
5024         if (!err) {
5025                 exception_handler = &jmploc;
5026                 redirect(redir, flags);
5027         }
5028         exception_handler = savehandler;
5029         if (err && exception != EXERROR)
5030                 longjmp(exception_handler->loc, 1);
5031         RESTORE_INT(saveint);
5032         return err;
5033 }
5034
5035
5036 /* ============ Routines to expand arguments to commands
5037  *
5038  * We have to deal with backquotes, shell variables, and file metacharacters.
5039  */
5040
5041 #if ENABLE_ASH_MATH_SUPPORT_64
5042 typedef int64_t arith_t;
5043 #define arith_t_type long long
5044 #else
5045 typedef long arith_t;
5046 #define arith_t_type long
5047 #endif
5048
5049 #if ENABLE_ASH_MATH_SUPPORT
5050 static arith_t dash_arith(const char *);
5051 static arith_t arith(const char *expr, int *perrcode);
5052 #endif
5053
5054 /*
5055  * expandarg flags
5056  */
5057 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5058 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5059 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5060 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5061 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5062 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
5063 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5064 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5065 #define EXP_QWORD       0x100   /* expand word in quoted parameter expansion */
5066 /*
5067  * _rmescape() flags
5068  */
5069 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5070 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5071 #define RMESCAPE_QUOTED 0x4     /* Remove CTLESC unless in quotes */
5072 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5073 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5074
5075 /*
5076  * Structure specifying which parts of the string should be searched
5077  * for IFS characters.
5078  */
5079 struct ifsregion {
5080         struct ifsregion *next; /* next region in list */
5081         int begoff;             /* offset of start of region */
5082         int endoff;             /* offset of end of region */
5083         int nulonly;            /* search for nul bytes only */
5084 };
5085
5086 struct arglist {
5087         struct strlist *list;
5088         struct strlist **lastp;
5089 };
5090
5091 /* output of current string */
5092 static char *expdest;
5093 /* list of back quote expressions */
5094 static struct nodelist *argbackq;
5095 /* first struct in list of ifs regions */
5096 static struct ifsregion ifsfirst;
5097 /* last struct in list */
5098 static struct ifsregion *ifslastp;
5099 /* holds expanded arg list */
5100 static struct arglist exparg;
5101
5102 /*
5103  * Our own itoa().
5104  */
5105 static int
5106 cvtnum(arith_t num)
5107 {
5108         int len;
5109
5110         expdest = makestrspace(32, expdest);
5111 #if ENABLE_ASH_MATH_SUPPORT_64
5112         len = fmtstr(expdest, 32, "%lld", (long long) num);
5113 #else
5114         len = fmtstr(expdest, 32, "%ld", num);
5115 #endif
5116         STADJUST(len, expdest);
5117         return len;
5118 }
5119
5120 static size_t
5121 esclen(const char *start, const char *p)
5122 {
5123         size_t esc = 0;
5124
5125         while (p > start && *--p == CTLESC) {
5126                 esc++;
5127         }
5128         return esc;
5129 }
5130
5131 /*
5132  * Remove any CTLESC characters from a string.
5133  */
5134 static char *
5135 _rmescapes(char *str, int flag)
5136 {
5137         static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5138
5139         char *p, *q, *r;
5140         unsigned inquotes;
5141         int notescaped;
5142         int globbing;
5143
5144         p = strpbrk(str, qchars);
5145         if (!p) {
5146                 return str;
5147         }
5148         q = p;
5149         r = str;
5150         if (flag & RMESCAPE_ALLOC) {
5151                 size_t len = p - str;
5152                 size_t fulllen = len + strlen(p) + 1;
5153
5154                 if (flag & RMESCAPE_GROW) {
5155                         r = makestrspace(fulllen, expdest);
5156                 } else if (flag & RMESCAPE_HEAP) {
5157                         r = ckmalloc(fulllen);
5158                 } else {
5159                         r = stalloc(fulllen);
5160                 }
5161                 q = r;
5162                 if (len > 0) {
5163                         q = (char *)memcpy(q, str, len) + len;
5164                 }
5165         }
5166         inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5167         globbing = flag & RMESCAPE_GLOB;
5168         notescaped = globbing;
5169         while (*p) {
5170                 if (*p == CTLQUOTEMARK) {
5171                         inquotes = ~inquotes;
5172                         p++;
5173                         notescaped = globbing;
5174                         continue;
5175                 }
5176                 if (*p == '\\') {
5177                         /* naked back slash */
5178                         notescaped = 0;
5179                         goto copy;
5180                 }
5181                 if (*p == CTLESC) {
5182                         p++;
5183                         if (notescaped && inquotes && *p != '/') {
5184                                 *q++ = '\\';
5185                         }
5186                 }
5187                 notescaped = globbing;
5188  copy:
5189                 *q++ = *p++;
5190         }
5191         *q = '\0';
5192         if (flag & RMESCAPE_GROW) {
5193                 expdest = r;
5194                 STADJUST(q - r + 1, expdest);
5195         }
5196         return r;
5197 }
5198 #define rmescapes(p) _rmescapes((p), 0)
5199
5200 #define pmatch(a, b) !fnmatch((a), (b), 0)
5201
5202 /*
5203  * Prepare a pattern for a expmeta (internal glob(3)) call.
5204  *
5205  * Returns an stalloced string.
5206  */
5207 static char *
5208 preglob(const char *pattern, int quoted, int flag)
5209 {
5210         flag |= RMESCAPE_GLOB;
5211         if (quoted) {
5212                 flag |= RMESCAPE_QUOTED;
5213         }
5214         return _rmescapes((char *)pattern, flag);
5215 }
5216
5217 /*
5218  * Put a string on the stack.
5219  */
5220 static void
5221 memtodest(const char *p, size_t len, int syntax, int quotes)
5222 {
5223         char *q = expdest;
5224
5225         q = makestrspace(len * 2, q);
5226
5227         while (len--) {
5228                 int c = signed_char2int(*p++);
5229                 if (!c)
5230                         continue;
5231                 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5232                         USTPUTC(CTLESC, q);
5233                 USTPUTC(c, q);
5234         }
5235
5236         expdest = q;
5237 }
5238
5239 static void
5240 strtodest(const char *p, int syntax, int quotes)
5241 {
5242         memtodest(p, strlen(p), syntax, quotes);
5243 }
5244
5245 /*
5246  * Record the fact that we have to scan this region of the
5247  * string for IFS characters.
5248  */
5249 static void
5250 recordregion(int start, int end, int nulonly)
5251 {
5252         struct ifsregion *ifsp;
5253
5254         if (ifslastp == NULL) {
5255                 ifsp = &ifsfirst;
5256         } else {
5257                 INT_OFF;
5258                 ifsp = ckzalloc(sizeof(*ifsp));
5259                 /*ifsp->next = NULL; - ckzalloc did it */
5260                 ifslastp->next = ifsp;
5261                 INT_ON;
5262         }
5263         ifslastp = ifsp;
5264         ifslastp->begoff = start;
5265         ifslastp->endoff = end;
5266         ifslastp->nulonly = nulonly;
5267 }
5268
5269 static void
5270 removerecordregions(int endoff)
5271 {
5272         if (ifslastp == NULL)
5273                 return;
5274
5275         if (ifsfirst.endoff > endoff) {
5276                 while (ifsfirst.next != NULL) {
5277                         struct ifsregion *ifsp;
5278                         INT_OFF;
5279                         ifsp = ifsfirst.next->next;
5280                         free(ifsfirst.next);
5281                         ifsfirst.next = ifsp;
5282                         INT_ON;
5283                 }
5284                 if (ifsfirst.begoff > endoff)
5285                         ifslastp = NULL;
5286                 else {
5287                         ifslastp = &ifsfirst;
5288                         ifsfirst.endoff = endoff;
5289                 }
5290                 return;
5291         }
5292
5293         ifslastp = &ifsfirst;
5294         while (ifslastp->next && ifslastp->next->begoff < endoff)
5295                 ifslastp=ifslastp->next;
5296         while (ifslastp->next != NULL) {
5297                 struct ifsregion *ifsp;
5298                 INT_OFF;
5299                 ifsp = ifslastp->next->next;
5300                 free(ifslastp->next);
5301                 ifslastp->next = ifsp;
5302                 INT_ON;
5303         }
5304         if (ifslastp->endoff > endoff)
5305                 ifslastp->endoff = endoff;
5306 }
5307
5308 static char *
5309 exptilde(char *startp, char *p, int flag)
5310 {
5311         char c;
5312         char *name;
5313         struct passwd *pw;
5314         const char *home;
5315         int quotes = flag & (EXP_FULL | EXP_CASE);
5316         int startloc;
5317
5318         name = p + 1;
5319
5320         while ((c = *++p) != '\0') {
5321                 switch (c) {
5322                 case CTLESC:
5323                         return startp;
5324                 case CTLQUOTEMARK:
5325                         return startp;
5326                 case ':':
5327                         if (flag & EXP_VARTILDE)
5328                                 goto done;
5329                         break;
5330                 case '/':
5331                 case CTLENDVAR:
5332                         goto done;
5333                 }
5334         }
5335  done:
5336         *p = '\0';
5337         if (*name == '\0') {
5338                 home = lookupvar(homestr);
5339         } else {
5340                 pw = getpwnam(name);
5341                 if (pw == NULL)
5342                         goto lose;
5343                 home = pw->pw_dir;
5344         }
5345         if (!home || !*home)
5346                 goto lose;
5347         *p = c;
5348         startloc = expdest - (char *)stackblock();
5349         strtodest(home, SQSYNTAX, quotes);
5350         recordregion(startloc, expdest - (char *)stackblock(), 0);
5351         return p;
5352  lose:
5353         *p = c;
5354         return startp;
5355 }
5356
5357 /*
5358  * Execute a command inside back quotes.  If it's a builtin command, we
5359  * want to save its output in a block obtained from malloc.  Otherwise
5360  * we fork off a subprocess and get the output of the command via a pipe.
5361  * Should be called with interrupts off.
5362  */
5363 struct backcmd {                /* result of evalbackcmd */
5364         int fd;                 /* file descriptor to read from */
5365         int nleft;              /* number of chars in buffer */
5366         char *buf;              /* buffer */
5367         struct job *jp;         /* job structure for command */
5368 };
5369
5370 /* These forward decls are needed to use "eval" code for backticks handling: */
5371 static uint8_t back_exitstatus; /* exit status of backquoted command */
5372 #define EV_EXIT 01              /* exit after evaluating tree */
5373 static void evaltree(union node *, int);
5374
5375 static void
5376 evalbackcmd(union node *n, struct backcmd *result)
5377 {
5378         int saveherefd;
5379
5380         result->fd = -1;
5381         result->buf = NULL;
5382         result->nleft = 0;
5383         result->jp = NULL;
5384         if (n == NULL) {
5385                 goto out;
5386         }
5387
5388         saveherefd = herefd;
5389         herefd = -1;
5390
5391         {
5392                 int pip[2];
5393                 struct job *jp;
5394
5395                 if (pipe(pip) < 0)
5396                         ash_msg_and_raise_error("pipe call failed");
5397                 jp = makejob(/*n,*/ 1);
5398                 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5399                         FORCE_INT_ON;
5400                         close(pip[0]);
5401                         if (pip[1] != 1) {
5402                                 close(1);
5403                                 copyfd(pip[1], 1);
5404                                 close(pip[1]);
5405                         }
5406                         eflag = 0;
5407                         evaltree(n, EV_EXIT); /* actually evaltreenr... */
5408                         /* NOTREACHED */
5409                 }
5410                 close(pip[1]);
5411                 result->fd = pip[0];
5412                 result->jp = jp;
5413         }
5414         herefd = saveherefd;
5415  out:
5416         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5417                 result->fd, result->buf, result->nleft, result->jp));
5418 }
5419
5420 /*
5421  * Expand stuff in backwards quotes.
5422  */
5423 static void
5424 expbackq(union node *cmd, int quoted, int quotes)
5425 {
5426         struct backcmd in;
5427         int i;
5428         char buf[128];
5429         char *p;
5430         char *dest;
5431         int startloc;
5432         int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5433         struct stackmark smark;
5434
5435         INT_OFF;
5436         setstackmark(&smark);
5437         dest = expdest;
5438         startloc = dest - (char *)stackblock();
5439         grabstackstr(dest);
5440         evalbackcmd(cmd, &in);
5441         popstackmark(&smark);
5442
5443         p = in.buf;
5444         i = in.nleft;
5445         if (i == 0)
5446                 goto read;
5447         for (;;) {
5448                 memtodest(p, i, syntax, quotes);
5449  read:
5450                 if (in.fd < 0)
5451                         break;
5452                 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5453                 TRACE(("expbackq: read returns %d\n", i));
5454                 if (i <= 0)
5455                         break;
5456                 p = buf;
5457         }
5458
5459         free(in.buf);
5460         if (in.fd >= 0) {
5461                 close(in.fd);
5462                 back_exitstatus = waitforjob(in.jp);
5463         }
5464         INT_ON;
5465
5466         /* Eat all trailing newlines */
5467         dest = expdest;
5468         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5469                 STUNPUTC(dest);
5470         expdest = dest;
5471
5472         if (quoted == 0)
5473                 recordregion(startloc, dest - (char *)stackblock(), 0);
5474         TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5475                 (dest - (char *)stackblock()) - startloc,
5476                 (dest - (char *)stackblock()) - startloc,
5477                 stackblock() + startloc));
5478 }
5479
5480 #if ENABLE_ASH_MATH_SUPPORT
5481 /*
5482  * Expand arithmetic expression.  Backup to start of expression,
5483  * evaluate, place result in (backed up) result, adjust string position.
5484  */
5485 static void
5486 expari(int quotes)
5487 {
5488         char *p, *start;
5489         int begoff;
5490         int flag;
5491         int len;
5492
5493         /*      ifsfree(); */
5494
5495         /*
5496          * This routine is slightly over-complicated for
5497          * efficiency.  Next we scan backwards looking for the
5498          * start of arithmetic.
5499          */
5500         start = stackblock();
5501         p = expdest - 1;
5502         *p = '\0';
5503         p--;
5504         do {
5505                 int esc;
5506
5507                 while (*p != CTLARI) {
5508                         p--;
5509 #if DEBUG
5510                         if (p < start) {
5511                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5512                         }
5513 #endif
5514                 }
5515
5516                 esc = esclen(start, p);
5517                 if (!(esc % 2)) {
5518                         break;
5519                 }
5520
5521                 p -= esc + 1;
5522         } while (1);
5523
5524         begoff = p - start;
5525
5526         removerecordregions(begoff);
5527
5528         flag = p[1];
5529
5530         expdest = p;
5531
5532         if (quotes)
5533                 rmescapes(p + 2);
5534
5535         len = cvtnum(dash_arith(p + 2));
5536
5537         if (flag != '"')
5538                 recordregion(begoff, begoff + len, 0);
5539 }
5540 #endif
5541
5542 /* argstr needs it */
5543 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5544
5545 /*
5546  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
5547  * characters to allow for further processing.  Otherwise treat
5548  * $@ like $* since no splitting will be performed.
5549  *
5550  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5551  * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5552  * for correct expansion of "B=$A" word.
5553  */
5554 static void
5555 argstr(char *p, int flag, struct strlist *var_str_list)
5556 {
5557         static const char spclchars[] ALIGN1 = {
5558                 '=',
5559                 ':',
5560                 CTLQUOTEMARK,
5561                 CTLENDVAR,
5562                 CTLESC,
5563                 CTLVAR,
5564                 CTLBACKQ,
5565                 CTLBACKQ | CTLQUOTE,
5566 #if ENABLE_ASH_MATH_SUPPORT
5567                 CTLENDARI,
5568 #endif
5569                 0
5570         };
5571         const char *reject = spclchars;
5572         int c;
5573         int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
5574         int breakall = flag & EXP_WORD;
5575         int inquotes;
5576         size_t length;
5577         int startloc;
5578
5579         if (!(flag & EXP_VARTILDE)) {
5580                 reject += 2;
5581         } else if (flag & EXP_VARTILDE2) {
5582                 reject++;
5583         }
5584         inquotes = 0;
5585         length = 0;
5586         if (flag & EXP_TILDE) {
5587                 char *q;
5588
5589                 flag &= ~EXP_TILDE;
5590  tilde:
5591                 q = p;
5592                 if (*q == CTLESC && (flag & EXP_QWORD))
5593                         q++;
5594                 if (*q == '~')
5595                         p = exptilde(p, q, flag);
5596         }
5597  start:
5598         startloc = expdest - (char *)stackblock();
5599         for (;;) {
5600                 length += strcspn(p + length, reject);
5601                 c = p[length];
5602                 if (c && (!(c & 0x80)
5603 #if ENABLE_ASH_MATH_SUPPORT
5604                                         || c == CTLENDARI
5605 #endif
5606                    )) {
5607                         /* c == '=' || c == ':' || c == CTLENDARI */
5608                         length++;
5609                 }
5610                 if (length > 0) {
5611                         int newloc;
5612                         expdest = stack_nputstr(p, length, expdest);
5613                         newloc = expdest - (char *)stackblock();
5614                         if (breakall && !inquotes && newloc > startloc) {
5615                                 recordregion(startloc, newloc, 0);
5616                         }
5617                         startloc = newloc;
5618                 }
5619                 p += length + 1;
5620                 length = 0;
5621
5622                 switch (c) {
5623                 case '\0':
5624                         goto breakloop;
5625                 case '=':
5626                         if (flag & EXP_VARTILDE2) {
5627                                 p--;
5628                                 continue;
5629                         }
5630                         flag |= EXP_VARTILDE2;
5631                         reject++;
5632                         /* fall through */
5633                 case ':':
5634                         /*
5635                          * sort of a hack - expand tildes in variable
5636                          * assignments (after the first '=' and after ':'s).
5637                          */
5638                         if (*--p == '~') {
5639                                 goto tilde;
5640                         }
5641                         continue;
5642                 }
5643
5644                 switch (c) {
5645                 case CTLENDVAR: /* ??? */
5646                         goto breakloop;
5647                 case CTLQUOTEMARK:
5648                         /* "$@" syntax adherence hack */
5649                         if (
5650                                 !inquotes &&
5651                                 !memcmp(p, dolatstr, 4) &&
5652                                 (p[4] == CTLQUOTEMARK || (
5653                                         p[4] == CTLENDVAR &&
5654                                         p[5] == CTLQUOTEMARK
5655                                 ))
5656                         ) {
5657                                 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5658                                 goto start;
5659                         }
5660                         inquotes = !inquotes;
5661  addquote:
5662                         if (quotes) {
5663                                 p--;
5664                                 length++;
5665                                 startloc++;
5666                         }
5667                         break;
5668                 case CTLESC:
5669                         startloc++;
5670                         length++;
5671                         goto addquote;
5672                 case CTLVAR:
5673                         p = evalvar(p, flag, var_str_list);
5674                         goto start;
5675                 case CTLBACKQ:
5676                         c = 0;
5677                 case CTLBACKQ|CTLQUOTE:
5678                         expbackq(argbackq->n, c, quotes);
5679                         argbackq = argbackq->next;
5680                         goto start;
5681 #if ENABLE_ASH_MATH_SUPPORT
5682                 case CTLENDARI:
5683                         p--;
5684                         expari(quotes);
5685                         goto start;
5686 #endif
5687                 }
5688         }
5689  breakloop:
5690         ;
5691 }
5692
5693 static char *
5694 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5695         int zero)
5696 {
5697 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5698 // as part of a larger change when he added support for ${var/a/b}.
5699 // However, it broke # and % operators:
5700 //
5701 //var=ababcdcd
5702 //                 ok       bad
5703 //echo ${var#ab}   abcdcd   abcdcd
5704 //echo ${var##ab}  abcdcd   abcdcd
5705 //echo ${var#a*b}  abcdcd   ababcdcd  (!)
5706 //echo ${var##a*b} cdcd     cdcd
5707 //echo ${var#?}    babcdcd  ababcdcd  (!)
5708 //echo ${var##?}   babcdcd  babcdcd
5709 //echo ${var#*}    ababcdcd babcdcd   (!)
5710 //echo ${var##*}
5711 //echo ${var%cd}   ababcd   ababcd
5712 //echo ${var%%cd}  ababcd   abab      (!)
5713 //echo ${var%c*d}  ababcd   ababcd
5714 //echo ${var%%c*d} abab     ababcdcd  (!)
5715 //echo ${var%?}    ababcdc  ababcdc
5716 //echo ${var%%?}   ababcdc  ababcdcd  (!)
5717 //echo ${var%*}    ababcdcd ababcdcd
5718 //echo ${var%%*}
5719 //
5720 // Commenting it back out helped. Remove it completely if it really
5721 // is not needed.
5722
5723         char *loc, *loc2; //, *full;
5724         char c;
5725
5726         loc = startp;
5727         loc2 = rmesc;
5728         do {
5729                 int match; // = strlen(str);
5730                 const char *s = loc2;
5731
5732                 c = *loc2;
5733                 if (zero) {
5734                         *loc2 = '\0';
5735                         s = rmesc;
5736                 }
5737                 match = pmatch(str, s); // this line was deleted
5738
5739 //              // chop off end if its '*'
5740 //              full = strrchr(str, '*');
5741 //              if (full && full != str)
5742 //                      match--;
5743 //
5744 //              // If str starts with '*' replace with s.
5745 //              if ((*str == '*') && strlen(s) >= match) {
5746 //                      full = xstrdup(s);
5747 //                      strncpy(full+strlen(s)-match+1, str+1, match-1);
5748 //              } else
5749 //                      full = xstrndup(str, match);
5750 //              match = strncmp(s, full, strlen(full));
5751 //              free(full);
5752 //
5753                 *loc2 = c;
5754                 if (match) // if (!match)
5755                         return loc;
5756                 if (quotes && *loc == CTLESC)
5757                         loc++;
5758                 loc++;
5759                 loc2++;
5760         } while (c);
5761         return 0;
5762 }
5763
5764 static char *
5765 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5766         int zero)
5767 {
5768         int esc = 0;
5769         char *loc;
5770         char *loc2;
5771
5772         for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5773                 int match;
5774                 char c = *loc2;
5775                 const char *s = loc2;
5776                 if (zero) {
5777                         *loc2 = '\0';
5778                         s = rmesc;
5779                 }
5780                 match = pmatch(str, s);
5781                 *loc2 = c;
5782                 if (match)
5783                         return loc;
5784                 loc--;
5785                 if (quotes) {
5786                         if (--esc < 0) {
5787                                 esc = esclen(startp, loc);
5788                         }
5789                         if (esc % 2) {
5790                                 esc--;
5791                                 loc--;
5792                         }
5793                 }
5794         }
5795         return 0;
5796 }
5797
5798 static void varunset(const char *, const char *, const char *, int) NORETURN;
5799 static void
5800 varunset(const char *end, const char *var, const char *umsg, int varflags)
5801 {
5802         const char *msg;
5803         const char *tail;
5804
5805         tail = nullstr;
5806         msg = "parameter not set";
5807         if (umsg) {
5808                 if (*end == CTLENDVAR) {
5809                         if (varflags & VSNUL)
5810                                 tail = " or null";
5811                 } else
5812                         msg = umsg;
5813         }
5814         ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5815 }
5816
5817 #if ENABLE_ASH_BASH_COMPAT
5818 static char *
5819 parse_sub_pattern(char *arg, int inquotes)
5820 {
5821         char *idx, *repl = NULL;
5822         unsigned char c;
5823
5824         idx = arg;
5825         while (1) {
5826                 c = *arg;
5827                 if (!c)
5828                         break;
5829                 if (c == '/') {
5830                         /* Only the first '/' seen is our separator */
5831                         if (!repl) {
5832                                 repl = idx + 1;
5833                                 c = '\0';
5834                         }
5835                 }
5836                 *idx++ = c;
5837                 if (!inquotes && c == '\\' && arg[1] == '\\')
5838                         arg++; /* skip both \\, not just first one */
5839                 arg++;
5840         }
5841         *idx = c; /* NUL */
5842
5843         return repl;
5844 }
5845 #endif /* ENABLE_ASH_BASH_COMPAT */
5846
5847 static const char *
5848 subevalvar(char *p, char *str, int strloc, int subtype,
5849                 int startloc, int varflags, int quotes, struct strlist *var_str_list)
5850 {
5851         struct nodelist *saveargbackq = argbackq;
5852         char *startp;
5853         char *loc;
5854         char *rmesc, *rmescend;
5855         USE_ASH_BASH_COMPAT(char *repl = NULL;)
5856         USE_ASH_BASH_COMPAT(char null = '\0';)
5857         USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
5858         int saveherefd = herefd;
5859         int amount, workloc, resetloc;
5860         int zero;
5861         char *(*scan)(char*, char*, char*, char*, int, int);
5862
5863         herefd = -1;
5864         argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
5865                         var_str_list);
5866         STPUTC('\0', expdest);
5867         herefd = saveherefd;
5868         argbackq = saveargbackq;
5869         startp = (char *)stackblock() + startloc;
5870
5871         switch (subtype) {
5872         case VSASSIGN:
5873                 setvar(str, startp, 0);
5874                 amount = startp - expdest;
5875                 STADJUST(amount, expdest);
5876                 return startp;
5877
5878 #if ENABLE_ASH_BASH_COMPAT
5879         case VSSUBSTR:
5880                 loc = str = stackblock() + strloc;
5881 // TODO: number() instead? It does error checking...
5882                 pos = atoi(loc);
5883                 len = str - startp - 1;
5884
5885                 /* *loc != '\0', guaranteed by parser */
5886                 if (quotes) {
5887                         char *ptr;
5888
5889                         /* We must adjust the length by the number of escapes we find. */
5890                         for (ptr = startp; ptr < (str - 1); ptr++) {
5891                                 if(*ptr == CTLESC) {
5892                                         len--;
5893                                         ptr++;
5894                                 }
5895                         }
5896                 }
5897                 orig_len = len;
5898
5899                 if (*loc++ == ':') {
5900 // TODO: number() instead? It does error checking...
5901                         len = atoi(loc);
5902                 } else {
5903                         len = orig_len;
5904                         while (*loc && *loc != ':')
5905                                 loc++;
5906                         if (*loc++ == ':')
5907 // TODO: number() instead? It does error checking...
5908                                 len = atoi(loc);
5909                 }
5910                 if (pos >= orig_len) {
5911                         pos = 0;
5912                         len = 0;
5913                 }
5914                 if (len > (orig_len - pos))
5915                         len = orig_len - pos;
5916
5917                 for (str = startp; pos; str++, pos--) {
5918                         if (quotes && *str == CTLESC)
5919                                 str++;
5920                 }
5921                 for (loc = startp; len; len--) {
5922                         if (quotes && *str == CTLESC)
5923                                 *loc++ = *str++;
5924                         *loc++ = *str++;
5925                 }
5926                 *loc = '\0';
5927                 amount = loc - expdest;
5928                 STADJUST(amount, expdest);
5929                 return loc;
5930 #endif
5931
5932         case VSQUESTION:
5933                 varunset(p, str, startp, varflags);
5934                 /* NOTREACHED */
5935         }
5936         resetloc = expdest - (char *)stackblock();
5937
5938         /* We'll comeback here if we grow the stack while handling
5939          * a VSREPLACE or VSREPLACEALL, since our pointers into the
5940          * stack will need rebasing, and we'll need to remove our work
5941          * areas each time
5942          */
5943  USE_ASH_BASH_COMPAT(restart:)
5944
5945         amount = expdest - ((char *)stackblock() + resetloc);
5946         STADJUST(-amount, expdest);
5947         startp = (char *)stackblock() + startloc;
5948
5949         rmesc = startp;
5950         rmescend = (char *)stackblock() + strloc;
5951         if (quotes) {
5952                 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5953                 if (rmesc != startp) {
5954                         rmescend = expdest;
5955                         startp = (char *)stackblock() + startloc;
5956                 }
5957         }
5958         rmescend--;
5959         str = (char *)stackblock() + strloc;
5960         preglob(str, varflags & VSQUOTE, 0);
5961         workloc = expdest - (char *)stackblock();
5962
5963 #if ENABLE_ASH_BASH_COMPAT
5964         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
5965                 char *idx, *end, *restart_detect;
5966
5967                 if(!repl) {
5968                         repl = parse_sub_pattern(str, varflags & VSQUOTE);
5969                         if (!repl)
5970                                 repl = &null;
5971                 }
5972
5973                 /* If there's no pattern to match, return the expansion unmolested */
5974                 if (*str == '\0')
5975                         return 0;
5976
5977                 len = 0;
5978                 idx = startp;
5979                 end = str - 1;
5980                 while (idx < end) {
5981                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
5982                         if (!loc) {
5983                                 /* No match, advance */
5984                                 restart_detect = stackblock();
5985                                 STPUTC(*idx, expdest);
5986                                 if (quotes && *idx == CTLESC) {
5987                                         idx++;
5988                                         len++;
5989                                         STPUTC(*idx, expdest);
5990                                 }
5991                                 if (stackblock() != restart_detect)
5992                                         goto restart;
5993                                 idx++;
5994                                 len++;
5995                                 rmesc++;
5996                                 continue;
5997                         }
5998
5999                         if (subtype == VSREPLACEALL) {
6000                                 while (idx < loc) {
6001                                         if (quotes && *idx == CTLESC)
6002                                                 idx++;
6003                                         idx++;
6004                                         rmesc++;
6005                                 }
6006                         } else
6007                                 idx = loc;
6008
6009                         for (loc = repl; *loc; loc++) {
6010                                 restart_detect = stackblock();
6011                                 STPUTC(*loc, expdest);
6012                                 if (stackblock() != restart_detect)
6013                                         goto restart;
6014                                 len++;
6015                         }
6016
6017                         if (subtype == VSREPLACE) {
6018                                 while (*idx) {
6019                                         restart_detect = stackblock();
6020                                         STPUTC(*idx, expdest);
6021                                         if (stackblock() != restart_detect)
6022                                                 goto restart;
6023                                         len++;
6024                                         idx++;
6025                                 }
6026                                 break;
6027                         }
6028                 }
6029
6030                 /* We've put the replaced text into a buffer at workloc, now
6031                  * move it to the right place and adjust the stack.
6032                  */
6033                 startp = stackblock() + startloc;
6034                 STPUTC('\0', expdest);
6035                 memmove(startp, stackblock() + workloc, len);
6036                 startp[len++] = '\0';
6037                 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6038                 STADJUST(-amount, expdest);
6039                 return startp;
6040         }
6041 #endif /* ENABLE_ASH_BASH_COMPAT */
6042
6043         subtype -= VSTRIMRIGHT;
6044 #if DEBUG
6045         if (subtype < 0 || subtype > 7)
6046                 abort();
6047 #endif
6048         /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6049         zero = subtype >> 1;
6050         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6051         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6052
6053         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6054         if (loc) {
6055                 if (zero) {
6056                         memmove(startp, loc, str - loc);
6057                         loc = startp + (str - loc) - 1;
6058                 }
6059                 *loc = '\0';
6060                 amount = loc - expdest;
6061                 STADJUST(amount, expdest);
6062         }
6063         return loc;
6064 }
6065
6066 /*
6067  * Add the value of a specialized variable to the stack string.
6068  */
6069 static ssize_t
6070 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6071 {
6072         int num;
6073         char *p;
6074         int i;
6075         int sep = 0;
6076         int sepq = 0;
6077         ssize_t len = 0;
6078         char **ap;
6079         int syntax;
6080         int quoted = varflags & VSQUOTE;
6081         int subtype = varflags & VSTYPE;
6082         int quotes = flags & (EXP_FULL | EXP_CASE);
6083
6084         if (quoted && (flags & EXP_FULL))
6085                 sep = 1 << CHAR_BIT;
6086
6087         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6088         switch (*name) {
6089         case '$':
6090                 num = rootpid;
6091                 goto numvar;
6092         case '?':
6093                 num = exitstatus;
6094                 goto numvar;
6095         case '#':
6096                 num = shellparam.nparam;
6097                 goto numvar;
6098         case '!':
6099                 num = backgndpid;
6100                 if (num == 0)
6101                         return -1;
6102  numvar:
6103                 len = cvtnum(num);
6104                 break;
6105         case '-':
6106                 p = makestrspace(NOPTS, expdest);
6107                 for (i = NOPTS - 1; i >= 0; i--) {
6108                         if (optlist[i]) {
6109                                 USTPUTC(optletters(i), p);
6110                                 len++;
6111                         }
6112                 }
6113                 expdest = p;
6114                 break;
6115         case '@':
6116                 if (sep)
6117                         goto param;
6118                 /* fall through */
6119         case '*':
6120                 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6121                 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6122                         sepq = 1;
6123  param:
6124                 ap = shellparam.p;
6125                 if (!ap)
6126                         return -1;
6127                 while ((p = *ap++)) {
6128                         size_t partlen;
6129
6130                         partlen = strlen(p);
6131                         len += partlen;
6132
6133                         if (!(subtype == VSPLUS || subtype == VSLENGTH))
6134                                 memtodest(p, partlen, syntax, quotes);
6135
6136                         if (*ap && sep) {
6137                                 char *q;
6138
6139                                 len++;
6140                                 if (subtype == VSPLUS || subtype == VSLENGTH) {
6141                                         continue;
6142                                 }
6143                                 q = expdest;
6144                                 if (sepq)
6145                                         STPUTC(CTLESC, q);
6146                                 STPUTC(sep, q);
6147                                 expdest = q;
6148                         }
6149                 }
6150                 return len;
6151         case '0':
6152         case '1':
6153         case '2':
6154         case '3':
6155         case '4':
6156         case '5':
6157         case '6':
6158         case '7':
6159         case '8':
6160         case '9':
6161 // TODO: number() instead? It does error checking...
6162                 num = atoi(name);
6163                 if (num < 0 || num > shellparam.nparam)
6164                         return -1;
6165                 p = num ? shellparam.p[num - 1] : arg0;
6166                 goto value;
6167         default:
6168                 /* NB: name has form "VAR=..." */
6169
6170                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6171                  * which should be considered before we check variables. */
6172                 if (var_str_list) {
6173                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6174                         p = NULL;
6175                         do {
6176                                 char *str, *eq;
6177                                 str = var_str_list->text;
6178                                 eq = strchr(str, '=');
6179                                 if (!eq) /* stop at first non-assignment */
6180                                         break;
6181                                 eq++;
6182                                 if (name_len == (unsigned)(eq - str)
6183                                  && strncmp(str, name, name_len) == 0) {
6184                                         p = eq;
6185                                         /* goto value; - WRONG! */
6186                                         /* think "A=1 A=2 B=$A" */
6187                                 }
6188                                 var_str_list = var_str_list->next;
6189                         } while (var_str_list);
6190                         if (p)
6191                                 goto value;
6192                 }
6193                 p = lookupvar(name);
6194  value:
6195                 if (!p)
6196                         return -1;
6197
6198                 len = strlen(p);
6199                 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6200                         memtodest(p, len, syntax, quotes);
6201                 return len;
6202         }
6203
6204         if (subtype == VSPLUS || subtype == VSLENGTH)
6205                 STADJUST(-len, expdest);
6206         return len;
6207 }
6208
6209 /*
6210  * Expand a variable, and return a pointer to the next character in the
6211  * input string.
6212  */
6213 static char *
6214 evalvar(char *p, int flag, struct strlist *var_str_list)
6215 {
6216         char varflags;
6217         char subtype;
6218         char quoted;
6219         char easy;
6220         char *var;
6221         int patloc;
6222         int startloc;
6223         ssize_t varlen;
6224
6225         varflags = *p++;
6226         subtype = varflags & VSTYPE;
6227         quoted = varflags & VSQUOTE;
6228         var = p;
6229         easy = (!quoted || (*var == '@' && shellparam.nparam));
6230         startloc = expdest - (char *)stackblock();
6231         p = strchr(p, '=') + 1;
6232
6233  again:
6234         varlen = varvalue(var, varflags, flag, var_str_list);
6235         if (varflags & VSNUL)
6236                 varlen--;
6237
6238         if (subtype == VSPLUS) {
6239                 varlen = -1 - varlen;
6240                 goto vsplus;
6241         }
6242
6243         if (subtype == VSMINUS) {
6244  vsplus:
6245                 if (varlen < 0) {
6246                         argstr(
6247                                 p, flag | EXP_TILDE |
6248                                         (quoted ?  EXP_QWORD : EXP_WORD),
6249                                 var_str_list
6250                         );
6251                         goto end;
6252                 }
6253                 if (easy)
6254                         goto record;
6255                 goto end;
6256         }
6257
6258         if (subtype == VSASSIGN || subtype == VSQUESTION) {
6259                 if (varlen < 0) {
6260                         if (subevalvar(p, var, /* strloc: */ 0,
6261                                         subtype, startloc, varflags,
6262                                         /* quotes: */ 0,
6263                                         var_str_list)
6264                         ) {
6265                                 varflags &= ~VSNUL;
6266                                 /*
6267                                  * Remove any recorded regions beyond
6268                                  * start of variable
6269                                  */
6270                                 removerecordregions(startloc);
6271                                 goto again;
6272                         }
6273                         goto end;
6274                 }
6275                 if (easy)
6276                         goto record;
6277                 goto end;
6278         }
6279
6280         if (varlen < 0 && uflag)
6281                 varunset(p, var, 0, 0);
6282
6283         if (subtype == VSLENGTH) {
6284                 cvtnum(varlen > 0 ? varlen : 0);
6285                 goto record;
6286         }
6287
6288         if (subtype == VSNORMAL) {
6289                 if (easy)
6290                         goto record;
6291                 goto end;
6292         }
6293
6294 #if DEBUG
6295         switch (subtype) {
6296         case VSTRIMLEFT:
6297         case VSTRIMLEFTMAX:
6298         case VSTRIMRIGHT:
6299         case VSTRIMRIGHTMAX:
6300 #if ENABLE_ASH_BASH_COMPAT
6301         case VSSUBSTR:
6302         case VSREPLACE:
6303         case VSREPLACEALL:
6304 #endif
6305                 break;
6306         default:
6307                 abort();
6308         }
6309 #endif
6310
6311         if (varlen >= 0) {
6312                 /*
6313                  * Terminate the string and start recording the pattern
6314                  * right after it
6315                  */
6316                 STPUTC('\0', expdest);
6317                 patloc = expdest - (char *)stackblock();
6318                 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6319                                 startloc, varflags,
6320                                 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6321                                 var_str_list)
6322                 ) {
6323                         int amount = expdest - (
6324                                 (char *)stackblock() + patloc - 1
6325                         );
6326                         STADJUST(-amount, expdest);
6327                 }
6328                 /* Remove any recorded regions beyond start of variable */
6329                 removerecordregions(startloc);
6330  record:
6331                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6332         }
6333
6334  end:
6335         if (subtype != VSNORMAL) {      /* skip to end of alternative */
6336                 int nesting = 1;
6337                 for (;;) {
6338                         char c = *p++;
6339                         if (c == CTLESC)
6340                                 p++;
6341                         else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6342                                 if (varlen >= 0)
6343                                         argbackq = argbackq->next;
6344                         } else if (c == CTLVAR) {
6345                                 if ((*p++ & VSTYPE) != VSNORMAL)
6346                                         nesting++;
6347                         } else if (c == CTLENDVAR) {
6348                                 if (--nesting == 0)
6349                                         break;
6350                         }
6351                 }
6352         }
6353         return p;
6354 }
6355
6356 /*
6357  * Break the argument string into pieces based upon IFS and add the
6358  * strings to the argument list.  The regions of the string to be
6359  * searched for IFS characters have been stored by recordregion.
6360  */
6361 static void
6362 ifsbreakup(char *string, struct arglist *arglist)
6363 {
6364         struct ifsregion *ifsp;
6365         struct strlist *sp;
6366         char *start;
6367         char *p;
6368         char *q;
6369         const char *ifs, *realifs;
6370         int ifsspc;
6371         int nulonly;
6372
6373         start = string;
6374         if (ifslastp != NULL) {
6375                 ifsspc = 0;
6376                 nulonly = 0;
6377                 realifs = ifsset() ? ifsval() : defifs;
6378                 ifsp = &ifsfirst;
6379                 do {
6380                         p = string + ifsp->begoff;
6381                         nulonly = ifsp->nulonly;
6382                         ifs = nulonly ? nullstr : realifs;
6383                         ifsspc = 0;
6384                         while (p < string + ifsp->endoff) {
6385                                 q = p;
6386                                 if (*p == CTLESC)
6387                                         p++;
6388                                 if (!strchr(ifs, *p)) {
6389                                         p++;
6390                                         continue;
6391                                 }
6392                                 if (!nulonly)
6393                                         ifsspc = (strchr(defifs, *p) != NULL);
6394                                 /* Ignore IFS whitespace at start */
6395                                 if (q == start && ifsspc) {
6396                                         p++;
6397                                         start = p;
6398                                         continue;
6399                                 }
6400                                 *q = '\0';
6401                                 sp = stzalloc(sizeof(*sp));
6402                                 sp->text = start;
6403                                 *arglist->lastp = sp;
6404                                 arglist->lastp = &sp->next;
6405                                 p++;
6406                                 if (!nulonly) {
6407                                         for (;;) {
6408                                                 if (p >= string + ifsp->endoff) {
6409                                                         break;
6410                                                 }
6411                                                 q = p;
6412                                                 if (*p == CTLESC)
6413                                                         p++;
6414                                                 if (strchr(ifs, *p) == NULL) {
6415                                                         p = q;
6416                                                         break;
6417                                                 }
6418                                                 if (strchr(defifs, *p) == NULL) {
6419                                                         if (ifsspc) {
6420                                                                 p++;
6421                                                                 ifsspc = 0;
6422                                                         } else {
6423                                                                 p = q;
6424                                                                 break;
6425                                                         }
6426                                                 } else
6427                                                         p++;
6428                                         }
6429                                 }
6430                                 start = p;
6431                         } /* while */
6432                         ifsp = ifsp->next;
6433                 } while (ifsp != NULL);
6434                 if (nulonly)
6435                         goto add;
6436         }
6437
6438         if (!*start)
6439                 return;
6440
6441  add:
6442         sp = stzalloc(sizeof(*sp));
6443         sp->text = start;
6444         *arglist->lastp = sp;
6445         arglist->lastp = &sp->next;
6446 }
6447
6448 static void
6449 ifsfree(void)
6450 {
6451         struct ifsregion *p;
6452
6453         INT_OFF;
6454         p = ifsfirst.next;
6455         do {
6456                 struct ifsregion *ifsp;
6457                 ifsp = p->next;
6458                 free(p);
6459                 p = ifsp;
6460         } while (p);
6461         ifslastp = NULL;
6462         ifsfirst.next = NULL;
6463         INT_ON;
6464 }
6465
6466 /*
6467  * Add a file name to the list.
6468  */
6469 static void
6470 addfname(const char *name)
6471 {
6472         struct strlist *sp;
6473
6474         sp = stzalloc(sizeof(*sp));
6475         sp->text = ststrdup(name);
6476         *exparg.lastp = sp;
6477         exparg.lastp = &sp->next;
6478 }
6479
6480 static char *expdir;
6481
6482 /*
6483  * Do metacharacter (i.e. *, ?, [...]) expansion.
6484  */
6485 static void
6486 expmeta(char *enddir, char *name)
6487 {
6488         char *p;
6489         const char *cp;
6490         char *start;
6491         char *endname;
6492         int metaflag;
6493         struct stat statb;
6494         DIR *dirp;
6495         struct dirent *dp;
6496         int atend;
6497         int matchdot;
6498
6499         metaflag = 0;
6500         start = name;
6501         for (p = name; *p; p++) {
6502                 if (*p == '*' || *p == '?')
6503                         metaflag = 1;
6504                 else if (*p == '[') {
6505                         char *q = p + 1;
6506                         if (*q == '!')
6507                                 q++;
6508                         for (;;) {
6509                                 if (*q == '\\')
6510                                         q++;
6511                                 if (*q == '/' || *q == '\0')
6512                                         break;
6513                                 if (*++q == ']') {
6514                                         metaflag = 1;
6515                                         break;
6516                                 }
6517                         }
6518                 } else if (*p == '\\')
6519                         p++;
6520                 else if (*p == '/') {
6521                         if (metaflag)
6522                                 goto out;
6523                         start = p + 1;
6524                 }
6525         }
6526  out:
6527         if (metaflag == 0) {    /* we've reached the end of the file name */
6528                 if (enddir != expdir)
6529                         metaflag++;
6530                 p = name;
6531                 do {
6532                         if (*p == '\\')
6533                                 p++;
6534                         *enddir++ = *p;
6535                 } while (*p++);
6536                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6537                         addfname(expdir);
6538                 return;
6539         }
6540         endname = p;
6541         if (name < start) {
6542                 p = name;
6543                 do {
6544                         if (*p == '\\')
6545                                 p++;
6546                         *enddir++ = *p++;
6547                 } while (p < start);
6548         }
6549         if (enddir == expdir) {
6550                 cp = ".";
6551         } else if (enddir == expdir + 1 && *expdir == '/') {
6552                 cp = "/";
6553         } else {
6554                 cp = expdir;
6555                 enddir[-1] = '\0';
6556         }
6557         dirp = opendir(cp);
6558         if (dirp == NULL)
6559                 return;
6560         if (enddir != expdir)
6561                 enddir[-1] = '/';
6562         if (*endname == 0) {
6563                 atend = 1;
6564         } else {
6565                 atend = 0;
6566                 *endname++ = '\0';
6567         }
6568         matchdot = 0;
6569         p = start;
6570         if (*p == '\\')
6571                 p++;
6572         if (*p == '.')
6573                 matchdot++;
6574         while (!intpending && (dp = readdir(dirp)) != NULL) {
6575                 if (dp->d_name[0] == '.' && ! matchdot)
6576                         continue;
6577                 if (pmatch(start, dp->d_name)) {
6578                         if (atend) {
6579                                 strcpy(enddir, dp->d_name);
6580                                 addfname(expdir);
6581                         } else {
6582                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6583                                         continue;
6584                                 p[-1] = '/';
6585                                 expmeta(p, endname);
6586                         }
6587                 }
6588         }
6589         closedir(dirp);
6590         if (! atend)
6591                 endname[-1] = '/';
6592 }
6593
6594 static struct strlist *
6595 msort(struct strlist *list, int len)
6596 {
6597         struct strlist *p, *q = NULL;
6598         struct strlist **lpp;
6599         int half;
6600         int n;
6601
6602         if (len <= 1)
6603                 return list;
6604         half = len >> 1;
6605         p = list;
6606         for (n = half; --n >= 0;) {
6607                 q = p;
6608                 p = p->next;
6609         }
6610         q->next = NULL;                 /* terminate first half of list */
6611         q = msort(list, half);          /* sort first half of list */
6612         p = msort(p, len - half);               /* sort second half */
6613         lpp = &list;
6614         for (;;) {
6615 #if ENABLE_LOCALE_SUPPORT
6616                 if (strcoll(p->text, q->text) < 0)
6617 #else
6618                 if (strcmp(p->text, q->text) < 0)
6619 #endif
6620                                                 {
6621                         *lpp = p;
6622                         lpp = &p->next;
6623                         p = *lpp;
6624                         if (p == NULL) {
6625                                 *lpp = q;
6626                                 break;
6627                         }
6628                 } else {
6629                         *lpp = q;
6630                         lpp = &q->next;
6631                         q = *lpp;
6632                         if (q == NULL) {
6633                                 *lpp = p;
6634                                 break;
6635                         }
6636                 }
6637         }
6638         return list;
6639 }
6640
6641 /*
6642  * Sort the results of file name expansion.  It calculates the number of
6643  * strings to sort and then calls msort (short for merge sort) to do the
6644  * work.
6645  */
6646 static struct strlist *
6647 expsort(struct strlist *str)
6648 {
6649         int len;
6650         struct strlist *sp;
6651
6652         len = 0;
6653         for (sp = str; sp; sp = sp->next)
6654                 len++;
6655         return msort(str, len);
6656 }
6657
6658 static void
6659 expandmeta(struct strlist *str /*, int flag*/)
6660 {
6661         static const char metachars[] ALIGN1 = {
6662                 '*', '?', '[', 0
6663         };
6664         /* TODO - EXP_REDIR */
6665
6666         while (str) {
6667                 struct strlist **savelastp;
6668                 struct strlist *sp;
6669                 char *p;
6670
6671                 if (fflag)
6672                         goto nometa;
6673                 if (!strpbrk(str->text, metachars))
6674                         goto nometa;
6675                 savelastp = exparg.lastp;
6676
6677                 INT_OFF;
6678                 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6679                 {
6680                         int i = strlen(str->text);
6681                         expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6682                 }
6683
6684                 expmeta(expdir, p);
6685                 free(expdir);
6686                 if (p != str->text)
6687                         free(p);
6688                 INT_ON;
6689                 if (exparg.lastp == savelastp) {
6690                         /*
6691                          * no matches
6692                          */
6693  nometa:
6694                         *exparg.lastp = str;
6695                         rmescapes(str->text);
6696                         exparg.lastp = &str->next;
6697                 } else {
6698                         *exparg.lastp = NULL;
6699                         *savelastp = sp = expsort(*savelastp);
6700                         while (sp->next != NULL)
6701                                 sp = sp->next;
6702                         exparg.lastp = &sp->next;
6703                 }
6704                 str = str->next;
6705         }
6706 }
6707
6708 /*
6709  * Perform variable substitution and command substitution on an argument,
6710  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
6711  * perform splitting and file name expansion.  When arglist is NULL, perform
6712  * here document expansion.
6713  */
6714 static void
6715 expandarg(union node *arg, struct arglist *arglist, int flag)
6716 {
6717         struct strlist *sp;
6718         char *p;
6719
6720         argbackq = arg->narg.backquote;
6721         STARTSTACKSTR(expdest);
6722         ifsfirst.next = NULL;
6723         ifslastp = NULL;
6724         argstr(arg->narg.text, flag,
6725                         /* var_str_list: */ arglist ? arglist->list : NULL);
6726         p = _STPUTC('\0', expdest);
6727         expdest = p - 1;
6728         if (arglist == NULL) {
6729                 return;                 /* here document expanded */
6730         }
6731         p = grabstackstr(p);
6732         exparg.lastp = &exparg.list;
6733         /*
6734          * TODO - EXP_REDIR
6735          */
6736         if (flag & EXP_FULL) {
6737                 ifsbreakup(p, &exparg);
6738                 *exparg.lastp = NULL;
6739                 exparg.lastp = &exparg.list;
6740                 expandmeta(exparg.list /*, flag*/);
6741         } else {
6742                 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6743                         rmescapes(p);
6744                 sp = stzalloc(sizeof(*sp));
6745                 sp->text = p;
6746                 *exparg.lastp = sp;
6747                 exparg.lastp = &sp->next;
6748         }
6749         if (ifsfirst.next)
6750                 ifsfree();
6751         *exparg.lastp = NULL;
6752         if (exparg.list) {
6753                 *arglist->lastp = exparg.list;
6754                 arglist->lastp = exparg.lastp;
6755         }
6756 }
6757
6758 /*
6759  * Expand shell variables and backquotes inside a here document.
6760  */
6761 static void
6762 expandhere(union node *arg, int fd)
6763 {
6764         herefd = fd;
6765         expandarg(arg, (struct arglist *)NULL, 0);
6766         full_write(fd, stackblock(), expdest - (char *)stackblock());
6767 }
6768
6769 /*
6770  * Returns true if the pattern matches the string.
6771  */
6772 static int
6773 patmatch(char *pattern, const char *string)
6774 {
6775         return pmatch(preglob(pattern, 0, 0), string);
6776 }
6777
6778 /*
6779  * See if a pattern matches in a case statement.
6780  */
6781 static int
6782 casematch(union node *pattern, char *val)
6783 {
6784         struct stackmark smark;
6785         int result;
6786
6787         setstackmark(&smark);
6788         argbackq = pattern->narg.backquote;
6789         STARTSTACKSTR(expdest);
6790         ifslastp = NULL;
6791         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6792                         /* var_str_list: */ NULL);
6793         STACKSTRNUL(expdest);
6794         result = patmatch(stackblock(), val);
6795         popstackmark(&smark);
6796         return result;
6797 }
6798
6799
6800 /* ============ find_command */
6801
6802 struct builtincmd {
6803         const char *name;
6804         int (*builtin)(int, char **);
6805         /* unsigned flags; */
6806 };
6807 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6808 /* "regular" builtins always take precedence over commands,
6809  * regardless of PATH=....%builtin... position */
6810 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6811 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
6812
6813 struct cmdentry {
6814         smallint cmdtype;       /* CMDxxx */
6815         union param {
6816                 int index;
6817                 /* index >= 0 for commands without path (slashes) */
6818                 /* (TODO: what exactly does the value mean? PATH position?) */
6819                 /* index == -1 for commands with slashes */
6820                 /* index == (-2 - applet_no) for NOFORK applets */
6821                 const struct builtincmd *cmd;
6822                 struct funcnode *func;
6823         } u;
6824 };
6825 /* values of cmdtype */
6826 #define CMDUNKNOWN      -1      /* no entry in table for command */
6827 #define CMDNORMAL       0       /* command is an executable program */
6828 #define CMDFUNCTION     1       /* command is a shell function */
6829 #define CMDBUILTIN      2       /* command is a shell builtin */
6830
6831 /* action to find_command() */
6832 #define DO_ERR          0x01    /* prints errors */
6833 #define DO_ABS          0x02    /* checks absolute paths */
6834 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
6835 #define DO_ALTPATH      0x08    /* using alternate path */
6836 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
6837
6838 static void find_command(char *, struct cmdentry *, int, const char *);
6839
6840
6841 /* ============ Hashing commands */
6842
6843 /*
6844  * When commands are first encountered, they are entered in a hash table.
6845  * This ensures that a full path search will not have to be done for them
6846  * on each invocation.
6847  *
6848  * We should investigate converting to a linear search, even though that
6849  * would make the command name "hash" a misnomer.
6850  */
6851
6852 struct tblentry {
6853         struct tblentry *next;  /* next entry in hash chain */
6854         union param param;      /* definition of builtin function */
6855         smallint cmdtype;       /* CMDxxx */
6856         char rehash;            /* if set, cd done since entry created */
6857         char cmdname[1];        /* name of command */
6858 };
6859
6860 static struct tblentry **cmdtable;
6861 #define INIT_G_cmdtable() do { \
6862         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
6863 } while (0)
6864
6865 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
6866
6867
6868 static void
6869 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
6870 {
6871         int repeated = 0;
6872
6873 #if ENABLE_FEATURE_SH_STANDALONE
6874         if (applet_no >= 0) {
6875                 if (APPLET_IS_NOEXEC(applet_no))
6876                         run_applet_no_and_exit(applet_no, argv);
6877                 /* re-exec ourselves with the new arguments */
6878                 execve(bb_busybox_exec_path, argv, envp);
6879                 /* If they called chroot or otherwise made the binary no longer
6880                  * executable, fall through */
6881         }
6882 #endif
6883
6884  repeat:
6885 #ifdef SYSV
6886         do {
6887                 execve(cmd, argv, envp);
6888         } while (errno == EINTR);
6889 #else
6890         execve(cmd, argv, envp);
6891 #endif
6892         if (repeated) {
6893                 free(argv);
6894                 return;
6895         }
6896         if (errno == ENOEXEC) {
6897                 char **ap;
6898                 char **new;
6899
6900                 for (ap = argv; *ap; ap++)
6901                         continue;
6902                 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
6903                 ap[1] = cmd;
6904                 ap[0] = cmd = (char *)DEFAULT_SHELL;
6905                 ap += 2;
6906                 argv++;
6907                 while ((*ap++ = *argv++) != NULL)
6908                         continue;
6909                 argv = new;
6910                 repeated++;
6911                 goto repeat;
6912         }
6913 }
6914
6915 /*
6916  * Exec a program.  Never returns.  If you change this routine, you may
6917  * have to change the find_command routine as well.
6918  */
6919 static void shellexec(char **, const char *, int) NORETURN;
6920 static void
6921 shellexec(char **argv, const char *path, int idx)
6922 {
6923         char *cmdname;
6924         int e;
6925         char **envp;
6926         int exerrno;
6927 #if ENABLE_FEATURE_SH_STANDALONE
6928         int applet_no = -1;
6929 #endif
6930
6931         clearredir(1);
6932         envp = listvars(VEXPORT, VUNSET, 0);
6933         if (strchr(argv[0], '/') != NULL
6934 #if ENABLE_FEATURE_SH_STANDALONE
6935          || (applet_no = find_applet_by_name(argv[0])) >= 0
6936 #endif
6937         ) {
6938                 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
6939                 e = errno;
6940         } else {
6941                 e = ENOENT;
6942                 while ((cmdname = padvance(&path, argv[0])) != NULL) {
6943                         if (--idx < 0 && pathopt == NULL) {
6944                                 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
6945                                 if (errno != ENOENT && errno != ENOTDIR)
6946                                         e = errno;
6947                         }
6948                         stunalloc(cmdname);
6949                 }
6950         }
6951
6952         /* Map to POSIX errors */
6953         switch (e) {
6954         case EACCES:
6955                 exerrno = 126;
6956                 break;
6957         case ENOENT:
6958                 exerrno = 127;
6959                 break;
6960         default:
6961                 exerrno = 2;
6962                 break;
6963         }
6964         exitstatus = exerrno;
6965         TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
6966                 argv[0], e, suppressint));
6967         ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
6968         /* NOTREACHED */
6969 }
6970
6971 static void
6972 printentry(struct tblentry *cmdp)
6973 {
6974         int idx;
6975         const char *path;
6976         char *name;
6977
6978         idx = cmdp->param.index;
6979         path = pathval();
6980         do {
6981                 name = padvance(&path, cmdp->cmdname);
6982                 stunalloc(name);
6983         } while (--idx >= 0);
6984         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
6985 }
6986
6987 /*
6988  * Clear out command entries.  The argument specifies the first entry in
6989  * PATH which has changed.
6990  */
6991 static void
6992 clearcmdentry(int firstchange)
6993 {
6994         struct tblentry **tblp;
6995         struct tblentry **pp;
6996         struct tblentry *cmdp;
6997
6998         INT_OFF;
6999         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7000                 pp = tblp;
7001                 while ((cmdp = *pp) != NULL) {
7002                         if ((cmdp->cmdtype == CMDNORMAL &&
7003                              cmdp->param.index >= firstchange)
7004                          || (cmdp->cmdtype == CMDBUILTIN &&
7005                              builtinloc >= firstchange)
7006                         ) {
7007                                 *pp = cmdp->next;
7008                                 free(cmdp);
7009                         } else {
7010                                 pp = &cmdp->next;
7011                         }
7012                 }
7013         }
7014         INT_ON;
7015 }
7016
7017 /*
7018  * Locate a command in the command hash table.  If "add" is nonzero,
7019  * add the command to the table if it is not already present.  The
7020  * variable "lastcmdentry" is set to point to the address of the link
7021  * pointing to the entry, so that delete_cmd_entry can delete the
7022  * entry.
7023  *
7024  * Interrupts must be off if called with add != 0.
7025  */
7026 static struct tblentry **lastcmdentry;
7027
7028 static struct tblentry *
7029 cmdlookup(const char *name, int add)
7030 {
7031         unsigned int hashval;
7032         const char *p;
7033         struct tblentry *cmdp;
7034         struct tblentry **pp;
7035
7036         p = name;
7037         hashval = (unsigned char)*p << 4;
7038         while (*p)
7039                 hashval += (unsigned char)*p++;
7040         hashval &= 0x7FFF;
7041         pp = &cmdtable[hashval % CMDTABLESIZE];
7042         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7043                 if (strcmp(cmdp->cmdname, name) == 0)
7044                         break;
7045                 pp = &cmdp->next;
7046         }
7047         if (add && cmdp == NULL) {
7048                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7049                                 + strlen(name)
7050                                 /* + 1 - already done because
7051                                  * tblentry::cmdname is char[1] */);
7052                 /*cmdp->next = NULL; - ckzalloc did it */
7053                 cmdp->cmdtype = CMDUNKNOWN;
7054                 strcpy(cmdp->cmdname, name);
7055         }
7056         lastcmdentry = pp;
7057         return cmdp;
7058 }
7059
7060 /*
7061  * Delete the command entry returned on the last lookup.
7062  */
7063 static void
7064 delete_cmd_entry(void)
7065 {
7066         struct tblentry *cmdp;
7067
7068         INT_OFF;
7069         cmdp = *lastcmdentry;
7070         *lastcmdentry = cmdp->next;
7071         if (cmdp->cmdtype == CMDFUNCTION)
7072                 freefunc(cmdp->param.func);
7073         free(cmdp);
7074         INT_ON;
7075 }
7076
7077 /*
7078  * Add a new command entry, replacing any existing command entry for
7079  * the same name - except special builtins.
7080  */
7081 static void
7082 addcmdentry(char *name, struct cmdentry *entry)
7083 {
7084         struct tblentry *cmdp;
7085
7086         cmdp = cmdlookup(name, 1);
7087         if (cmdp->cmdtype == CMDFUNCTION) {
7088                 freefunc(cmdp->param.func);
7089         }
7090         cmdp->cmdtype = entry->cmdtype;
7091         cmdp->param = entry->u;
7092         cmdp->rehash = 0;
7093 }
7094
7095 static int
7096 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7097 {
7098         struct tblentry **pp;
7099         struct tblentry *cmdp;
7100         int c;
7101         struct cmdentry entry;
7102         char *name;
7103
7104         if (nextopt("r") != '\0') {
7105                 clearcmdentry(0);
7106                 return 0;
7107         }
7108
7109         if (*argptr == NULL) {
7110                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7111                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7112                                 if (cmdp->cmdtype == CMDNORMAL)
7113                                         printentry(cmdp);
7114                         }
7115                 }
7116                 return 0;
7117         }
7118
7119         c = 0;
7120         while ((name = *argptr) != NULL) {
7121                 cmdp = cmdlookup(name, 0);
7122                 if (cmdp != NULL
7123                  && (cmdp->cmdtype == CMDNORMAL
7124                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7125                 ) {
7126                         delete_cmd_entry();
7127                 }
7128                 find_command(name, &entry, DO_ERR, pathval());
7129                 if (entry.cmdtype == CMDUNKNOWN)
7130                         c = 1;
7131                 argptr++;
7132         }
7133         return c;
7134 }
7135
7136 /*
7137  * Called when a cd is done.  Marks all commands so the next time they
7138  * are executed they will be rehashed.
7139  */
7140 static void
7141 hashcd(void)
7142 {
7143         struct tblentry **pp;
7144         struct tblentry *cmdp;
7145
7146         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7147                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7148                         if (cmdp->cmdtype == CMDNORMAL
7149                          || (cmdp->cmdtype == CMDBUILTIN
7150                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7151                              && builtinloc > 0)
7152                         ) {
7153                                 cmdp->rehash = 1;
7154                         }
7155                 }
7156         }
7157 }
7158
7159 /*
7160  * Fix command hash table when PATH changed.
7161  * Called before PATH is changed.  The argument is the new value of PATH;
7162  * pathval() still returns the old value at this point.
7163  * Called with interrupts off.
7164  */
7165 static void
7166 changepath(const char *new)
7167 {
7168         const char *old;
7169         int firstchange;
7170         int idx;
7171         int idx_bltin;
7172
7173         old = pathval();
7174         firstchange = 9999;     /* assume no change */
7175         idx = 0;
7176         idx_bltin = -1;
7177         for (;;) {
7178                 if (*old != *new) {
7179                         firstchange = idx;
7180                         if ((*old == '\0' && *new == ':')
7181                          || (*old == ':' && *new == '\0'))
7182                                 firstchange++;
7183                         old = new;      /* ignore subsequent differences */
7184                 }
7185                 if (*new == '\0')
7186                         break;
7187                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7188                         idx_bltin = idx;
7189                 if (*new == ':')
7190                         idx++;
7191                 new++, old++;
7192         }
7193         if (builtinloc < 0 && idx_bltin >= 0)
7194                 builtinloc = idx_bltin;             /* zap builtins */
7195         if (builtinloc >= 0 && idx_bltin < 0)
7196                 firstchange = 0;
7197         clearcmdentry(firstchange);
7198         builtinloc = idx_bltin;
7199 }
7200
7201 #define TEOF 0
7202 #define TNL 1
7203 #define TREDIR 2
7204 #define TWORD 3
7205 #define TSEMI 4
7206 #define TBACKGND 5
7207 #define TAND 6
7208 #define TOR 7
7209 #define TPIPE 8
7210 #define TLP 9
7211 #define TRP 10
7212 #define TENDCASE 11
7213 #define TENDBQUOTE 12
7214 #define TNOT 13
7215 #define TCASE 14
7216 #define TDO 15
7217 #define TDONE 16
7218 #define TELIF 17
7219 #define TELSE 18
7220 #define TESAC 19
7221 #define TFI 20
7222 #define TFOR 21
7223 #define TIF 22
7224 #define TIN 23
7225 #define TTHEN 24
7226 #define TUNTIL 25
7227 #define TWHILE 26
7228 #define TBEGIN 27
7229 #define TEND 28
7230 typedef smallint token_id_t;
7231
7232 /* first char is indicating which tokens mark the end of a list */
7233 static const char *const tokname_array[] = {
7234         "\1end of file",
7235         "\0newline",
7236         "\0redirection",
7237         "\0word",
7238         "\0;",
7239         "\0&",
7240         "\0&&",
7241         "\0||",
7242         "\0|",
7243         "\0(",
7244         "\1)",
7245         "\1;;",
7246         "\1`",
7247 #define KWDOFFSET 13
7248         /* the following are keywords */
7249         "\0!",
7250         "\0case",
7251         "\1do",
7252         "\1done",
7253         "\1elif",
7254         "\1else",
7255         "\1esac",
7256         "\1fi",
7257         "\0for",
7258         "\0if",
7259         "\0in",
7260         "\1then",
7261         "\0until",
7262         "\0while",
7263         "\0{",
7264         "\1}",
7265 };
7266
7267 static const char *
7268 tokname(int tok)
7269 {
7270         static char buf[16];
7271
7272 //try this:
7273 //if (tok < TSEMI) return tokname_array[tok] + 1;
7274 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7275 //return buf;
7276
7277         if (tok >= TSEMI)
7278                 buf[0] = '"';
7279         sprintf(buf + (tok >= TSEMI), "%s%c",
7280                         tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7281         return buf;
7282 }
7283
7284 /* Wrapper around strcmp for qsort/bsearch/... */
7285 static int
7286 pstrcmp(const void *a, const void *b)
7287 {
7288         return strcmp((char*) a, (*(char**) b) + 1);
7289 }
7290
7291 static const char *const *
7292 findkwd(const char *s)
7293 {
7294         return bsearch(s, tokname_array + KWDOFFSET,
7295                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
7296                         sizeof(tokname_array[0]), pstrcmp);
7297 }
7298
7299 /*
7300  * Locate and print what a word is...
7301  */
7302 static int
7303 describe_command(char *command, int describe_command_verbose)
7304 {
7305         struct cmdentry entry;
7306         struct tblentry *cmdp;
7307 #if ENABLE_ASH_ALIAS
7308         const struct alias *ap;
7309 #endif
7310         const char *path = pathval();
7311
7312         if (describe_command_verbose) {
7313                 out1str(command);
7314         }
7315
7316         /* First look at the keywords */
7317         if (findkwd(command)) {
7318                 out1str(describe_command_verbose ? " is a shell keyword" : command);
7319                 goto out;
7320         }
7321
7322 #if ENABLE_ASH_ALIAS
7323         /* Then look at the aliases */
7324         ap = lookupalias(command, 0);
7325         if (ap != NULL) {
7326                 if (!describe_command_verbose) {
7327                         out1str("alias ");
7328                         printalias(ap);
7329                         return 0;
7330                 }
7331                 out1fmt(" is an alias for %s", ap->val);
7332                 goto out;
7333         }
7334 #endif
7335         /* Then check if it is a tracked alias */
7336         cmdp = cmdlookup(command, 0);
7337         if (cmdp != NULL) {
7338                 entry.cmdtype = cmdp->cmdtype;
7339                 entry.u = cmdp->param;
7340         } else {
7341                 /* Finally use brute force */
7342                 find_command(command, &entry, DO_ABS, path);
7343         }
7344
7345         switch (entry.cmdtype) {
7346         case CMDNORMAL: {
7347                 int j = entry.u.index;
7348                 char *p;
7349                 if (j < 0) {
7350                         p = command;
7351                 } else {
7352                         do {
7353                                 p = padvance(&path, command);
7354                                 stunalloc(p);
7355                         } while (--j >= 0);
7356                 }
7357                 if (describe_command_verbose) {
7358                         out1fmt(" is%s %s",
7359                                 (cmdp ? " a tracked alias for" : nullstr), p
7360                         );
7361                 } else {
7362                         out1str(p);
7363                 }
7364                 break;
7365         }
7366
7367         case CMDFUNCTION:
7368                 if (describe_command_verbose) {
7369                         out1str(" is a shell function");
7370                 } else {
7371                         out1str(command);
7372                 }
7373                 break;
7374
7375         case CMDBUILTIN:
7376                 if (describe_command_verbose) {
7377                         out1fmt(" is a %sshell builtin",
7378                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7379                                         "special " : nullstr
7380                         );
7381                 } else {
7382                         out1str(command);
7383                 }
7384                 break;
7385
7386         default:
7387                 if (describe_command_verbose) {
7388                         out1str(": not found\n");
7389                 }
7390                 return 127;
7391         }
7392  out:
7393         outstr("\n", stdout);
7394         return 0;
7395 }
7396
7397 static int
7398 typecmd(int argc UNUSED_PARAM, char **argv)
7399 {
7400         int i = 1;
7401         int err = 0;
7402         int verbose = 1;
7403
7404         /* type -p ... ? (we don't bother checking for 'p') */
7405         if (argv[1] && argv[1][0] == '-') {
7406                 i++;
7407                 verbose = 0;
7408         }
7409         while (argv[i]) {
7410                 err |= describe_command(argv[i++], verbose);
7411         }
7412         return err;
7413 }
7414
7415 #if ENABLE_ASH_CMDCMD
7416 static int
7417 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7418 {
7419         int c;
7420         enum {
7421                 VERIFY_BRIEF = 1,
7422                 VERIFY_VERBOSE = 2,
7423         } verify = 0;
7424
7425         while ((c = nextopt("pvV")) != '\0')
7426                 if (c == 'V')
7427                         verify |= VERIFY_VERBOSE;
7428                 else if (c == 'v')
7429                         verify |= VERIFY_BRIEF;
7430 #if DEBUG
7431                 else if (c != 'p')
7432                         abort();
7433 #endif
7434         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7435         if (verify && (*argptr != NULL)) {
7436                 return describe_command(*argptr, verify - VERIFY_BRIEF);
7437         }
7438
7439         return 0;
7440 }
7441 #endif
7442
7443
7444 /* ============ eval.c */
7445
7446 static int funcblocksize;          /* size of structures in function */
7447 static int funcstringsize;         /* size of strings in node */
7448 static void *funcblock;            /* block to allocate function from */
7449 static char *funcstring;           /* block to allocate strings from */
7450
7451 /* flags in argument to evaltree */
7452 #define EV_EXIT 01              /* exit after evaluating tree */
7453 #define EV_TESTED 02            /* exit status is checked; ignore -e flag */
7454 #define EV_BACKCMD 04           /* command executing within back quotes */
7455
7456 static const short nodesize[26] = {
7457         SHELL_ALIGN(sizeof(struct ncmd)),
7458         SHELL_ALIGN(sizeof(struct npipe)),
7459         SHELL_ALIGN(sizeof(struct nredir)),
7460         SHELL_ALIGN(sizeof(struct nredir)),
7461         SHELL_ALIGN(sizeof(struct nredir)),
7462         SHELL_ALIGN(sizeof(struct nbinary)),
7463         SHELL_ALIGN(sizeof(struct nbinary)),
7464         SHELL_ALIGN(sizeof(struct nbinary)),
7465         SHELL_ALIGN(sizeof(struct nif)),
7466         SHELL_ALIGN(sizeof(struct nbinary)),
7467         SHELL_ALIGN(sizeof(struct nbinary)),
7468         SHELL_ALIGN(sizeof(struct nfor)),
7469         SHELL_ALIGN(sizeof(struct ncase)),
7470         SHELL_ALIGN(sizeof(struct nclist)),
7471         SHELL_ALIGN(sizeof(struct narg)),
7472         SHELL_ALIGN(sizeof(struct narg)),
7473         SHELL_ALIGN(sizeof(struct nfile)),
7474         SHELL_ALIGN(sizeof(struct nfile)),
7475         SHELL_ALIGN(sizeof(struct nfile)),
7476         SHELL_ALIGN(sizeof(struct nfile)),
7477         SHELL_ALIGN(sizeof(struct nfile)),
7478         SHELL_ALIGN(sizeof(struct ndup)),
7479         SHELL_ALIGN(sizeof(struct ndup)),
7480         SHELL_ALIGN(sizeof(struct nhere)),
7481         SHELL_ALIGN(sizeof(struct nhere)),
7482         SHELL_ALIGN(sizeof(struct nnot)),
7483 };
7484
7485 static void calcsize(union node *n);
7486
7487 static void
7488 sizenodelist(struct nodelist *lp)
7489 {
7490         while (lp) {
7491                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7492                 calcsize(lp->n);
7493                 lp = lp->next;
7494         }
7495 }
7496
7497 static void
7498 calcsize(union node *n)
7499 {
7500         if (n == NULL)
7501                 return;
7502         funcblocksize += nodesize[n->type];
7503         switch (n->type) {
7504         case NCMD:
7505                 calcsize(n->ncmd.redirect);
7506                 calcsize(n->ncmd.args);
7507                 calcsize(n->ncmd.assign);
7508                 break;
7509         case NPIPE:
7510                 sizenodelist(n->npipe.cmdlist);
7511                 break;
7512         case NREDIR:
7513         case NBACKGND:
7514         case NSUBSHELL:
7515                 calcsize(n->nredir.redirect);
7516                 calcsize(n->nredir.n);
7517                 break;
7518         case NAND:
7519         case NOR:
7520         case NSEMI:
7521         case NWHILE:
7522         case NUNTIL:
7523                 calcsize(n->nbinary.ch2);
7524                 calcsize(n->nbinary.ch1);
7525                 break;
7526         case NIF:
7527                 calcsize(n->nif.elsepart);
7528                 calcsize(n->nif.ifpart);
7529                 calcsize(n->nif.test);
7530                 break;
7531         case NFOR:
7532                 funcstringsize += strlen(n->nfor.var) + 1;
7533                 calcsize(n->nfor.body);
7534                 calcsize(n->nfor.args);
7535                 break;
7536         case NCASE:
7537                 calcsize(n->ncase.cases);
7538                 calcsize(n->ncase.expr);
7539                 break;
7540         case NCLIST:
7541                 calcsize(n->nclist.body);
7542                 calcsize(n->nclist.pattern);
7543                 calcsize(n->nclist.next);
7544                 break;
7545         case NDEFUN:
7546         case NARG:
7547                 sizenodelist(n->narg.backquote);
7548                 funcstringsize += strlen(n->narg.text) + 1;
7549                 calcsize(n->narg.next);
7550                 break;
7551         case NTO:
7552         case NCLOBBER:
7553         case NFROM:
7554         case NFROMTO:
7555         case NAPPEND:
7556                 calcsize(n->nfile.fname);
7557                 calcsize(n->nfile.next);
7558                 break;
7559         case NTOFD:
7560         case NFROMFD:
7561                 calcsize(n->ndup.vname);
7562                 calcsize(n->ndup.next);
7563         break;
7564         case NHERE:
7565         case NXHERE:
7566                 calcsize(n->nhere.doc);
7567                 calcsize(n->nhere.next);
7568                 break;
7569         case NNOT:
7570                 calcsize(n->nnot.com);
7571                 break;
7572         };
7573 }
7574
7575 static char *
7576 nodeckstrdup(char *s)
7577 {
7578         char *rtn = funcstring;
7579
7580         strcpy(funcstring, s);
7581         funcstring += strlen(s) + 1;
7582         return rtn;
7583 }
7584
7585 static union node *copynode(union node *);
7586
7587 static struct nodelist *
7588 copynodelist(struct nodelist *lp)
7589 {
7590         struct nodelist *start;
7591         struct nodelist **lpp;
7592
7593         lpp = &start;
7594         while (lp) {
7595                 *lpp = funcblock;
7596                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7597                 (*lpp)->n = copynode(lp->n);
7598                 lp = lp->next;
7599                 lpp = &(*lpp)->next;
7600         }
7601         *lpp = NULL;
7602         return start;
7603 }
7604
7605 static union node *
7606 copynode(union node *n)
7607 {
7608         union node *new;
7609
7610         if (n == NULL)
7611                 return NULL;
7612         new = funcblock;
7613         funcblock = (char *) funcblock + nodesize[n->type];
7614
7615         switch (n->type) {
7616         case NCMD:
7617                 new->ncmd.redirect = copynode(n->ncmd.redirect);
7618                 new->ncmd.args = copynode(n->ncmd.args);
7619                 new->ncmd.assign = copynode(n->ncmd.assign);
7620                 break;
7621         case NPIPE:
7622                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7623                 new->npipe.backgnd = n->npipe.backgnd;
7624                 break;
7625         case NREDIR:
7626         case NBACKGND:
7627         case NSUBSHELL:
7628                 new->nredir.redirect = copynode(n->nredir.redirect);
7629                 new->nredir.n = copynode(n->nredir.n);
7630                 break;
7631         case NAND:
7632         case NOR:
7633         case NSEMI:
7634         case NWHILE:
7635         case NUNTIL:
7636                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7637                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7638                 break;
7639         case NIF:
7640                 new->nif.elsepart = copynode(n->nif.elsepart);
7641                 new->nif.ifpart = copynode(n->nif.ifpart);
7642                 new->nif.test = copynode(n->nif.test);
7643                 break;
7644         case NFOR:
7645                 new->nfor.var = nodeckstrdup(n->nfor.var);
7646                 new->nfor.body = copynode(n->nfor.body);
7647                 new->nfor.args = copynode(n->nfor.args);
7648                 break;
7649         case NCASE:
7650                 new->ncase.cases = copynode(n->ncase.cases);
7651                 new->ncase.expr = copynode(n->ncase.expr);
7652                 break;
7653         case NCLIST:
7654                 new->nclist.body = copynode(n->nclist.body);
7655                 new->nclist.pattern = copynode(n->nclist.pattern);
7656                 new->nclist.next = copynode(n->nclist.next);
7657                 break;
7658         case NDEFUN:
7659         case NARG:
7660                 new->narg.backquote = copynodelist(n->narg.backquote);
7661                 new->narg.text = nodeckstrdup(n->narg.text);
7662                 new->narg.next = copynode(n->narg.next);
7663                 break;
7664         case NTO:
7665         case NCLOBBER:
7666         case NFROM:
7667         case NFROMTO:
7668         case NAPPEND:
7669                 new->nfile.fname = copynode(n->nfile.fname);
7670                 new->nfile.fd = n->nfile.fd;
7671                 new->nfile.next = copynode(n->nfile.next);
7672                 break;
7673         case NTOFD:
7674         case NFROMFD:
7675                 new->ndup.vname = copynode(n->ndup.vname);
7676                 new->ndup.dupfd = n->ndup.dupfd;
7677                 new->ndup.fd = n->ndup.fd;
7678                 new->ndup.next = copynode(n->ndup.next);
7679                 break;
7680         case NHERE:
7681         case NXHERE:
7682                 new->nhere.doc = copynode(n->nhere.doc);
7683                 new->nhere.fd = n->nhere.fd;
7684                 new->nhere.next = copynode(n->nhere.next);
7685                 break;
7686         case NNOT:
7687                 new->nnot.com = copynode(n->nnot.com);
7688                 break;
7689         };
7690         new->type = n->type;
7691         return new;
7692 }
7693
7694 /*
7695  * Make a copy of a parse tree.
7696  */
7697 static struct funcnode *
7698 copyfunc(union node *n)
7699 {
7700         struct funcnode *f;
7701         size_t blocksize;
7702
7703         funcblocksize = offsetof(struct funcnode, n);
7704         funcstringsize = 0;
7705         calcsize(n);
7706         blocksize = funcblocksize;
7707         f = ckmalloc(blocksize + funcstringsize);
7708         funcblock = (char *) f + offsetof(struct funcnode, n);
7709         funcstring = (char *) f + blocksize;
7710         copynode(n);
7711         f->count = 0;
7712         return f;
7713 }
7714
7715 /*
7716  * Define a shell function.
7717  */
7718 static void
7719 defun(char *name, union node *func)
7720 {
7721         struct cmdentry entry;
7722
7723         INT_OFF;
7724         entry.cmdtype = CMDFUNCTION;
7725         entry.u.func = copyfunc(func);
7726         addcmdentry(name, &entry);
7727         INT_ON;
7728 }
7729
7730 static int evalskip;            /* set if we are skipping commands */
7731 /* reasons for skipping commands (see comment on breakcmd routine) */
7732 #define SKIPBREAK      (1 << 0)
7733 #define SKIPCONT       (1 << 1)
7734 #define SKIPFUNC       (1 << 2)
7735 #define SKIPFILE       (1 << 3)
7736 #define SKIPEVAL       (1 << 4)
7737 static int skipcount;           /* number of levels to skip */
7738 static int funcnest;            /* depth of function calls */
7739 static int loopnest;            /* current loop nesting level */
7740
7741 /* forward decl way out to parsing code - dotrap needs it */
7742 static int evalstring(char *s, int mask);
7743
7744 /*
7745  * Called to execute a trap.  Perhaps we should avoid entering new trap
7746  * handlers while we are executing a trap handler.
7747  */
7748 static int
7749 dotrap(void)
7750 {
7751         char *p;
7752         char *q;
7753         int i;
7754         int savestatus;
7755         int skip;
7756
7757         savestatus = exitstatus;
7758         pendingsig = 0;
7759         xbarrier();
7760
7761         for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
7762                 if (!*q)
7763                         continue;
7764                 *q = '\0';
7765
7766                 p = trap[i + 1];
7767                 if (!p)
7768                         continue;
7769                 skip = evalstring(p, SKIPEVAL);
7770                 exitstatus = savestatus;
7771                 if (skip)
7772                         return skip;
7773         }
7774
7775         return 0;
7776 }
7777
7778 /* forward declarations - evaluation is fairly recursive business... */
7779 static void evalloop(union node *, int);
7780 static void evalfor(union node *, int);
7781 static void evalcase(union node *, int);
7782 static void evalsubshell(union node *, int);
7783 static void expredir(union node *);
7784 static void evalpipe(union node *, int);
7785 static void evalcommand(union node *, int);
7786 static int evalbltin(const struct builtincmd *, int, char **);
7787 static void prehash(union node *);
7788
7789 /*
7790  * Evaluate a parse tree.  The value is left in the global variable
7791  * exitstatus.
7792  */
7793 static void
7794 evaltree(union node *n, int flags)
7795 {
7796         int checkexit = 0;
7797         void (*evalfn)(union node *, int);
7798         unsigned isor;
7799         int status;
7800         if (n == NULL) {
7801                 TRACE(("evaltree(NULL) called\n"));
7802                 goto out;
7803         }
7804         TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7805                         getpid(), n, n->type, flags));
7806         switch (n->type) {
7807         default:
7808 #if DEBUG
7809                 out1fmt("Node type = %d\n", n->type);
7810                 fflush(stdout);
7811                 break;
7812 #endif
7813         case NNOT:
7814                 evaltree(n->nnot.com, EV_TESTED);
7815                 status = !exitstatus;
7816                 goto setstatus;
7817         case NREDIR:
7818                 expredir(n->nredir.redirect);
7819                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7820                 if (!status) {
7821                         evaltree(n->nredir.n, flags & EV_TESTED);
7822                         status = exitstatus;
7823                 }
7824                 popredir(0);
7825                 goto setstatus;
7826         case NCMD:
7827                 evalfn = evalcommand;
7828  checkexit:
7829                 if (eflag && !(flags & EV_TESTED))
7830                         checkexit = ~0;
7831                 goto calleval;
7832         case NFOR:
7833                 evalfn = evalfor;
7834                 goto calleval;
7835         case NWHILE:
7836         case NUNTIL:
7837                 evalfn = evalloop;
7838                 goto calleval;
7839         case NSUBSHELL:
7840         case NBACKGND:
7841                 evalfn = evalsubshell;
7842                 goto calleval;
7843         case NPIPE:
7844                 evalfn = evalpipe;
7845                 goto checkexit;
7846         case NCASE:
7847                 evalfn = evalcase;
7848                 goto calleval;
7849         case NAND:
7850         case NOR:
7851         case NSEMI:
7852 #if NAND + 1 != NOR
7853 #error NAND + 1 != NOR
7854 #endif
7855 #if NOR + 1 != NSEMI
7856 #error NOR + 1 != NSEMI
7857 #endif
7858                 isor = n->type - NAND;
7859                 evaltree(
7860                         n->nbinary.ch1,
7861                         (flags | ((isor >> 1) - 1)) & EV_TESTED
7862                 );
7863                 if (!exitstatus == isor)
7864                         break;
7865                 if (!evalskip) {
7866                         n = n->nbinary.ch2;
7867  evaln:
7868                         evalfn = evaltree;
7869  calleval:
7870                         evalfn(n, flags);
7871                         break;
7872                 }
7873                 break;
7874         case NIF:
7875                 evaltree(n->nif.test, EV_TESTED);
7876                 if (evalskip)
7877                         break;
7878                 if (exitstatus == 0) {
7879                         n = n->nif.ifpart;
7880                         goto evaln;
7881                 } else if (n->nif.elsepart) {
7882                         n = n->nif.elsepart;
7883                         goto evaln;
7884                 }
7885                 goto success;
7886         case NDEFUN:
7887                 defun(n->narg.text, n->narg.next);
7888  success:
7889                 status = 0;
7890  setstatus:
7891                 exitstatus = status;
7892                 break;
7893         }
7894  out:
7895         if ((checkexit & exitstatus))
7896                 evalskip |= SKIPEVAL;
7897         else if (pendingsig && dotrap())
7898                 goto exexit;
7899
7900         if (flags & EV_EXIT) {
7901  exexit:
7902                 raise_exception(EXEXIT);
7903         }
7904 }
7905
7906 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
7907 static
7908 #endif
7909 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
7910
7911 static void
7912 evalloop(union node *n, int flags)
7913 {
7914         int status;
7915
7916         loopnest++;
7917         status = 0;
7918         flags &= EV_TESTED;
7919         for (;;) {
7920                 int i;
7921
7922                 evaltree(n->nbinary.ch1, EV_TESTED);
7923                 if (evalskip) {
7924  skipping:
7925                         if (evalskip == SKIPCONT && --skipcount <= 0) {
7926                                 evalskip = 0;
7927                                 continue;
7928                         }
7929                         if (evalskip == SKIPBREAK && --skipcount <= 0)
7930                                 evalskip = 0;
7931                         break;
7932                 }
7933                 i = exitstatus;
7934                 if (n->type != NWHILE)
7935                         i = !i;
7936                 if (i != 0)
7937                         break;
7938                 evaltree(n->nbinary.ch2, flags);
7939                 status = exitstatus;
7940                 if (evalskip)
7941                         goto skipping;
7942         }
7943         loopnest--;
7944         exitstatus = status;
7945 }
7946
7947 static void
7948 evalfor(union node *n, int flags)
7949 {
7950         struct arglist arglist;
7951         union node *argp;
7952         struct strlist *sp;
7953         struct stackmark smark;
7954
7955         setstackmark(&smark);
7956         arglist.list = NULL;
7957         arglist.lastp = &arglist.list;
7958         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
7959                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
7960                 /* XXX */
7961                 if (evalskip)
7962                         goto out;
7963         }
7964         *arglist.lastp = NULL;
7965
7966         exitstatus = 0;
7967         loopnest++;
7968         flags &= EV_TESTED;
7969         for (sp = arglist.list; sp; sp = sp->next) {
7970                 setvar(n->nfor.var, sp->text, 0);
7971                 evaltree(n->nfor.body, flags);
7972                 if (evalskip) {
7973                         if (evalskip == SKIPCONT && --skipcount <= 0) {
7974                                 evalskip = 0;
7975                                 continue;
7976                         }
7977                         if (evalskip == SKIPBREAK && --skipcount <= 0)
7978                                 evalskip = 0;
7979                         break;
7980                 }
7981         }
7982         loopnest--;
7983  out:
7984         popstackmark(&smark);
7985 }
7986
7987 static void
7988 evalcase(union node *n, int flags)
7989 {
7990         union node *cp;
7991         union node *patp;
7992         struct arglist arglist;
7993         struct stackmark smark;
7994
7995         setstackmark(&smark);
7996         arglist.list = NULL;
7997         arglist.lastp = &arglist.list;
7998         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
7999         exitstatus = 0;
8000         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8001                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8002                         if (casematch(patp, arglist.list->text)) {
8003                                 if (evalskip == 0) {
8004                                         evaltree(cp->nclist.body, flags);
8005                                 }
8006                                 goto out;
8007                         }
8008                 }
8009         }
8010  out:
8011         popstackmark(&smark);
8012 }
8013
8014 /*
8015  * Kick off a subshell to evaluate a tree.
8016  */
8017 static void
8018 evalsubshell(union node *n, int flags)
8019 {
8020         struct job *jp;
8021         int backgnd = (n->type == NBACKGND);
8022         int status;
8023
8024         expredir(n->nredir.redirect);
8025         if (!backgnd && flags & EV_EXIT && !trap[0])
8026                 goto nofork;
8027         INT_OFF;
8028         jp = makejob(/*n,*/ 1);
8029         if (forkshell(jp, n, backgnd) == 0) {
8030                 INT_ON;
8031                 flags |= EV_EXIT;
8032                 if (backgnd)
8033                         flags &=~ EV_TESTED;
8034  nofork:
8035                 redirect(n->nredir.redirect, 0);
8036                 evaltreenr(n->nredir.n, flags);
8037                 /* never returns */
8038         }
8039         status = 0;
8040         if (! backgnd)
8041                 status = waitforjob(jp);
8042         exitstatus = status;
8043         INT_ON;
8044 }
8045
8046 /*
8047  * Compute the names of the files in a redirection list.
8048  */
8049 static void fixredir(union node *, const char *, int);
8050 static void
8051 expredir(union node *n)
8052 {
8053         union node *redir;
8054
8055         for (redir = n; redir; redir = redir->nfile.next) {
8056                 struct arglist fn;
8057
8058                 fn.list = NULL;
8059                 fn.lastp = &fn.list;
8060                 switch (redir->type) {
8061                 case NFROMTO:
8062                 case NFROM:
8063                 case NTO:
8064                 case NCLOBBER:
8065                 case NAPPEND:
8066                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8067                         redir->nfile.expfname = fn.list->text;
8068                         break;
8069                 case NFROMFD:
8070                 case NTOFD:
8071                         if (redir->ndup.vname) {
8072                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8073                                 if (fn.list == NULL)
8074                                         ash_msg_and_raise_error("redir error");
8075                                 fixredir(redir, fn.list->text, 1);
8076                         }
8077                         break;
8078                 }
8079         }
8080 }
8081
8082 /*
8083  * Evaluate a pipeline.  All the processes in the pipeline are children
8084  * of the process creating the pipeline.  (This differs from some versions
8085  * of the shell, which make the last process in a pipeline the parent
8086  * of all the rest.)
8087  */
8088 static void
8089 evalpipe(union node *n, int flags)
8090 {
8091         struct job *jp;
8092         struct nodelist *lp;
8093         int pipelen;
8094         int prevfd;
8095         int pip[2];
8096
8097         TRACE(("evalpipe(0x%lx) called\n", (long)n));
8098         pipelen = 0;
8099         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8100                 pipelen++;
8101         flags |= EV_EXIT;
8102         INT_OFF;
8103         jp = makejob(/*n,*/ pipelen);
8104         prevfd = -1;
8105         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8106                 prehash(lp->n);
8107                 pip[1] = -1;
8108                 if (lp->next) {
8109                         if (pipe(pip) < 0) {
8110                                 close(prevfd);
8111                                 ash_msg_and_raise_error("pipe call failed");
8112                         }
8113                 }
8114                 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
8115                         INT_ON;
8116                         if (pip[1] >= 0) {
8117                                 close(pip[0]);
8118                         }
8119                         if (prevfd > 0) {
8120                                 dup2(prevfd, 0);
8121                                 close(prevfd);
8122                         }
8123                         if (pip[1] > 1) {
8124                                 dup2(pip[1], 1);
8125                                 close(pip[1]);
8126                         }
8127                         evaltreenr(lp->n, flags);
8128                         /* never returns */
8129                 }
8130                 if (prevfd >= 0)
8131                         close(prevfd);
8132                 prevfd = pip[0];
8133                 close(pip[1]);
8134         }
8135         if (n->npipe.backgnd == 0) {
8136                 exitstatus = waitforjob(jp);
8137                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
8138         }
8139         INT_ON;
8140 }
8141
8142 /*
8143  * Controls whether the shell is interactive or not.
8144  */
8145 static void
8146 setinteractive(int on)
8147 {
8148         static smallint is_interactive;
8149
8150         if (++on == is_interactive)
8151                 return;
8152         is_interactive = on;
8153         setsignal(SIGINT);
8154         setsignal(SIGQUIT);
8155         setsignal(SIGTERM);
8156 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8157         if (is_interactive > 1) {
8158                 /* Looks like they want an interactive shell */
8159                 static smallint did_banner;
8160
8161                 if (!did_banner) {
8162                         out1fmt(
8163                                 "\n\n"
8164                                 "%s built-in shell (ash)\n"
8165                                 "Enter 'help' for a list of built-in commands."
8166                                 "\n\n",
8167                                 bb_banner);
8168                         did_banner = 1;
8169                 }
8170         }
8171 #endif
8172 }
8173
8174 static void
8175 optschanged(void)
8176 {
8177 #if DEBUG
8178         opentrace();
8179 #endif
8180         setinteractive(iflag);
8181         setjobctl(mflag);
8182 #if ENABLE_FEATURE_EDITING_VI
8183         if (viflag)
8184                 line_input_state->flags |= VI_MODE;
8185         else
8186                 line_input_state->flags &= ~VI_MODE;
8187 #else
8188         viflag = 0; /* forcibly keep the option off */
8189 #endif
8190 }
8191
8192 static struct localvar *localvars;
8193
8194 /*
8195  * Called after a function returns.
8196  * Interrupts must be off.
8197  */
8198 static void
8199 poplocalvars(void)
8200 {
8201         struct localvar *lvp;
8202         struct var *vp;
8203
8204         while ((lvp = localvars) != NULL) {
8205                 localvars = lvp->next;
8206                 vp = lvp->vp;
8207                 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8208                 if (vp == NULL) {       /* $- saved */
8209                         memcpy(optlist, lvp->text, sizeof(optlist));
8210                         free((char*)lvp->text);
8211                         optschanged();
8212                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8213                         unsetvar(vp->text);
8214                 } else {
8215                         if (vp->func)
8216                                 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8217                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8218                                 free((char*)vp->text);
8219                         vp->flags = lvp->flags;
8220                         vp->text = lvp->text;
8221                 }
8222                 free(lvp);
8223         }
8224 }
8225
8226 static int
8227 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8228 {
8229         volatile struct shparam saveparam;
8230         struct localvar *volatile savelocalvars;
8231         struct jmploc *volatile savehandler;
8232         struct jmploc jmploc;
8233         int e;
8234
8235         saveparam = shellparam;
8236         savelocalvars = localvars;
8237         e = setjmp(jmploc.loc);
8238         if (e) {
8239                 goto funcdone;
8240         }
8241         INT_OFF;
8242         savehandler = exception_handler;
8243         exception_handler = &jmploc;
8244         localvars = NULL;
8245         shellparam.malloced = 0;
8246         func->count++;
8247         funcnest++;
8248         INT_ON;
8249         shellparam.nparam = argc - 1;
8250         shellparam.p = argv + 1;
8251 #if ENABLE_ASH_GETOPTS
8252         shellparam.optind = 1;
8253         shellparam.optoff = -1;
8254 #endif
8255         evaltree(&func->n, flags & EV_TESTED);
8256  funcdone:
8257         INT_OFF;
8258         funcnest--;
8259         freefunc(func);
8260         poplocalvars();
8261         localvars = savelocalvars;
8262         freeparam(&shellparam);
8263         shellparam = saveparam;
8264         exception_handler = savehandler;
8265         INT_ON;
8266         evalskip &= ~SKIPFUNC;
8267         return e;
8268 }
8269
8270 #if ENABLE_ASH_CMDCMD
8271 static char **
8272 parse_command_args(char **argv, const char **path)
8273 {
8274         char *cp, c;
8275
8276         for (;;) {
8277                 cp = *++argv;
8278                 if (!cp)
8279                         return 0;
8280                 if (*cp++ != '-')
8281                         break;
8282                 c = *cp++;
8283                 if (!c)
8284                         break;
8285                 if (c == '-' && !*cp) {
8286                         argv++;
8287                         break;
8288                 }
8289                 do {
8290                         switch (c) {
8291                         case 'p':
8292                                 *path = bb_default_path;
8293                                 break;
8294                         default:
8295                                 /* run 'typecmd' for other options */
8296                                 return 0;
8297                         }
8298                         c = *cp++;
8299                 } while (c);
8300         }
8301         return argv;
8302 }
8303 #endif
8304
8305 /*
8306  * Make a variable a local variable.  When a variable is made local, it's
8307  * value and flags are saved in a localvar structure.  The saved values
8308  * will be restored when the shell function returns.  We handle the name
8309  * "-" as a special case.
8310  */
8311 static void
8312 mklocal(char *name)
8313 {
8314         struct localvar *lvp;
8315         struct var **vpp;
8316         struct var *vp;
8317
8318         INT_OFF;
8319         lvp = ckzalloc(sizeof(struct localvar));
8320         if (LONE_DASH(name)) {
8321                 char *p;
8322                 p = ckmalloc(sizeof(optlist));
8323                 lvp->text = memcpy(p, optlist, sizeof(optlist));
8324                 vp = NULL;
8325         } else {
8326                 char *eq;
8327
8328                 vpp = hashvar(name);
8329                 vp = *findvar(vpp, name);
8330                 eq = strchr(name, '=');
8331                 if (vp == NULL) {
8332                         if (eq)
8333                                 setvareq(name, VSTRFIXED);
8334                         else
8335                                 setvar(name, NULL, VSTRFIXED);
8336                         vp = *vpp;      /* the new variable */
8337                         lvp->flags = VUNSET;
8338                 } else {
8339                         lvp->text = vp->text;
8340                         lvp->flags = vp->flags;
8341                         vp->flags |= VSTRFIXED|VTEXTFIXED;
8342                         if (eq)
8343                                 setvareq(name, 0);
8344                 }
8345         }
8346         lvp->vp = vp;
8347         lvp->next = localvars;
8348         localvars = lvp;
8349         INT_ON;
8350 }
8351
8352 /*
8353  * The "local" command.
8354  */
8355 static int
8356 localcmd(int argc UNUSED_PARAM, char **argv)
8357 {
8358         char *name;
8359
8360         argv = argptr;
8361         while ((name = *argv++) != NULL) {
8362                 mklocal(name);
8363         }
8364         return 0;
8365 }
8366
8367 static int
8368 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8369 {
8370         return 1;
8371 }
8372
8373 static int
8374 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8375 {
8376         return 0;
8377 }
8378
8379 static int
8380 execcmd(int argc UNUSED_PARAM, char **argv)
8381 {
8382         if (argv[1]) {
8383                 iflag = 0;              /* exit on error */
8384                 mflag = 0;
8385                 optschanged();
8386                 shellexec(argv + 1, pathval(), 0);
8387         }
8388         return 0;
8389 }
8390
8391 /*
8392  * The return command.
8393  */
8394 static int
8395 returncmd(int argc UNUSED_PARAM, char **argv)
8396 {
8397         /*
8398          * If called outside a function, do what ksh does;
8399          * skip the rest of the file.
8400          */
8401         evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8402         return argv[1] ? number(argv[1]) : exitstatus;
8403 }
8404
8405 /* Forward declarations for builtintab[] */
8406 static int breakcmd(int, char **);
8407 static int dotcmd(int, char **);
8408 static int evalcmd(int, char **);
8409 static int exitcmd(int, char **);
8410 static int exportcmd(int, char **);
8411 #if ENABLE_ASH_GETOPTS
8412 static int getoptscmd(int, char **);
8413 #endif
8414 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8415 static int helpcmd(int, char **);
8416 #endif
8417 #if ENABLE_ASH_MATH_SUPPORT
8418 static int letcmd(int, char **);
8419 #endif
8420 static int readcmd(int, char **);
8421 static int setcmd(int, char **);
8422 static int shiftcmd(int, char **);
8423 static int timescmd(int, char **);
8424 static int trapcmd(int, char **);
8425 static int umaskcmd(int, char **);
8426 static int unsetcmd(int, char **);
8427 static int ulimitcmd(int, char **);
8428
8429 #define BUILTIN_NOSPEC          "0"
8430 #define BUILTIN_SPECIAL         "1"
8431 #define BUILTIN_REGULAR         "2"
8432 #define BUILTIN_SPEC_REG        "3"
8433 #define BUILTIN_ASSIGN          "4"
8434 #define BUILTIN_SPEC_ASSG       "5"
8435 #define BUILTIN_REG_ASSG        "6"
8436 #define BUILTIN_SPEC_REG_ASSG   "7"
8437
8438 /* We do not handle [[ expr ]] bashism bash-compatibly,
8439  * we make it a synonym of [ expr ].
8440  * Basically, word splitting and pathname expansion should NOT be performed
8441  * Examples:
8442  * no word splitting:     a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8443  * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8444  * Additional operators:
8445  * || and && should work as -o and -a
8446  * =~ regexp match
8447  * Apart from the above, [[ expr ]] should work as [ expr ]
8448  */
8449
8450 #define echocmd   echo_main
8451 #define printfcmd printf_main
8452 #define testcmd   test_main
8453
8454 /* Keep these in proper order since it is searched via bsearch() */
8455 static const struct builtincmd builtintab[] = {
8456         { BUILTIN_SPEC_REG      ".", dotcmd },
8457         { BUILTIN_SPEC_REG      ":", truecmd },
8458 #if ENABLE_ASH_BUILTIN_TEST
8459         { BUILTIN_REGULAR       "[", testcmd },
8460 #if ENABLE_ASH_BASH_COMPAT
8461         { BUILTIN_REGULAR       "[[", testcmd },
8462 #endif
8463 #endif
8464 #if ENABLE_ASH_ALIAS
8465         { BUILTIN_REG_ASSG      "alias", aliascmd },
8466 #endif
8467 #if JOBS
8468         { BUILTIN_REGULAR       "bg", fg_bgcmd },
8469 #endif
8470         { BUILTIN_SPEC_REG      "break", breakcmd },
8471         { BUILTIN_REGULAR       "cd", cdcmd },
8472         { BUILTIN_NOSPEC        "chdir", cdcmd },
8473 #if ENABLE_ASH_CMDCMD
8474         { BUILTIN_REGULAR       "command", commandcmd },
8475 #endif
8476         { BUILTIN_SPEC_REG      "continue", breakcmd },
8477 #if ENABLE_ASH_BUILTIN_ECHO
8478         { BUILTIN_REGULAR       "echo", echocmd },
8479 #endif
8480         { BUILTIN_SPEC_REG      "eval", evalcmd },
8481         { BUILTIN_SPEC_REG      "exec", execcmd },
8482         { BUILTIN_SPEC_REG      "exit", exitcmd },
8483         { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8484         { BUILTIN_REGULAR       "false", falsecmd },
8485 #if JOBS
8486         { BUILTIN_REGULAR       "fg", fg_bgcmd },
8487 #endif
8488 #if ENABLE_ASH_GETOPTS
8489         { BUILTIN_REGULAR       "getopts", getoptscmd },
8490 #endif
8491         { BUILTIN_NOSPEC        "hash", hashcmd },
8492 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8493         { BUILTIN_NOSPEC        "help", helpcmd },
8494 #endif
8495 #if JOBS
8496         { BUILTIN_REGULAR       "jobs", jobscmd },
8497         { BUILTIN_REGULAR       "kill", killcmd },
8498 #endif
8499 #if ENABLE_ASH_MATH_SUPPORT
8500         { BUILTIN_NOSPEC        "let", letcmd },
8501 #endif
8502         { BUILTIN_ASSIGN        "local", localcmd },
8503 #if ENABLE_ASH_BUILTIN_PRINTF
8504         { BUILTIN_REGULAR       "printf", printfcmd },
8505 #endif
8506         { BUILTIN_NOSPEC        "pwd", pwdcmd },
8507         { BUILTIN_REGULAR       "read", readcmd },
8508         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8509         { BUILTIN_SPEC_REG      "return", returncmd },
8510         { BUILTIN_SPEC_REG      "set", setcmd },
8511         { BUILTIN_SPEC_REG      "shift", shiftcmd },
8512         { BUILTIN_SPEC_REG      "source", dotcmd },
8513 #if ENABLE_ASH_BUILTIN_TEST
8514         { BUILTIN_REGULAR       "test", testcmd },
8515 #endif
8516         { BUILTIN_SPEC_REG      "times", timescmd },
8517         { BUILTIN_SPEC_REG      "trap", trapcmd },
8518         { BUILTIN_REGULAR       "true", truecmd },
8519         { BUILTIN_NOSPEC        "type", typecmd },
8520         { BUILTIN_NOSPEC        "ulimit", ulimitcmd },
8521         { BUILTIN_REGULAR       "umask", umaskcmd },
8522 #if ENABLE_ASH_ALIAS
8523         { BUILTIN_REGULAR       "unalias", unaliascmd },
8524 #endif
8525         { BUILTIN_SPEC_REG      "unset", unsetcmd },
8526         { BUILTIN_REGULAR       "wait", waitcmd },
8527 };
8528
8529 /* Should match the above table! */
8530 #define COMMANDCMD (builtintab + \
8531         2 + \
8532         1 * ENABLE_ASH_BUILTIN_TEST + \
8533         1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8534         1 * ENABLE_ASH_ALIAS + \
8535         1 * ENABLE_ASH_JOB_CONTROL + \
8536         3)
8537 #define EXECCMD (builtintab + \
8538         2 + \
8539         1 * ENABLE_ASH_BUILTIN_TEST + \
8540         1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8541         1 * ENABLE_ASH_ALIAS + \
8542         1 * ENABLE_ASH_JOB_CONTROL + \
8543         3 + \
8544         1 * ENABLE_ASH_CMDCMD + \
8545         1 + \
8546         ENABLE_ASH_BUILTIN_ECHO + \
8547         1)
8548
8549 /*
8550  * Search the table of builtin commands.
8551  */
8552 static struct builtincmd *
8553 find_builtin(const char *name)
8554 {
8555         struct builtincmd *bp;
8556
8557         bp = bsearch(
8558                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8559                 pstrcmp
8560         );
8561         return bp;
8562 }
8563
8564 /*
8565  * Execute a simple command.
8566  */
8567 static int
8568 isassignment(const char *p)
8569 {
8570         const char *q = endofname(p);
8571         if (p == q)
8572                 return 0;
8573         return *q == '=';
8574 }
8575 static int
8576 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8577 {
8578         /* Preserve exitstatus of a previous possible redirection
8579          * as POSIX mandates */
8580         return back_exitstatus;
8581 }
8582 static void
8583 evalcommand(union node *cmd, int flags)
8584 {
8585         static const struct builtincmd null_bltin = {
8586                 "\0\0", bltincmd /* why three NULs? */
8587         };
8588         struct stackmark smark;
8589         union node *argp;
8590         struct arglist arglist;
8591         struct arglist varlist;
8592         char **argv;
8593         int argc;
8594         const struct strlist *sp;
8595         struct cmdentry cmdentry;
8596         struct job *jp;
8597         char *lastarg;
8598         const char *path;
8599         int spclbltin;
8600         int cmd_is_exec;
8601         int status;
8602         char **nargv;
8603         struct builtincmd *bcmd;
8604         int pseudovarflag = 0;
8605
8606         /* First expand the arguments. */
8607         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8608         setstackmark(&smark);
8609         back_exitstatus = 0;
8610
8611         cmdentry.cmdtype = CMDBUILTIN;
8612         cmdentry.u.cmd = &null_bltin;
8613         varlist.lastp = &varlist.list;
8614         *varlist.lastp = NULL;
8615         arglist.lastp = &arglist.list;
8616         *arglist.lastp = NULL;
8617
8618         argc = 0;
8619         if (cmd->ncmd.args) {
8620                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8621                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8622         }
8623
8624         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8625                 struct strlist **spp;
8626
8627                 spp = arglist.lastp;
8628                 if (pseudovarflag && isassignment(argp->narg.text))
8629                         expandarg(argp, &arglist, EXP_VARTILDE);
8630                 else
8631                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8632
8633                 for (sp = *spp; sp; sp = sp->next)
8634                         argc++;
8635         }
8636
8637         argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8638         for (sp = arglist.list; sp; sp = sp->next) {
8639                 TRACE(("evalcommand arg: %s\n", sp->text));
8640                 *nargv++ = sp->text;
8641         }
8642         *nargv = NULL;
8643
8644         lastarg = NULL;
8645         if (iflag && funcnest == 0 && argc > 0)
8646                 lastarg = nargv[-1];
8647
8648         preverrout_fd = 2;
8649         expredir(cmd->ncmd.redirect);
8650         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8651
8652         path = vpath.text;
8653         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8654                 struct strlist **spp;
8655                 char *p;
8656
8657                 spp = varlist.lastp;
8658                 expandarg(argp, &varlist, EXP_VARTILDE);
8659
8660                 /*
8661                  * Modify the command lookup path, if a PATH= assignment
8662                  * is present
8663                  */
8664                 p = (*spp)->text;
8665                 if (varequal(p, path))
8666                         path = p;
8667         }
8668
8669         /* Print the command if xflag is set. */
8670         if (xflag) {
8671                 int n;
8672                 const char *p = " %s";
8673
8674                 p++;
8675                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8676
8677                 sp = varlist.list;
8678                 for (n = 0; n < 2; n++) {
8679                         while (sp) {
8680                                 fdprintf(preverrout_fd, p, sp->text);
8681                                 sp = sp->next;
8682                                 if (*p == '%') {
8683                                         p--;
8684                                 }
8685                         }
8686                         sp = arglist.list;
8687                 }
8688                 safe_write(preverrout_fd, "\n", 1);
8689         }
8690
8691         cmd_is_exec = 0;
8692         spclbltin = -1;
8693
8694         /* Now locate the command. */
8695         if (argc) {
8696                 const char *oldpath;
8697                 int cmd_flag = DO_ERR;
8698
8699                 path += 5;
8700                 oldpath = path;
8701                 for (;;) {
8702                         find_command(argv[0], &cmdentry, cmd_flag, path);
8703                         if (cmdentry.cmdtype == CMDUNKNOWN) {
8704                                 status = 127;
8705                                 flush_stderr();
8706                                 goto bail;
8707                         }
8708
8709                         /* implement bltin and command here */
8710                         if (cmdentry.cmdtype != CMDBUILTIN)
8711                                 break;
8712                         if (spclbltin < 0)
8713                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8714                         if (cmdentry.u.cmd == EXECCMD)
8715                                 cmd_is_exec++;
8716 #if ENABLE_ASH_CMDCMD
8717                         if (cmdentry.u.cmd == COMMANDCMD) {
8718                                 path = oldpath;
8719                                 nargv = parse_command_args(argv, &path);
8720                                 if (!nargv)
8721                                         break;
8722                                 argc -= nargv - argv;
8723                                 argv = nargv;
8724                                 cmd_flag |= DO_NOFUNC;
8725                         } else
8726 #endif
8727                                 break;
8728                 }
8729         }
8730
8731         if (status) {
8732                 /* We have a redirection error. */
8733                 if (spclbltin > 0)
8734                         raise_exception(EXERROR);
8735  bail:
8736                 exitstatus = status;
8737                 goto out;
8738         }
8739
8740         /* Execute the command. */
8741         switch (cmdentry.cmdtype) {
8742         default:
8743 #if ENABLE_FEATURE_SH_NOFORK
8744         {
8745                 /* find_command() encodes applet_no as (-2 - applet_no) */
8746                 int applet_no = (- cmdentry.u.index - 2);
8747                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8748                         listsetvar(varlist.list, VEXPORT|VSTACK);
8749                         /* run <applet>_main() */
8750                         exitstatus = run_nofork_applet(applet_no, argv);
8751                         break;
8752                 }
8753         }
8754 #endif
8755
8756                 /* Fork off a child process if necessary. */
8757                 if (!(flags & EV_EXIT) || trap[0]) {
8758                         INT_OFF;
8759                         jp = makejob(/*cmd,*/ 1);
8760                         if (forkshell(jp, cmd, FORK_FG) != 0) {
8761                                 exitstatus = waitforjob(jp);
8762                                 INT_ON;
8763                                 break;
8764                         }
8765                         FORCE_INT_ON;
8766                 }
8767                 listsetvar(varlist.list, VEXPORT|VSTACK);
8768                 shellexec(argv, path, cmdentry.u.index);
8769                 /* NOTREACHED */
8770
8771         case CMDBUILTIN:
8772                 cmdenviron = varlist.list;
8773                 if (cmdenviron) {
8774                         struct strlist *list = cmdenviron;
8775                         int i = VNOSET;
8776                         if (spclbltin > 0 || argc == 0) {
8777                                 i = 0;
8778                                 if (cmd_is_exec && argc > 1)
8779                                         i = VEXPORT;
8780                         }
8781                         listsetvar(list, i);
8782                 }
8783                 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8784                         int exit_status;
8785                         int i = exception;
8786                         if (i == EXEXIT)
8787                                 goto raise;
8788                         exit_status = 2;
8789                         if (i == EXINT)
8790                                 exit_status = 128 + SIGINT;
8791                         if (i == EXSIG)
8792                                 exit_status = 128 + pendingsig;
8793                         exitstatus = exit_status;
8794                         if (i == EXINT || spclbltin > 0) {
8795  raise:
8796                                 longjmp(exception_handler->loc, 1);
8797                         }
8798                         FORCE_INT_ON;
8799                 }
8800                 break;
8801
8802         case CMDFUNCTION:
8803                 listsetvar(varlist.list, 0);
8804                 if (evalfun(cmdentry.u.func, argc, argv, flags))
8805                         goto raise;
8806                 break;
8807         }
8808
8809  out:
8810         popredir(cmd_is_exec);
8811         if (lastarg)
8812                 /* dsl: I think this is intended to be used to support
8813                  * '_' in 'vi' command mode during line editing...
8814                  * However I implemented that within libedit itself.
8815                  */
8816                 setvar("_", lastarg, 0);
8817         popstackmark(&smark);
8818 }
8819
8820 static int
8821 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8822 {
8823         char *volatile savecmdname;
8824         struct jmploc *volatile savehandler;
8825         struct jmploc jmploc;
8826         int i;
8827
8828         savecmdname = commandname;
8829         i = setjmp(jmploc.loc);
8830         if (i)
8831                 goto cmddone;
8832         savehandler = exception_handler;
8833         exception_handler = &jmploc;
8834         commandname = argv[0];
8835         argptr = argv + 1;
8836         optptr = NULL;                  /* initialize nextopt */
8837         exitstatus = (*cmd->builtin)(argc, argv);
8838         flush_stdout_stderr();
8839  cmddone:
8840         exitstatus |= ferror(stdout);
8841         clearerr(stdout);
8842         commandname = savecmdname;
8843 //      exsig = 0;
8844         exception_handler = savehandler;
8845
8846         return i;
8847 }
8848
8849 static int
8850 goodname(const char *p)
8851 {
8852         return !*endofname(p);
8853 }
8854
8855
8856 /*
8857  * Search for a command.  This is called before we fork so that the
8858  * location of the command will be available in the parent as well as
8859  * the child.  The check for "goodname" is an overly conservative
8860  * check that the name will not be subject to expansion.
8861  */
8862 static void
8863 prehash(union node *n)
8864 {
8865         struct cmdentry entry;
8866
8867         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8868                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8869 }
8870
8871
8872 /* ============ Builtin commands
8873  *
8874  * Builtin commands whose functions are closely tied to evaluation
8875  * are implemented here.
8876  */
8877
8878 /*
8879  * Handle break and continue commands.  Break, continue, and return are
8880  * all handled by setting the evalskip flag.  The evaluation routines
8881  * above all check this flag, and if it is set they start skipping
8882  * commands rather than executing them.  The variable skipcount is
8883  * the number of loops to break/continue, or the number of function
8884  * levels to return.  (The latter is always 1.)  It should probably
8885  * be an error to break out of more loops than exist, but it isn't
8886  * in the standard shell so we don't make it one here.
8887  */
8888 static int
8889 breakcmd(int argc UNUSED_PARAM, char **argv)
8890 {
8891         int n = argv[1] ? number(argv[1]) : 1;
8892
8893         if (n <= 0)
8894                 ash_msg_and_raise_error(illnum, argv[1]);
8895         if (n > loopnest)
8896                 n = loopnest;
8897         if (n > 0) {
8898                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
8899                 skipcount = n;
8900         }
8901         return 0;
8902 }
8903
8904
8905 /* ============ input.c
8906  *
8907  * This implements the input routines used by the parser.
8908  */
8909
8910 #define EOF_NLEFT -99           /* value of parsenleft when EOF pushed back */
8911
8912 enum {
8913         INPUT_PUSH_FILE = 1,
8914         INPUT_NOFILE_OK = 2,
8915 };
8916
8917 static int plinno = 1;                  /* input line number */
8918 /* number of characters left in input buffer */
8919 static int parsenleft;                  /* copy of parsefile->nleft */
8920 static int parselleft;                  /* copy of parsefile->lleft */
8921 /* next character in input buffer */
8922 static char *parsenextc;                /* copy of parsefile->nextc */
8923
8924 static smallint checkkwd;
8925 /* values of checkkwd variable */
8926 #define CHKALIAS        0x1
8927 #define CHKKWD          0x2
8928 #define CHKNL           0x4
8929
8930 static void
8931 popstring(void)
8932 {
8933         struct strpush *sp = g_parsefile->strpush;
8934
8935         INT_OFF;
8936 #if ENABLE_ASH_ALIAS
8937         if (sp->ap) {
8938                 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8939                         checkkwd |= CHKALIAS;
8940                 }
8941                 if (sp->string != sp->ap->val) {
8942                         free(sp->string);
8943                 }
8944                 sp->ap->flag &= ~ALIASINUSE;
8945                 if (sp->ap->flag & ALIASDEAD) {
8946                         unalias(sp->ap->name);
8947                 }
8948         }
8949 #endif
8950         parsenextc = sp->prevstring;
8951         parsenleft = sp->prevnleft;
8952 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8953         g_parsefile->strpush = sp->prev;
8954         if (sp != &(g_parsefile->basestrpush))
8955                 free(sp);
8956         INT_ON;
8957 }
8958
8959 static int
8960 preadfd(void)
8961 {
8962         int nr;
8963         char *buf =  g_parsefile->buf;
8964         parsenextc = buf;
8965
8966 #if ENABLE_FEATURE_EDITING
8967  retry:
8968         if (!iflag || g_parsefile->fd)
8969                 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
8970         else {
8971 #if ENABLE_FEATURE_TAB_COMPLETION
8972                 line_input_state->path_lookup = pathval();
8973 #endif
8974                 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8975                 if (nr == 0) {
8976                         /* Ctrl+C pressed */
8977                         if (trap[SIGINT]) {
8978                                 buf[0] = '\n';
8979                                 buf[1] = '\0';
8980                                 raise(SIGINT);
8981                                 return 1;
8982                         }
8983                         goto retry;
8984                 }
8985                 if (nr < 0 && errno == 0) {
8986                         /* Ctrl+D pressed */
8987                         nr = 0;
8988                 }
8989         }
8990 #else
8991         nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
8992 #endif
8993
8994 #if 0
8995 /* nonblock_safe_read() handles this problem */
8996         if (nr < 0) {
8997                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8998                         int flags = fcntl(0, F_GETFL);
8999                         if (flags >= 0 && (flags & O_NONBLOCK)) {
9000                                 flags &= ~O_NONBLOCK;
9001                                 if (fcntl(0, F_SETFL, flags) >= 0) {
9002                                         out2str("sh: turning off NDELAY mode\n");
9003                                         goto retry;
9004                                 }
9005                         }
9006                 }
9007         }
9008 #endif
9009         return nr;
9010 }
9011
9012 /*
9013  * Refill the input buffer and return the next input character:
9014  *
9015  * 1) If a string was pushed back on the input, pop it;
9016  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
9017  *    from a string so we can't refill the buffer, return EOF.
9018  * 3) If the is more stuff in this buffer, use it else call read to fill it.
9019  * 4) Process input up to the next newline, deleting nul characters.
9020  */
9021 static int
9022 preadbuffer(void)
9023 {
9024         char *q;
9025         int more;
9026         char savec;
9027
9028         while (g_parsefile->strpush) {
9029 #if ENABLE_ASH_ALIAS
9030                 if (parsenleft == -1 && g_parsefile->strpush->ap &&
9031                         parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
9032                         return PEOA;
9033                 }
9034 #endif
9035                 popstring();
9036                 if (--parsenleft >= 0)
9037                         return signed_char2int(*parsenextc++);
9038         }
9039         if (parsenleft == EOF_NLEFT || g_parsefile->buf == NULL)
9040                 return PEOF;
9041         flush_stdout_stderr();
9042
9043         more = parselleft;
9044         if (more <= 0) {
9045  again:
9046                 more = preadfd();
9047                 if (more <= 0) {
9048                         parselleft = parsenleft = EOF_NLEFT;
9049                         return PEOF;
9050                 }
9051         }
9052
9053         q = parsenextc;
9054
9055         /* delete nul characters */
9056         for (;;) {
9057                 int c;
9058
9059                 more--;
9060                 c = *q;
9061
9062                 if (!c)
9063                         memmove(q, q + 1, more);
9064                 else {
9065                         q++;
9066                         if (c == '\n') {
9067                                 parsenleft = q - parsenextc - 1;
9068                                 break;
9069                         }
9070                 }
9071
9072                 if (more <= 0) {
9073                         parsenleft = q - parsenextc - 1;
9074                         if (parsenleft < 0)
9075                                 goto again;
9076                         break;
9077                 }
9078         }
9079         parselleft = more;
9080
9081         savec = *q;
9082         *q = '\0';
9083
9084         if (vflag) {
9085                 out2str(parsenextc);
9086         }
9087
9088         *q = savec;
9089
9090         return signed_char2int(*parsenextc++);
9091 }
9092
9093 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
9094 static int
9095 pgetc(void)
9096 {
9097         return pgetc_as_macro();
9098 }
9099
9100 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9101 #define pgetc_macro() pgetc()
9102 #else
9103 #define pgetc_macro() pgetc_as_macro()
9104 #endif
9105
9106 /*
9107  * Same as pgetc(), but ignores PEOA.
9108  */
9109 #if ENABLE_ASH_ALIAS
9110 static int
9111 pgetc2(void)
9112 {
9113         int c;
9114
9115         do {
9116                 c = pgetc_macro();
9117         } while (c == PEOA);
9118         return c;
9119 }
9120 #else
9121 static int
9122 pgetc2(void)
9123 {
9124         return pgetc_macro();
9125 }
9126 #endif
9127
9128 /*
9129  * Read a line from the script.
9130  */
9131 static char *
9132 pfgets(char *line, int len)
9133 {
9134         char *p = line;
9135         int nleft = len;
9136         int c;
9137
9138         while (--nleft > 0) {
9139                 c = pgetc2();
9140                 if (c == PEOF) {
9141                         if (p == line)
9142                                 return NULL;
9143                         break;
9144                 }
9145                 *p++ = c;
9146                 if (c == '\n')
9147                         break;
9148         }
9149         *p = '\0';
9150         return line;
9151 }
9152
9153 /*
9154  * Undo the last call to pgetc.  Only one character may be pushed back.
9155  * PEOF may be pushed back.
9156  */
9157 static void
9158 pungetc(void)
9159 {
9160         parsenleft++;
9161         parsenextc--;
9162 }
9163
9164 /*
9165  * Push a string back onto the input at this current parsefile level.
9166  * We handle aliases this way.
9167  */
9168 #if !ENABLE_ASH_ALIAS
9169 #define pushstring(s, ap) pushstring(s)
9170 #endif
9171 static void
9172 pushstring(char *s, struct alias *ap)
9173 {
9174         struct strpush *sp;
9175         size_t len;
9176
9177         len = strlen(s);
9178         INT_OFF;
9179 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
9180         if (g_parsefile->strpush) {
9181                 sp = ckzalloc(sizeof(struct strpush));
9182                 sp->prev = g_parsefile->strpush;
9183                 g_parsefile->strpush = sp;
9184         } else
9185                 sp = g_parsefile->strpush = &(g_parsefile->basestrpush);
9186         sp->prevstring = parsenextc;
9187         sp->prevnleft = parsenleft;
9188 #if ENABLE_ASH_ALIAS
9189         sp->ap = ap;
9190         if (ap) {
9191                 ap->flag |= ALIASINUSE;
9192                 sp->string = s;
9193         }
9194 #endif
9195         parsenextc = s;
9196         parsenleft = len;
9197         INT_ON;
9198 }
9199
9200 /*
9201  * To handle the "." command, a stack of input files is used.  Pushfile
9202  * adds a new entry to the stack and popfile restores the previous level.
9203  */
9204 static void
9205 pushfile(void)
9206 {
9207         struct parsefile *pf;
9208
9209         g_parsefile->nleft = parsenleft;
9210         g_parsefile->lleft = parselleft;
9211         g_parsefile->nextc = parsenextc;
9212         g_parsefile->linno = plinno;
9213         pf = ckzalloc(sizeof(*pf));
9214         pf->prev = g_parsefile;
9215         pf->fd = -1;
9216         /*pf->strpush = NULL; - ckzalloc did it */
9217         /*pf->basestrpush.prev = NULL;*/
9218         g_parsefile = pf;
9219 }
9220
9221 static void
9222 popfile(void)
9223 {
9224         struct parsefile *pf = g_parsefile;
9225
9226         INT_OFF;
9227         if (pf->fd >= 0)
9228                 close(pf->fd);
9229         free(pf->buf);
9230         while (pf->strpush)
9231                 popstring();
9232         g_parsefile = pf->prev;
9233         free(pf);
9234         parsenleft = g_parsefile->nleft;
9235         parselleft = g_parsefile->lleft;
9236         parsenextc = g_parsefile->nextc;
9237         plinno = g_parsefile->linno;
9238         INT_ON;
9239 }
9240
9241 /*
9242  * Return to top level.
9243  */
9244 static void
9245 popallfiles(void)
9246 {
9247         while (g_parsefile != &basepf)
9248                 popfile();
9249 }
9250
9251 /*
9252  * Close the file(s) that the shell is reading commands from.  Called
9253  * after a fork is done.
9254  */
9255 static void
9256 closescript(void)
9257 {
9258         popallfiles();
9259         if (g_parsefile->fd > 0) {
9260                 close(g_parsefile->fd);
9261                 g_parsefile->fd = 0;
9262         }
9263 }
9264
9265 /*
9266  * Like setinputfile, but takes an open file descriptor.  Call this with
9267  * interrupts off.
9268  */
9269 static void
9270 setinputfd(int fd, int push)
9271 {
9272         close_on_exec_on(fd);
9273         if (push) {
9274                 pushfile();
9275                 g_parsefile->buf = 0;
9276         }
9277         g_parsefile->fd = fd;
9278         if (g_parsefile->buf == NULL)
9279                 g_parsefile->buf = ckmalloc(IBUFSIZ);
9280         parselleft = parsenleft = 0;
9281         plinno = 1;
9282 }
9283
9284 /*
9285  * Set the input to take input from a file.  If push is set, push the
9286  * old input onto the stack first.
9287  */
9288 static int
9289 setinputfile(const char *fname, int flags)
9290 {
9291         int fd;
9292         int fd2;
9293
9294         INT_OFF;
9295         fd = open(fname, O_RDONLY);
9296         if (fd < 0) {
9297                 if (flags & INPUT_NOFILE_OK)
9298                         goto out;
9299                 ash_msg_and_raise_error("can't open %s", fname);
9300         }
9301         if (fd < 10) {
9302                 fd2 = copyfd(fd, 10);
9303                 close(fd);
9304                 if (fd2 < 0)
9305                         ash_msg_and_raise_error("out of file descriptors");
9306                 fd = fd2;
9307         }
9308         setinputfd(fd, flags & INPUT_PUSH_FILE);
9309  out:
9310         INT_ON;
9311         return fd;
9312 }
9313
9314 /*
9315  * Like setinputfile, but takes input from a string.
9316  */
9317 static void
9318 setinputstring(char *string)
9319 {
9320         INT_OFF;
9321         pushfile();
9322         parsenextc = string;
9323         parsenleft = strlen(string);
9324         g_parsefile->buf = NULL;
9325         plinno = 1;
9326         INT_ON;
9327 }
9328
9329
9330 /* ============ mail.c
9331  *
9332  * Routines to check for mail.
9333  */
9334
9335 #if ENABLE_ASH_MAIL
9336
9337 #define MAXMBOXES 10
9338
9339 /* times of mailboxes */
9340 static time_t mailtime[MAXMBOXES];
9341 /* Set if MAIL or MAILPATH is changed. */
9342 static smallint mail_var_path_changed;
9343
9344 /*
9345  * Print appropriate message(s) if mail has arrived.
9346  * If mail_var_path_changed is set,
9347  * then the value of MAIL has mail_var_path_changed,
9348  * so we just update the values.
9349  */
9350 static void
9351 chkmail(void)
9352 {
9353         const char *mpath;
9354         char *p;
9355         char *q;
9356         time_t *mtp;
9357         struct stackmark smark;
9358         struct stat statb;
9359
9360         setstackmark(&smark);
9361         mpath = mpathset() ? mpathval() : mailval();
9362         for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9363                 p = padvance(&mpath, nullstr);
9364                 if (p == NULL)
9365                         break;
9366                 if (*p == '\0')
9367                         continue;
9368                 for (q = p; *q; q++)
9369                         continue;
9370 #if DEBUG
9371                 if (q[-1] != '/')
9372                         abort();
9373 #endif
9374                 q[-1] = '\0';                   /* delete trailing '/' */
9375                 if (stat(p, &statb) < 0) {
9376                         *mtp = 0;
9377                         continue;
9378                 }
9379                 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9380                         fprintf(
9381                                 stderr, snlfmt,
9382                                 pathopt ? pathopt : "you have mail"
9383                         );
9384                 }
9385                 *mtp = statb.st_mtime;
9386         }
9387         mail_var_path_changed = 0;
9388         popstackmark(&smark);
9389 }
9390
9391 static void
9392 changemail(const char *val UNUSED_PARAM)
9393 {
9394         mail_var_path_changed = 1;
9395 }
9396
9397 #endif /* ASH_MAIL */
9398
9399
9400 /* ============ ??? */
9401
9402 /*
9403  * Set the shell parameters.
9404  */
9405 static void
9406 setparam(char **argv)
9407 {
9408         char **newparam;
9409         char **ap;
9410         int nparam;
9411
9412         for (nparam = 0; argv[nparam]; nparam++)
9413                 continue;
9414         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9415         while (*argv) {
9416                 *ap++ = ckstrdup(*argv++);
9417         }
9418         *ap = NULL;
9419         freeparam(&shellparam);
9420         shellparam.malloced = 1;
9421         shellparam.nparam = nparam;
9422         shellparam.p = newparam;
9423 #if ENABLE_ASH_GETOPTS
9424         shellparam.optind = 1;
9425         shellparam.optoff = -1;
9426 #endif
9427 }
9428
9429 /*
9430  * Process shell options.  The global variable argptr contains a pointer
9431  * to the argument list; we advance it past the options.
9432  *
9433  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9434  * For a non-interactive shell, an error condition encountered
9435  * by a special built-in ... shall cause the shell to write a diagnostic message
9436  * to standard error and exit as shown in the following table:
9437  * Error                                           Special Built-In
9438  * ...
9439  * Utility syntax error (option or operand error)  Shall exit
9440  * ...
9441  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9442  * we see that bash does not do that (set "finishes" with error code 1 instead,
9443  * and shell continues), and people rely on this behavior!
9444  * Testcase:
9445  * set -o barfoo 2>/dev/null
9446  * echo $?
9447  *
9448  * Oh well. Let's mimic that.
9449  */
9450 static int
9451 plus_minus_o(char *name, int val)
9452 {
9453         int i;
9454
9455         if (name) {
9456                 for (i = 0; i < NOPTS; i++) {
9457                         if (strcmp(name, optnames(i)) == 0) {
9458                                 optlist[i] = val;
9459                                 return 0;
9460                         }
9461                 }
9462                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9463                 return 1;
9464         }
9465         for (i = 0; i < NOPTS; i++) {
9466                 if (val) {
9467                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9468                 } else {
9469                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9470                 }
9471         }
9472         return 0;
9473 }
9474 static void
9475 setoption(int flag, int val)
9476 {
9477         int i;
9478
9479         for (i = 0; i < NOPTS; i++) {
9480                 if (optletters(i) == flag) {
9481                         optlist[i] = val;
9482                         return;
9483                 }
9484         }
9485         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9486         /* NOTREACHED */
9487 }
9488 static int
9489 options(int cmdline)
9490 {
9491         char *p;
9492         int val;
9493         int c;
9494
9495         if (cmdline)
9496                 minusc = NULL;
9497         while ((p = *argptr) != NULL) {
9498                 c = *p++;
9499                 if (c != '-' && c != '+')
9500                         break;
9501                 argptr++;
9502                 val = 0; /* val = 0 if c == '+' */
9503                 if (c == '-') {
9504                         val = 1;
9505                         if (p[0] == '\0' || LONE_DASH(p)) {
9506                                 if (!cmdline) {
9507                                         /* "-" means turn off -x and -v */
9508                                         if (p[0] == '\0')
9509                                                 xflag = vflag = 0;
9510                                         /* "--" means reset params */
9511                                         else if (*argptr == NULL)
9512                                                 setparam(argptr);
9513                                 }
9514                                 break;    /* "-" or  "--" terminates options */
9515                         }
9516                 }
9517                 /* first char was + or - */
9518                 while ((c = *p++) != '\0') {
9519                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9520                         if (c == 'c' && cmdline) {
9521                                 minusc = p;     /* command is after shell args */
9522                         } else if (c == 'o') {
9523                                 if (plus_minus_o(*argptr, val)) {
9524                                         /* it already printed err message */
9525                                         return 1; /* error */
9526                                 }
9527                                 if (*argptr)
9528                                         argptr++;
9529                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9530                                 isloginsh = 1;
9531                         /* bash does not accept +-login, we also won't */
9532                         } else if (cmdline && val && (c == '-')) { /* long options */
9533                                 if (strcmp(p, "login") == 0)
9534                                         isloginsh = 1;
9535                                 break;
9536                         } else {
9537                                 setoption(c, val);
9538                         }
9539                 }
9540         }
9541         return 0;
9542 }
9543
9544 /*
9545  * The shift builtin command.
9546  */
9547 static int
9548 shiftcmd(int argc UNUSED_PARAM, char **argv)
9549 {
9550         int n;
9551         char **ap1, **ap2;
9552
9553         n = 1;
9554         if (argv[1])
9555                 n = number(argv[1]);
9556         if (n > shellparam.nparam)
9557                 n = shellparam.nparam;
9558         INT_OFF;
9559         shellparam.nparam -= n;
9560         for (ap1 = shellparam.p; --n >= 0; ap1++) {
9561                 if (shellparam.malloced)
9562                         free(*ap1);
9563         }
9564         ap2 = shellparam.p;
9565         while ((*ap2++ = *ap1++) != NULL)
9566                 continue;
9567 #if ENABLE_ASH_GETOPTS
9568         shellparam.optind = 1;
9569         shellparam.optoff = -1;
9570 #endif
9571         INT_ON;
9572         return 0;
9573 }
9574
9575 /*
9576  * POSIX requires that 'set' (but not export or readonly) output the
9577  * variables in lexicographic order - by the locale's collating order (sigh).
9578  * Maybe we could keep them in an ordered balanced binary tree
9579  * instead of hashed lists.
9580  * For now just roll 'em through qsort for printing...
9581  */
9582 static int
9583 showvars(const char *sep_prefix, int on, int off)
9584 {
9585         const char *sep;
9586         char **ep, **epend;
9587
9588         ep = listvars(on, off, &epend);
9589         qsort(ep, epend - ep, sizeof(char *), vpcmp);
9590
9591         sep = *sep_prefix ? " " : sep_prefix;
9592
9593         for (; ep < epend; ep++) {
9594                 const char *p;
9595                 const char *q;
9596
9597                 p = strchrnul(*ep, '=');
9598                 q = nullstr;
9599                 if (*p)
9600                         q = single_quote(++p);
9601                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9602         }
9603         return 0;
9604 }
9605
9606 /*
9607  * The set command builtin.
9608  */
9609 static int
9610 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9611 {
9612         int retval;
9613
9614         if (!argv[1])
9615                 return showvars(nullstr, 0, VUNSET);
9616         INT_OFF;
9617         retval = 1;
9618         if (!options(0)) { /* if no parse error... */
9619                 retval = 0;
9620                 optschanged();
9621                 if (*argptr != NULL) {
9622                         setparam(argptr);
9623                 }
9624         }
9625         INT_ON;
9626         return retval;
9627 }
9628
9629 #if ENABLE_ASH_RANDOM_SUPPORT
9630 static void
9631 change_random(const char *value)
9632 {
9633         /* Galois LFSR parameter */
9634         /* Taps at 32 31 29 1: */
9635         enum { MASK = 0x8000000b };
9636         /* Another example - taps at 32 31 30 10: */
9637         /* MASK = 0x00400007 */
9638
9639         if (value == NULL) {
9640                 /* "get", generate */
9641                 uint32_t t;
9642
9643                 /* LCG has period of 2^32 and alternating lowest bit */
9644                 random_LCG = 1664525 * random_LCG + 1013904223;
9645                 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9646                 t = (random_galois_LFSR << 1);
9647                 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9648                         t ^= MASK;
9649                 random_galois_LFSR = t;
9650                 /* Both are weak, combining them gives better randomness
9651                  * and ~2^64 period. & 0x7fff is probably bash compat
9652                  * for $RANDOM range. Combining with subtraction is
9653                  * just for fun. + and ^ would work equally well. */
9654                 t = (t - random_LCG) & 0x7fff;
9655                 /* set without recursion */
9656                 setvar(vrandom.text, utoa(t), VNOFUNC);
9657                 vrandom.flags &= ~VNOFUNC;
9658         } else {
9659                 /* set/reset */
9660                 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9661         }
9662 }
9663 #endif
9664
9665 #if ENABLE_ASH_GETOPTS
9666 static int
9667 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9668 {
9669         char *p, *q;
9670         char c = '?';
9671         int done = 0;
9672         int err = 0;
9673         char s[12];
9674         char **optnext;
9675
9676         if (*param_optind < 1)
9677                 return 1;
9678         optnext = optfirst + *param_optind - 1;
9679
9680         if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9681                 p = NULL;
9682         else
9683                 p = optnext[-1] + *optoff;
9684         if (p == NULL || *p == '\0') {
9685                 /* Current word is done, advance */
9686                 p = *optnext;
9687                 if (p == NULL || *p != '-' || *++p == '\0') {
9688  atend:
9689                         p = NULL;
9690                         done = 1;
9691                         goto out;
9692                 }
9693                 optnext++;
9694                 if (LONE_DASH(p))        /* check for "--" */
9695                         goto atend;
9696         }
9697
9698         c = *p++;
9699         for (q = optstr; *q != c;) {
9700                 if (*q == '\0') {
9701                         if (optstr[0] == ':') {
9702                                 s[0] = c;
9703                                 s[1] = '\0';
9704                                 err |= setvarsafe("OPTARG", s, 0);
9705                         } else {
9706                                 fprintf(stderr, "Illegal option -%c\n", c);
9707                                 unsetvar("OPTARG");
9708                         }
9709                         c = '?';
9710                         goto out;
9711                 }
9712                 if (*++q == ':')
9713                         q++;
9714         }
9715
9716         if (*++q == ':') {
9717                 if (*p == '\0' && (p = *optnext) == NULL) {
9718                         if (optstr[0] == ':') {
9719                                 s[0] = c;
9720                                 s[1] = '\0';
9721                                 err |= setvarsafe("OPTARG", s, 0);
9722                                 c = ':';
9723                         } else {
9724                                 fprintf(stderr, "No arg for -%c option\n", c);
9725                                 unsetvar("OPTARG");
9726                                 c = '?';
9727                         }
9728                         goto out;
9729                 }
9730
9731                 if (p == *optnext)
9732                         optnext++;
9733                 err |= setvarsafe("OPTARG", p, 0);
9734                 p = NULL;
9735         } else
9736                 err |= setvarsafe("OPTARG", nullstr, 0);
9737  out:
9738         *optoff = p ? p - *(optnext - 1) : -1;
9739         *param_optind = optnext - optfirst + 1;
9740         fmtstr(s, sizeof(s), "%d", *param_optind);
9741         err |= setvarsafe("OPTIND", s, VNOFUNC);
9742         s[0] = c;
9743         s[1] = '\0';
9744         err |= setvarsafe(optvar, s, 0);
9745         if (err) {
9746                 *param_optind = 1;
9747                 *optoff = -1;
9748                 flush_stdout_stderr();
9749                 raise_exception(EXERROR);
9750         }
9751         return done;
9752 }
9753
9754 /*
9755  * The getopts builtin.  Shellparam.optnext points to the next argument
9756  * to be processed.  Shellparam.optptr points to the next character to
9757  * be processed in the current argument.  If shellparam.optnext is NULL,
9758  * then it's the first time getopts has been called.
9759  */
9760 static int
9761 getoptscmd(int argc, char **argv)
9762 {
9763         char **optbase;
9764
9765         if (argc < 3)
9766                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9767         if (argc == 3) {
9768                 optbase = shellparam.p;
9769                 if (shellparam.optind > shellparam.nparam + 1) {
9770                         shellparam.optind = 1;
9771                         shellparam.optoff = -1;
9772                 }
9773         } else {
9774                 optbase = &argv[3];
9775                 if (shellparam.optind > argc - 2) {
9776                         shellparam.optind = 1;
9777                         shellparam.optoff = -1;
9778                 }
9779         }
9780
9781         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9782                         &shellparam.optoff);
9783 }
9784 #endif /* ASH_GETOPTS */
9785
9786
9787 /* ============ Shell parser */
9788
9789 struct heredoc {
9790         struct heredoc *next;   /* next here document in list */
9791         union node *here;       /* redirection node */
9792         char *eofmark;          /* string indicating end of input */
9793         smallint striptabs;     /* if set, strip leading tabs */
9794 };
9795
9796 static smallint tokpushback;           /* last token pushed back */
9797 static smallint parsebackquote;        /* nonzero if we are inside backquotes */
9798 static smallint quoteflag;             /* set if (part of) last token was quoted */
9799 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
9800 static struct heredoc *heredoclist;    /* list of here documents to read */
9801 static char *wordtext;                 /* text of last word returned by readtoken */
9802 static struct nodelist *backquotelist;
9803 static union node *redirnode;
9804 static struct heredoc *heredoc;
9805 /*
9806  * NEOF is returned by parsecmd when it encounters an end of file.  It
9807  * must be distinct from NULL, so we use the address of a variable that
9808  * happens to be handy.
9809  */
9810 #define NEOF ((union node *)&tokpushback)
9811
9812 static void raise_error_syntax(const char *) NORETURN;
9813 static void
9814 raise_error_syntax(const char *msg)
9815 {
9816         ash_msg_and_raise_error("syntax error: %s", msg);
9817         /* NOTREACHED */
9818 }
9819
9820 /*
9821  * Called when an unexpected token is read during the parse.  The argument
9822  * is the token that is expected, or -1 if more than one type of token can
9823  * occur at this point.
9824  */
9825 static void raise_error_unexpected_syntax(int) NORETURN;
9826 static void
9827 raise_error_unexpected_syntax(int token)
9828 {
9829         char msg[64];
9830         int l;
9831
9832         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9833         if (token >= 0)
9834                 sprintf(msg + l, " (expecting %s)", tokname(token));
9835         raise_error_syntax(msg);
9836         /* NOTREACHED */
9837 }
9838
9839 #define EOFMARKLEN 79
9840
9841 /* parsing is heavily cross-recursive, need these forward decls */
9842 static union node *andor(void);
9843 static union node *pipeline(void);
9844 static union node *parse_command(void);
9845 static void parseheredoc(void);
9846 static char peektoken(void);
9847 static int readtoken(void);
9848
9849 static union node *
9850 list(int nlflag)
9851 {
9852         union node *n1, *n2, *n3;
9853         int tok;
9854
9855         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9856         if (nlflag == 2 && peektoken())
9857                 return NULL;
9858         n1 = NULL;
9859         for (;;) {
9860                 n2 = andor();
9861                 tok = readtoken();
9862                 if (tok == TBACKGND) {
9863                         if (n2->type == NPIPE) {
9864                                 n2->npipe.backgnd = 1;
9865                         } else {
9866                                 if (n2->type != NREDIR) {
9867                                         n3 = stzalloc(sizeof(struct nredir));
9868                                         n3->nredir.n = n2;
9869                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
9870                                         n2 = n3;
9871                                 }
9872                                 n2->type = NBACKGND;
9873                         }
9874                 }
9875                 if (n1 == NULL) {
9876                         n1 = n2;
9877                 } else {
9878                         n3 = stzalloc(sizeof(struct nbinary));
9879                         n3->type = NSEMI;
9880                         n3->nbinary.ch1 = n1;
9881                         n3->nbinary.ch2 = n2;
9882                         n1 = n3;
9883                 }
9884                 switch (tok) {
9885                 case TBACKGND:
9886                 case TSEMI:
9887                         tok = readtoken();
9888                         /* fall through */
9889                 case TNL:
9890                         if (tok == TNL) {
9891                                 parseheredoc();
9892                                 if (nlflag == 1)
9893                                         return n1;
9894                         } else {
9895                                 tokpushback = 1;
9896                         }
9897                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9898                         if (peektoken())
9899                                 return n1;
9900                         break;
9901                 case TEOF:
9902                         if (heredoclist)
9903                                 parseheredoc();
9904                         else
9905                                 pungetc();              /* push back EOF on input */
9906                         return n1;
9907                 default:
9908                         if (nlflag == 1)
9909                                 raise_error_unexpected_syntax(-1);
9910                         tokpushback = 1;
9911                         return n1;
9912                 }
9913         }
9914 }
9915
9916 static union node *
9917 andor(void)
9918 {
9919         union node *n1, *n2, *n3;
9920         int t;
9921
9922         n1 = pipeline();
9923         for (;;) {
9924                 t = readtoken();
9925                 if (t == TAND) {
9926                         t = NAND;
9927                 } else if (t == TOR) {
9928                         t = NOR;
9929                 } else {
9930                         tokpushback = 1;
9931                         return n1;
9932                 }
9933                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9934                 n2 = pipeline();
9935                 n3 = stzalloc(sizeof(struct nbinary));
9936                 n3->type = t;
9937                 n3->nbinary.ch1 = n1;
9938                 n3->nbinary.ch2 = n2;
9939                 n1 = n3;
9940         }
9941 }
9942
9943 static union node *
9944 pipeline(void)
9945 {
9946         union node *n1, *n2, *pipenode;
9947         struct nodelist *lp, *prev;
9948         int negate;
9949
9950         negate = 0;
9951         TRACE(("pipeline: entered\n"));
9952         if (readtoken() == TNOT) {
9953                 negate = !negate;
9954                 checkkwd = CHKKWD | CHKALIAS;
9955         } else
9956                 tokpushback = 1;
9957         n1 = parse_command();
9958         if (readtoken() == TPIPE) {
9959                 pipenode = stzalloc(sizeof(struct npipe));
9960                 pipenode->type = NPIPE;
9961                 /*pipenode->npipe.backgnd = 0; - stzalloc did it */
9962                 lp = stzalloc(sizeof(struct nodelist));
9963                 pipenode->npipe.cmdlist = lp;
9964                 lp->n = n1;
9965                 do {
9966                         prev = lp;
9967                         lp = stzalloc(sizeof(struct nodelist));
9968                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9969                         lp->n = parse_command();
9970                         prev->next = lp;
9971                 } while (readtoken() == TPIPE);
9972                 lp->next = NULL;
9973                 n1 = pipenode;
9974         }
9975         tokpushback = 1;
9976         if (negate) {
9977                 n2 = stzalloc(sizeof(struct nnot));
9978                 n2->type = NNOT;
9979                 n2->nnot.com = n1;
9980                 return n2;
9981         }
9982         return n1;
9983 }
9984
9985 static union node *
9986 makename(void)
9987 {
9988         union node *n;
9989
9990         n = stzalloc(sizeof(struct narg));
9991         n->type = NARG;
9992         /*n->narg.next = NULL; - stzalloc did it */
9993         n->narg.text = wordtext;
9994         n->narg.backquote = backquotelist;
9995         return n;
9996 }
9997
9998 static void
9999 fixredir(union node *n, const char *text, int err)
10000 {
10001         TRACE(("Fix redir %s %d\n", text, err));
10002         if (!err)
10003                 n->ndup.vname = NULL;
10004
10005         if (isdigit(text[0]) && text[1] == '\0')
10006                 n->ndup.dupfd = text[0] - '0';
10007         else if (LONE_DASH(text))
10008                 n->ndup.dupfd = -1;
10009         else {
10010                 if (err)
10011                         raise_error_syntax("Bad fd number");
10012                 n->ndup.vname = makename();
10013         }
10014 }
10015
10016 /*
10017  * Returns true if the text contains nothing to expand (no dollar signs
10018  * or backquotes).
10019  */
10020 static int
10021 noexpand(char *text)
10022 {
10023         char *p;
10024         char c;
10025
10026         p = text;
10027         while ((c = *p++) != '\0') {
10028                 if (c == CTLQUOTEMARK)
10029                         continue;
10030                 if (c == CTLESC)
10031                         p++;
10032                 else if (SIT(c, BASESYNTAX) == CCTL)
10033                         return 0;
10034         }
10035         return 1;
10036 }
10037
10038 static void
10039 parsefname(void)
10040 {
10041         union node *n = redirnode;
10042
10043         if (readtoken() != TWORD)
10044                 raise_error_unexpected_syntax(-1);
10045         if (n->type == NHERE) {
10046                 struct heredoc *here = heredoc;
10047                 struct heredoc *p;
10048                 int i;
10049
10050                 if (quoteflag == 0)
10051                         n->type = NXHERE;
10052                 TRACE(("Here document %d\n", n->type));
10053                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10054                         raise_error_syntax("Illegal eof marker for << redirection");
10055                 rmescapes(wordtext);
10056                 here->eofmark = wordtext;
10057                 here->next = NULL;
10058                 if (heredoclist == NULL)
10059                         heredoclist = here;
10060                 else {
10061                         for (p = heredoclist; p->next; p = p->next)
10062                                 continue;
10063                         p->next = here;
10064                 }
10065         } else if (n->type == NTOFD || n->type == NFROMFD) {
10066                 fixredir(n, wordtext, 0);
10067         } else {
10068                 n->nfile.fname = makename();
10069         }
10070 }
10071
10072 static union node *
10073 simplecmd(void)
10074 {
10075         union node *args, **app;
10076         union node *n = NULL;
10077         union node *vars, **vpp;
10078         union node **rpp, *redir;
10079         int savecheckkwd;
10080 #if ENABLE_ASH_BASH_COMPAT
10081         smallint double_brackets_flag = 0;
10082 #endif
10083
10084         args = NULL;
10085         app = &args;
10086         vars = NULL;
10087         vpp = &vars;
10088         redir = NULL;
10089         rpp = &redir;
10090
10091         savecheckkwd = CHKALIAS;
10092         for (;;) {
10093                 int t;
10094                 checkkwd = savecheckkwd;
10095                 t = readtoken();
10096                 switch (t) {
10097 #if ENABLE_ASH_BASH_COMPAT
10098                 case TAND: /* "&&" */
10099                 case TOR: /* "||" */
10100                         if (!double_brackets_flag) {
10101                                 tokpushback = 1;
10102                                 goto out;
10103                         }
10104                         wordtext = (char *) (t == TAND ? "-a" : "-o");
10105 #endif
10106                 case TWORD:
10107                         n = stzalloc(sizeof(struct narg));
10108                         n->type = NARG;
10109                         /*n->narg.next = NULL; - stzalloc did it */
10110                         n->narg.text = wordtext;
10111 #if ENABLE_ASH_BASH_COMPAT
10112                         if (strcmp("[[", wordtext) == 0)
10113                                 double_brackets_flag = 1;
10114                         else if (strcmp("]]", wordtext) == 0)
10115                                 double_brackets_flag = 0;
10116 #endif
10117                         n->narg.backquote = backquotelist;
10118                         if (savecheckkwd && isassignment(wordtext)) {
10119                                 *vpp = n;
10120                                 vpp = &n->narg.next;
10121                         } else {
10122                                 *app = n;
10123                                 app = &n->narg.next;
10124                                 savecheckkwd = 0;
10125                         }
10126                         break;
10127                 case TREDIR:
10128                         *rpp = n = redirnode;
10129                         rpp = &n->nfile.next;
10130                         parsefname();   /* read name of redirection file */
10131                         break;
10132                 case TLP:
10133                         if (args && app == &args->narg.next
10134                          && !vars && !redir
10135                         ) {
10136                                 struct builtincmd *bcmd;
10137                                 const char *name;
10138
10139                                 /* We have a function */
10140                                 if (readtoken() != TRP)
10141                                         raise_error_unexpected_syntax(TRP);
10142                                 name = n->narg.text;
10143                                 if (!goodname(name)
10144                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10145                                 ) {
10146                                         raise_error_syntax("Bad function name");
10147                                 }
10148                                 n->type = NDEFUN;
10149                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10150                                 n->narg.next = parse_command();
10151                                 return n;
10152                         }
10153                         /* fall through */
10154                 default:
10155                         tokpushback = 1;
10156                         goto out;
10157                 }
10158         }
10159  out:
10160         *app = NULL;
10161         *vpp = NULL;
10162         *rpp = NULL;
10163         n = stzalloc(sizeof(struct ncmd));
10164         n->type = NCMD;
10165         n->ncmd.args = args;
10166         n->ncmd.assign = vars;
10167         n->ncmd.redirect = redir;
10168         return n;
10169 }
10170
10171 static union node *
10172 parse_command(void)
10173 {
10174         union node *n1, *n2;
10175         union node *ap, **app;
10176         union node *cp, **cpp;
10177         union node *redir, **rpp;
10178         union node **rpp2;
10179         int t;
10180
10181         redir = NULL;
10182         rpp2 = &redir;
10183
10184         switch (readtoken()) {
10185         default:
10186                 raise_error_unexpected_syntax(-1);
10187                 /* NOTREACHED */
10188         case TIF:
10189                 n1 = stzalloc(sizeof(struct nif));
10190                 n1->type = NIF;
10191                 n1->nif.test = list(0);
10192                 if (readtoken() != TTHEN)
10193                         raise_error_unexpected_syntax(TTHEN);
10194                 n1->nif.ifpart = list(0);
10195                 n2 = n1;
10196                 while (readtoken() == TELIF) {
10197                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
10198                         n2 = n2->nif.elsepart;
10199                         n2->type = NIF;
10200                         n2->nif.test = list(0);
10201                         if (readtoken() != TTHEN)
10202                                 raise_error_unexpected_syntax(TTHEN);
10203                         n2->nif.ifpart = list(0);
10204                 }
10205                 if (lasttoken == TELSE)
10206                         n2->nif.elsepart = list(0);
10207                 else {
10208                         n2->nif.elsepart = NULL;
10209                         tokpushback = 1;
10210                 }
10211                 t = TFI;
10212                 break;
10213         case TWHILE:
10214         case TUNTIL: {
10215                 int got;
10216                 n1 = stzalloc(sizeof(struct nbinary));
10217                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10218                 n1->nbinary.ch1 = list(0);
10219                 got = readtoken();
10220                 if (got != TDO) {
10221                         TRACE(("expecting DO got %s %s\n", tokname(got),
10222                                         got == TWORD ? wordtext : ""));
10223                         raise_error_unexpected_syntax(TDO);
10224                 }
10225                 n1->nbinary.ch2 = list(0);
10226                 t = TDONE;
10227                 break;
10228         }
10229         case TFOR:
10230                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
10231                         raise_error_syntax("Bad for loop variable");
10232                 n1 = stzalloc(sizeof(struct nfor));
10233                 n1->type = NFOR;
10234                 n1->nfor.var = wordtext;
10235                 checkkwd = CHKKWD | CHKALIAS;
10236                 if (readtoken() == TIN) {
10237                         app = &ap;
10238                         while (readtoken() == TWORD) {
10239                                 n2 = stzalloc(sizeof(struct narg));
10240                                 n2->type = NARG;
10241                                 /*n2->narg.next = NULL; - stzalloc did it */
10242                                 n2->narg.text = wordtext;
10243                                 n2->narg.backquote = backquotelist;
10244                                 *app = n2;
10245                                 app = &n2->narg.next;
10246                         }
10247                         *app = NULL;
10248                         n1->nfor.args = ap;
10249                         if (lasttoken != TNL && lasttoken != TSEMI)
10250                                 raise_error_unexpected_syntax(-1);
10251                 } else {
10252                         n2 = stzalloc(sizeof(struct narg));
10253                         n2->type = NARG;
10254                         /*n2->narg.next = NULL; - stzalloc did it */
10255                         n2->narg.text = (char *)dolatstr;
10256                         /*n2->narg.backquote = NULL;*/
10257                         n1->nfor.args = n2;
10258                         /*
10259                          * Newline or semicolon here is optional (but note
10260                          * that the original Bourne shell only allowed NL).
10261                          */
10262                         if (lasttoken != TNL && lasttoken != TSEMI)
10263                                 tokpushback = 1;
10264                 }
10265                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10266                 if (readtoken() != TDO)
10267                         raise_error_unexpected_syntax(TDO);
10268                 n1->nfor.body = list(0);
10269                 t = TDONE;
10270                 break;
10271         case TCASE:
10272                 n1 = stzalloc(sizeof(struct ncase));
10273                 n1->type = NCASE;
10274                 if (readtoken() != TWORD)
10275                         raise_error_unexpected_syntax(TWORD);
10276                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10277                 n2->type = NARG;
10278                 /*n2->narg.next = NULL; - stzalloc did it */
10279                 n2->narg.text = wordtext;
10280                 n2->narg.backquote = backquotelist;
10281                 do {
10282                         checkkwd = CHKKWD | CHKALIAS;
10283                 } while (readtoken() == TNL);
10284                 if (lasttoken != TIN)
10285                         raise_error_unexpected_syntax(TIN);
10286                 cpp = &n1->ncase.cases;
10287  next_case:
10288                 checkkwd = CHKNL | CHKKWD;
10289                 t = readtoken();
10290                 while (t != TESAC) {
10291                         if (lasttoken == TLP)
10292                                 readtoken();
10293                         *cpp = cp = stzalloc(sizeof(struct nclist));
10294                         cp->type = NCLIST;
10295                         app = &cp->nclist.pattern;
10296                         for (;;) {
10297                                 *app = ap = stzalloc(sizeof(struct narg));
10298                                 ap->type = NARG;
10299                                 /*ap->narg.next = NULL; - stzalloc did it */
10300                                 ap->narg.text = wordtext;
10301                                 ap->narg.backquote = backquotelist;
10302                                 if (readtoken() != TPIPE)
10303                                         break;
10304                                 app = &ap->narg.next;
10305                                 readtoken();
10306                         }
10307                         //ap->narg.next = NULL;
10308                         if (lasttoken != TRP)
10309                                 raise_error_unexpected_syntax(TRP);
10310                         cp->nclist.body = list(2);
10311
10312                         cpp = &cp->nclist.next;
10313
10314                         checkkwd = CHKNL | CHKKWD;
10315                         t = readtoken();
10316                         if (t != TESAC) {
10317                                 if (t != TENDCASE)
10318                                         raise_error_unexpected_syntax(TENDCASE);
10319                                 goto next_case;
10320                         }
10321                 }
10322                 *cpp = NULL;
10323                 goto redir;
10324         case TLP:
10325                 n1 = stzalloc(sizeof(struct nredir));
10326                 n1->type = NSUBSHELL;
10327                 n1->nredir.n = list(0);
10328                 /*n1->nredir.redirect = NULL; - stzalloc did it */
10329                 t = TRP;
10330                 break;
10331         case TBEGIN:
10332                 n1 = list(0);
10333                 t = TEND;
10334                 break;
10335         case TWORD:
10336         case TREDIR:
10337                 tokpushback = 1;
10338                 return simplecmd();
10339         }
10340
10341         if (readtoken() != t)
10342                 raise_error_unexpected_syntax(t);
10343
10344  redir:
10345         /* Now check for redirection which may follow command */
10346         checkkwd = CHKKWD | CHKALIAS;
10347         rpp = rpp2;
10348         while (readtoken() == TREDIR) {
10349                 *rpp = n2 = redirnode;
10350                 rpp = &n2->nfile.next;
10351                 parsefname();
10352         }
10353         tokpushback = 1;
10354         *rpp = NULL;
10355         if (redir) {
10356                 if (n1->type != NSUBSHELL) {
10357                         n2 = stzalloc(sizeof(struct nredir));
10358                         n2->type = NREDIR;
10359                         n2->nredir.n = n1;
10360                         n1 = n2;
10361                 }
10362                 n1->nredir.redirect = redir;
10363         }
10364         return n1;
10365 }
10366
10367 #if ENABLE_ASH_BASH_COMPAT
10368 static int decode_dollar_squote(void)
10369 {
10370         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10371         int c, cnt;
10372         char *p;
10373         char buf[4];
10374
10375         c = pgetc();
10376         p = strchr(C_escapes, c);
10377         if (p) {
10378                 buf[0] = c;
10379                 p = buf;
10380                 cnt = 3;
10381                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10382                         do {
10383                                 c = pgetc();
10384                                 *++p = c;
10385                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
10386                         pungetc();
10387                 } else if (c == 'x') { /* \xHH */
10388                         do {
10389                                 c = pgetc();
10390                                 *++p = c;
10391                         } while (isxdigit(c) && --cnt);
10392                         pungetc();
10393                         if (cnt == 3) { /* \x but next char is "bad" */
10394                                 c = 'x';
10395                                 goto unrecognized;
10396                         }
10397                 } else { /* simple seq like \\ or \t */
10398                         p++;
10399                 }
10400                 *p = '\0';
10401                 p = buf;
10402                 c = bb_process_escape_sequence((void*)&p);
10403         } else { /* unrecognized "\z": print both chars unless ' or " */
10404                 if (c != '\'' && c != '"') {
10405  unrecognized:
10406                         c |= 0x100; /* "please encode \, then me" */
10407                 }
10408         }
10409         return c;
10410 }
10411 #endif
10412
10413 /*
10414  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10415  * is not NULL, read a here document.  In the latter case, eofmark is the
10416  * word which marks the end of the document and striptabs is true if
10417  * leading tabs should be stripped from the document.  The argument firstc
10418  * is the first character of the input token or document.
10419  *
10420  * Because C does not have internal subroutines, I have simulated them
10421  * using goto's to implement the subroutine linkage.  The following macros
10422  * will run code that appears at the end of readtoken1.
10423  */
10424 #define CHECKEND()      {goto checkend; checkend_return:;}
10425 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10426 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10427 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10428 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10429 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10430 static int
10431 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10432 {
10433         /* NB: syntax parameter fits into smallint */
10434         int c = firstc;
10435         char *out;
10436         int len;
10437         char line[EOFMARKLEN + 1];
10438         struct nodelist *bqlist;
10439         smallint quotef;
10440         smallint dblquote;
10441         smallint oldstyle;
10442         smallint prevsyntax; /* syntax before arithmetic */
10443 #if ENABLE_ASH_EXPAND_PRMT
10444         smallint pssyntax;   /* we are expanding a prompt string */
10445 #endif
10446         int varnest;         /* levels of variables expansion */
10447         int arinest;         /* levels of arithmetic expansion */
10448         int parenlevel;      /* levels of parens in arithmetic */
10449         int dqvarnest;       /* levels of variables expansion within double quotes */
10450
10451         USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10452
10453 #if __GNUC__
10454         /* Avoid longjmp clobbering */
10455         (void) &out;
10456         (void) &quotef;
10457         (void) &dblquote;
10458         (void) &varnest;
10459         (void) &arinest;
10460         (void) &parenlevel;
10461         (void) &dqvarnest;
10462         (void) &oldstyle;
10463         (void) &prevsyntax;
10464         (void) &syntax;
10465 #endif
10466         startlinno = plinno;
10467         bqlist = NULL;
10468         quotef = 0;
10469         oldstyle = 0;
10470         prevsyntax = 0;
10471 #if ENABLE_ASH_EXPAND_PRMT
10472         pssyntax = (syntax == PSSYNTAX);
10473         if (pssyntax)
10474                 syntax = DQSYNTAX;
10475 #endif
10476         dblquote = (syntax == DQSYNTAX);
10477         varnest = 0;
10478         arinest = 0;
10479         parenlevel = 0;
10480         dqvarnest = 0;
10481
10482         STARTSTACKSTR(out);
10483         loop: { /* for each line, until end of word */
10484                 CHECKEND();     /* set c to PEOF if at end of here document */
10485                 for (;;) {      /* until end of line or end of word */
10486                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
10487                         switch (SIT(c, syntax)) {
10488                         case CNL:       /* '\n' */
10489                                 if (syntax == BASESYNTAX)
10490                                         goto endword;   /* exit outer loop */
10491                                 USTPUTC(c, out);
10492                                 plinno++;
10493                                 if (doprompt)
10494                                         setprompt(2);
10495                                 c = pgetc();
10496                                 goto loop;              /* continue outer loop */
10497                         case CWORD:
10498                                 USTPUTC(c, out);
10499                                 break;
10500                         case CCTL:
10501                                 if (eofmark == NULL || dblquote)
10502                                         USTPUTC(CTLESC, out);
10503 #if ENABLE_ASH_BASH_COMPAT
10504                                 if (c == '\\' && bash_dollar_squote) {
10505                                         c = decode_dollar_squote();
10506                                         if (c & 0x100) {
10507                                                 USTPUTC('\\', out);
10508                                                 c = (unsigned char)c;
10509                                         }
10510                                 }
10511 #endif
10512                                 USTPUTC(c, out);
10513                                 break;
10514                         case CBACK:     /* backslash */
10515                                 c = pgetc2();
10516                                 if (c == PEOF) {
10517                                         USTPUTC(CTLESC, out);
10518                                         USTPUTC('\\', out);
10519                                         pungetc();
10520                                 } else if (c == '\n') {
10521                                         if (doprompt)
10522                                                 setprompt(2);
10523                                 } else {
10524 #if ENABLE_ASH_EXPAND_PRMT
10525                                         if (c == '$' && pssyntax) {
10526                                                 USTPUTC(CTLESC, out);
10527                                                 USTPUTC('\\', out);
10528                                         }
10529 #endif
10530                                         if (dblquote && c != '\\'
10531                                          && c != '`' && c != '$'
10532                                          && (c != '"' || eofmark != NULL)
10533                                         ) {
10534                                                 USTPUTC(CTLESC, out);
10535                                                 USTPUTC('\\', out);
10536                                         }
10537                                         if (SIT(c, SQSYNTAX) == CCTL)
10538                                                 USTPUTC(CTLESC, out);
10539                                         USTPUTC(c, out);
10540                                         quotef = 1;
10541                                 }
10542                                 break;
10543                         case CSQUOTE:
10544                                 syntax = SQSYNTAX;
10545  quotemark:
10546                                 if (eofmark == NULL) {
10547                                         USTPUTC(CTLQUOTEMARK, out);
10548                                 }
10549                                 break;
10550                         case CDQUOTE:
10551                                 syntax = DQSYNTAX;
10552                                 dblquote = 1;
10553                                 goto quotemark;
10554                         case CENDQUOTE:
10555                                 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10556                                 if (eofmark != NULL && arinest == 0
10557                                  && varnest == 0
10558                                 ) {
10559                                         USTPUTC(c, out);
10560                                 } else {
10561                                         if (dqvarnest == 0) {
10562                                                 syntax = BASESYNTAX;
10563                                                 dblquote = 0;
10564                                         }
10565                                         quotef = 1;
10566                                         goto quotemark;
10567                                 }
10568                                 break;
10569                         case CVAR:      /* '$' */
10570                                 PARSESUB();             /* parse substitution */
10571                                 break;
10572                         case CENDVAR:   /* '}' */
10573                                 if (varnest > 0) {
10574                                         varnest--;
10575                                         if (dqvarnest > 0) {
10576                                                 dqvarnest--;
10577                                         }
10578                                         USTPUTC(CTLENDVAR, out);
10579                                 } else {
10580                                         USTPUTC(c, out);
10581                                 }
10582                                 break;
10583 #if ENABLE_ASH_MATH_SUPPORT
10584                         case CLP:       /* '(' in arithmetic */
10585                                 parenlevel++;
10586                                 USTPUTC(c, out);
10587                                 break;
10588                         case CRP:       /* ')' in arithmetic */
10589                                 if (parenlevel > 0) {
10590                                         USTPUTC(c, out);
10591                                         --parenlevel;
10592                                 } else {
10593                                         if (pgetc() == ')') {
10594                                                 if (--arinest == 0) {
10595                                                         USTPUTC(CTLENDARI, out);
10596                                                         syntax = prevsyntax;
10597                                                         dblquote = (syntax == DQSYNTAX);
10598                                                 } else
10599                                                         USTPUTC(')', out);
10600                                         } else {
10601                                                 /*
10602                                                  * unbalanced parens
10603                                                  *  (don't 2nd guess - no error)
10604                                                  */
10605                                                 pungetc();
10606                                                 USTPUTC(')', out);
10607                                         }
10608                                 }
10609                                 break;
10610 #endif
10611                         case CBQUOTE:   /* '`' */
10612                                 PARSEBACKQOLD();
10613                                 break;
10614                         case CENDFILE:
10615                                 goto endword;           /* exit outer loop */
10616                         case CIGN:
10617                                 break;
10618                         default:
10619                                 if (varnest == 0)
10620                                         goto endword;   /* exit outer loop */
10621 #if ENABLE_ASH_ALIAS
10622                                 if (c != PEOA)
10623 #endif
10624                                         USTPUTC(c, out);
10625
10626                         }
10627                         c = pgetc_macro();
10628                 } /* for(;;) */
10629         }
10630  endword:
10631 #if ENABLE_ASH_MATH_SUPPORT
10632         if (syntax == ARISYNTAX)
10633                 raise_error_syntax("Missing '))'");
10634 #endif
10635         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10636                 raise_error_syntax("Unterminated quoted string");
10637         if (varnest != 0) {
10638                 startlinno = plinno;
10639                 /* { */
10640                 raise_error_syntax("Missing '}'");
10641         }
10642         USTPUTC('\0', out);
10643         len = out - (char *)stackblock();
10644         out = stackblock();
10645         if (eofmark == NULL) {
10646                 if ((c == '>' || c == '<')
10647                  && quotef == 0
10648                  && len <= 2
10649                  && (*out == '\0' || isdigit(*out))
10650                 ) {
10651                         PARSEREDIR();
10652                         lasttoken = TREDIR;
10653                         return lasttoken;
10654                 }
10655                 pungetc();
10656         }
10657         quoteflag = quotef;
10658         backquotelist = bqlist;
10659         grabstackblock(len);
10660         wordtext = out;
10661         lasttoken = TWORD;
10662         return lasttoken;
10663 /* end of readtoken routine */
10664
10665 /*
10666  * Check to see whether we are at the end of the here document.  When this
10667  * is called, c is set to the first character of the next input line.  If
10668  * we are at the end of the here document, this routine sets the c to PEOF.
10669  */
10670 checkend: {
10671         if (eofmark) {
10672 #if ENABLE_ASH_ALIAS
10673                 if (c == PEOA) {
10674                         c = pgetc2();
10675                 }
10676 #endif
10677                 if (striptabs) {
10678                         while (c == '\t') {
10679                                 c = pgetc2();
10680                         }
10681                 }
10682                 if (c == *eofmark) {
10683                         if (pfgets(line, sizeof(line)) != NULL) {
10684                                 char *p, *q;
10685
10686                                 p = line;
10687                                 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10688                                         continue;
10689                                 if (*p == '\n' && *q == '\0') {
10690                                         c = PEOF;
10691                                         plinno++;
10692                                         needprompt = doprompt;
10693                                 } else {
10694                                         pushstring(line, NULL);
10695                                 }
10696                         }
10697                 }
10698         }
10699         goto checkend_return;
10700 }
10701
10702 /*
10703  * Parse a redirection operator.  The variable "out" points to a string
10704  * specifying the fd to be redirected.  The variable "c" contains the
10705  * first character of the redirection operator.
10706  */
10707 parseredir: {
10708         char fd = *out;
10709         union node *np;
10710
10711         np = stzalloc(sizeof(struct nfile));
10712         if (c == '>') {
10713                 np->nfile.fd = 1;
10714                 c = pgetc();
10715                 if (c == '>')
10716                         np->type = NAPPEND;
10717                 else if (c == '|')
10718                         np->type = NCLOBBER;
10719                 else if (c == '&')
10720                         np->type = NTOFD;
10721                 else {
10722                         np->type = NTO;
10723                         pungetc();
10724                 }
10725         } else {        /* c == '<' */
10726                 /*np->nfile.fd = 0; - stzalloc did it */
10727                 c = pgetc();
10728                 switch (c) {
10729                 case '<':
10730                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
10731                                 np = stzalloc(sizeof(struct nhere));
10732                                 /*np->nfile.fd = 0; - stzalloc did it */
10733                         }
10734                         np->type = NHERE;
10735                         heredoc = stzalloc(sizeof(struct heredoc));
10736                         heredoc->here = np;
10737                         c = pgetc();
10738                         if (c == '-') {
10739                                 heredoc->striptabs = 1;
10740                         } else {
10741                                 /*heredoc->striptabs = 0; - stzalloc did it */
10742                                 pungetc();
10743                         }
10744                         break;
10745
10746                 case '&':
10747                         np->type = NFROMFD;
10748                         break;
10749
10750                 case '>':
10751                         np->type = NFROMTO;
10752                         break;
10753
10754                 default:
10755                         np->type = NFROM;
10756                         pungetc();
10757                         break;
10758                 }
10759         }
10760         if (fd != '\0')
10761                 np->nfile.fd = fd - '0';
10762         redirnode = np;
10763         goto parseredir_return;
10764 }
10765
10766 /*
10767  * Parse a substitution.  At this point, we have read the dollar sign
10768  * and nothing else.
10769  */
10770
10771 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10772  * (assuming ascii char codes, as the original implementation did) */
10773 #define is_special(c) \
10774         (((unsigned)(c) - 33 < 32) \
10775                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
10776 parsesub: {
10777         int subtype;
10778         int typeloc;
10779         int flags;
10780         char *p;
10781         static const char types[] ALIGN1 = "}-+?=";
10782
10783         c = pgetc();
10784         if (c <= PEOA_OR_PEOF
10785          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10786         ) {
10787 #if ENABLE_ASH_BASH_COMPAT
10788                 if (c == '\'')
10789                         bash_dollar_squote = 1;
10790                 else
10791 #endif
10792                         USTPUTC('$', out);
10793                 pungetc();
10794         } else if (c == '(') {  /* $(command) or $((arith)) */
10795                 if (pgetc() == '(') {
10796 #if ENABLE_ASH_MATH_SUPPORT
10797                         PARSEARITH();
10798 #else
10799                         raise_error_syntax("you disabled math support for $((arith)) syntax");
10800 #endif
10801                 } else {
10802                         pungetc();
10803                         PARSEBACKQNEW();
10804                 }
10805         } else {
10806                 USTPUTC(CTLVAR, out);
10807                 typeloc = out - (char *)stackblock();
10808                 USTPUTC(VSNORMAL, out);
10809                 subtype = VSNORMAL;
10810                 if (c == '{') {
10811                         c = pgetc();
10812                         if (c == '#') {
10813                                 c = pgetc();
10814                                 if (c == '}')
10815                                         c = '#';
10816                                 else
10817                                         subtype = VSLENGTH;
10818                         } else
10819                                 subtype = 0;
10820                 }
10821                 if (c > PEOA_OR_PEOF && is_name(c)) {
10822                         do {
10823                                 STPUTC(c, out);
10824                                 c = pgetc();
10825                         } while (c > PEOA_OR_PEOF && is_in_name(c));
10826                 } else if (isdigit(c)) {
10827                         do {
10828                                 STPUTC(c, out);
10829                                 c = pgetc();
10830                         } while (isdigit(c));
10831                 } else if (is_special(c)) {
10832                         USTPUTC(c, out);
10833                         c = pgetc();
10834                 } else
10835  badsub:                raise_error_syntax("Bad substitution");
10836
10837                 STPUTC('=', out);
10838                 flags = 0;
10839                 if (subtype == 0) {
10840                         switch (c) {
10841                         case ':':
10842                                 c = pgetc();
10843 #if ENABLE_ASH_BASH_COMPAT
10844                                 if (c == ':' || c == '$' || isdigit(c)) {
10845                                         pungetc();
10846                                         subtype = VSSUBSTR;
10847                                         break;
10848                                 }
10849 #endif
10850                                 flags = VSNUL;
10851                                 /*FALLTHROUGH*/
10852                         default:
10853                                 p = strchr(types, c);
10854                                 if (p == NULL)
10855                                         goto badsub;
10856                                 subtype = p - types + VSNORMAL;
10857                                 break;
10858                         case '%':
10859                         case '#': {
10860                                 int cc = c;
10861                                 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
10862                                 c = pgetc();
10863                                 if (c == cc)
10864                                         subtype++;
10865                                 else
10866                                         pungetc();
10867                                 break;
10868                         }
10869 #if ENABLE_ASH_BASH_COMPAT
10870                         case '/':
10871                                 subtype = VSREPLACE;
10872                                 c = pgetc();
10873                                 if (c == '/')
10874                                         subtype++; /* VSREPLACEALL */
10875                                 else
10876                                         pungetc();
10877                                 break;
10878 #endif
10879                         }
10880                 } else {
10881                         pungetc();
10882                 }
10883                 if (dblquote || arinest)
10884                         flags |= VSQUOTE;
10885                 *((char *)stackblock() + typeloc) = subtype | flags;
10886                 if (subtype != VSNORMAL) {
10887                         varnest++;
10888                         if (dblquote || arinest) {
10889                                 dqvarnest++;
10890                         }
10891                 }
10892         }
10893         goto parsesub_return;
10894 }
10895
10896 /*
10897  * Called to parse command substitutions.  Newstyle is set if the command
10898  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10899  * list of commands (passed by reference), and savelen is the number of
10900  * characters on the top of the stack which must be preserved.
10901  */
10902 parsebackq: {
10903         struct nodelist **nlpp;
10904         smallint savepbq;
10905         union node *n;
10906         char *volatile str;
10907         struct jmploc jmploc;
10908         struct jmploc *volatile savehandler;
10909         size_t savelen;
10910         smallint saveprompt = 0;
10911
10912 #ifdef __GNUC__
10913         (void) &saveprompt;
10914 #endif
10915         savepbq = parsebackquote;
10916         if (setjmp(jmploc.loc)) {
10917                 free(str);
10918                 parsebackquote = 0;
10919                 exception_handler = savehandler;
10920                 longjmp(exception_handler->loc, 1);
10921         }
10922         INT_OFF;
10923         str = NULL;
10924         savelen = out - (char *)stackblock();
10925         if (savelen > 0) {
10926                 str = ckmalloc(savelen);
10927                 memcpy(str, stackblock(), savelen);
10928         }
10929         savehandler = exception_handler;
10930         exception_handler = &jmploc;
10931         INT_ON;
10932         if (oldstyle) {
10933                 /* We must read until the closing backquote, giving special
10934                    treatment to some slashes, and then push the string and
10935                    reread it as input, interpreting it normally.  */
10936                 char *pout;
10937                 int pc;
10938                 size_t psavelen;
10939                 char *pstr;
10940
10941
10942                 STARTSTACKSTR(pout);
10943                 for (;;) {
10944                         if (needprompt) {
10945                                 setprompt(2);
10946                         }
10947                         pc = pgetc();
10948                         switch (pc) {
10949                         case '`':
10950                                 goto done;
10951
10952                         case '\\':
10953                                 pc = pgetc();
10954                                 if (pc == '\n') {
10955                                         plinno++;
10956                                         if (doprompt)
10957                                                 setprompt(2);
10958                                         /*
10959                                          * If eating a newline, avoid putting
10960                                          * the newline into the new character
10961                                          * stream (via the STPUTC after the
10962                                          * switch).
10963                                          */
10964                                         continue;
10965                                 }
10966                                 if (pc != '\\' && pc != '`' && pc != '$'
10967                                  && (!dblquote || pc != '"'))
10968                                         STPUTC('\\', pout);
10969                                 if (pc > PEOA_OR_PEOF) {
10970                                         break;
10971                                 }
10972                                 /* fall through */
10973
10974                         case PEOF:
10975 #if ENABLE_ASH_ALIAS
10976                         case PEOA:
10977 #endif
10978                                 startlinno = plinno;
10979                                 raise_error_syntax("EOF in backquote substitution");
10980
10981                         case '\n':
10982                                 plinno++;
10983                                 needprompt = doprompt;
10984                                 break;
10985
10986                         default:
10987                                 break;
10988                         }
10989                         STPUTC(pc, pout);
10990                 }
10991  done:
10992                 STPUTC('\0', pout);
10993                 psavelen = pout - (char *)stackblock();
10994                 if (psavelen > 0) {
10995                         pstr = grabstackstr(pout);
10996                         setinputstring(pstr);
10997                 }
10998         }
10999         nlpp = &bqlist;
11000         while (*nlpp)
11001                 nlpp = &(*nlpp)->next;
11002         *nlpp = stzalloc(sizeof(**nlpp));
11003         /* (*nlpp)->next = NULL; - stzalloc did it */
11004         parsebackquote = oldstyle;
11005
11006         if (oldstyle) {
11007                 saveprompt = doprompt;
11008                 doprompt = 0;
11009         }
11010
11011         n = list(2);
11012
11013         if (oldstyle)
11014                 doprompt = saveprompt;
11015         else if (readtoken() != TRP)
11016                 raise_error_unexpected_syntax(TRP);
11017
11018         (*nlpp)->n = n;
11019         if (oldstyle) {
11020                 /*
11021                  * Start reading from old file again, ignoring any pushed back
11022                  * tokens left from the backquote parsing
11023                  */
11024                 popfile();
11025                 tokpushback = 0;
11026         }
11027         while (stackblocksize() <= savelen)
11028                 growstackblock();
11029         STARTSTACKSTR(out);
11030         if (str) {
11031                 memcpy(out, str, savelen);
11032                 STADJUST(savelen, out);
11033                 INT_OFF;
11034                 free(str);
11035                 str = NULL;
11036                 INT_ON;
11037         }
11038         parsebackquote = savepbq;
11039         exception_handler = savehandler;
11040         if (arinest || dblquote)
11041                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11042         else
11043                 USTPUTC(CTLBACKQ, out);
11044         if (oldstyle)
11045                 goto parsebackq_oldreturn;
11046         goto parsebackq_newreturn;
11047 }
11048
11049 #if ENABLE_ASH_MATH_SUPPORT
11050 /*
11051  * Parse an arithmetic expansion (indicate start of one and set state)
11052  */
11053 parsearith: {
11054         if (++arinest == 1) {
11055                 prevsyntax = syntax;
11056                 syntax = ARISYNTAX;
11057                 USTPUTC(CTLARI, out);
11058                 if (dblquote)
11059                         USTPUTC('"', out);
11060                 else
11061                         USTPUTC(' ', out);
11062         } else {
11063                 /*
11064                  * we collapse embedded arithmetic expansion to
11065                  * parenthesis, which should be equivalent
11066                  */
11067                 USTPUTC('(', out);
11068         }
11069         goto parsearith_return;
11070 }
11071 #endif
11072
11073 } /* end of readtoken */
11074
11075 /*
11076  * Read the next input token.
11077  * If the token is a word, we set backquotelist to the list of cmds in
11078  *      backquotes.  We set quoteflag to true if any part of the word was
11079  *      quoted.
11080  * If the token is TREDIR, then we set redirnode to a structure containing
11081  *      the redirection.
11082  * In all cases, the variable startlinno is set to the number of the line
11083  *      on which the token starts.
11084  *
11085  * [Change comment:  here documents and internal procedures]
11086  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
11087  *  word parsing code into a separate routine.  In this case, readtoken
11088  *  doesn't need to have any internal procedures, but parseword does.
11089  *  We could also make parseoperator in essence the main routine, and
11090  *  have parseword (readtoken1?) handle both words and redirection.]
11091  */
11092 #define NEW_xxreadtoken
11093 #ifdef NEW_xxreadtoken
11094 /* singles must be first! */
11095 static const char xxreadtoken_chars[7] ALIGN1 = {
11096         '\n', '(', ')', '&', '|', ';', 0
11097 };
11098
11099 static const char xxreadtoken_tokens[] ALIGN1 = {
11100         TNL, TLP, TRP,          /* only single occurrence allowed */
11101         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11102         TEOF,                   /* corresponds to trailing nul */
11103         TAND, TOR, TENDCASE     /* if double occurrence */
11104 };
11105
11106 #define xxreadtoken_doubles \
11107         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
11108 #define xxreadtoken_singles \
11109         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
11110
11111 static int
11112 xxreadtoken(void)
11113 {
11114         int c;
11115
11116         if (tokpushback) {
11117                 tokpushback = 0;
11118                 return lasttoken;
11119         }
11120         if (needprompt) {
11121                 setprompt(2);
11122         }
11123         startlinno = plinno;
11124         for (;;) {                      /* until token or start of word found */
11125                 c = pgetc_macro();
11126
11127                 if ((c != ' ') && (c != '\t')
11128 #if ENABLE_ASH_ALIAS
11129                  && (c != PEOA)
11130 #endif
11131                 ) {
11132                         if (c == '#') {
11133                                 while ((c = pgetc()) != '\n' && c != PEOF)
11134                                         continue;
11135                                 pungetc();
11136                         } else if (c == '\\') {
11137                                 if (pgetc() != '\n') {
11138                                         pungetc();
11139                                         goto READTOKEN1;
11140                                 }
11141                                 startlinno = ++plinno;
11142                                 if (doprompt)
11143                                         setprompt(2);
11144                         } else {
11145                                 const char *p
11146                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11147
11148                                 if (c != PEOF) {
11149                                         if (c == '\n') {
11150                                                 plinno++;
11151                                                 needprompt = doprompt;
11152                                         }
11153
11154                                         p = strchr(xxreadtoken_chars, c);
11155                                         if (p == NULL) {
11156  READTOKEN1:
11157                                                 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11158                                         }
11159
11160                                         if ((size_t)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11161                                                 if (pgetc() == *p) {    /* double occurrence? */
11162                                                         p += xxreadtoken_doubles + 1;
11163                                                 } else {
11164                                                         pungetc();
11165                                                 }
11166                                         }
11167                                 }
11168                                 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11169                                 return lasttoken;
11170                         }
11171                 }
11172         } /* for */
11173 }
11174 #else
11175 #define RETURN(token)   return lasttoken = token
11176 static int
11177 xxreadtoken(void)
11178 {
11179         int c;
11180
11181         if (tokpushback) {
11182                 tokpushback = 0;
11183                 return lasttoken;
11184         }
11185         if (needprompt) {
11186                 setprompt(2);
11187         }
11188         startlinno = plinno;
11189         for (;;) {      /* until token or start of word found */
11190                 c = pgetc_macro();
11191                 switch (c) {
11192                 case ' ': case '\t':
11193 #if ENABLE_ASH_ALIAS
11194                 case PEOA:
11195 #endif
11196                         continue;
11197                 case '#':
11198                         while ((c = pgetc()) != '\n' && c != PEOF)
11199                                 continue;
11200                         pungetc();
11201                         continue;
11202                 case '\\':
11203                         if (pgetc() == '\n') {
11204                                 startlinno = ++plinno;
11205                                 if (doprompt)
11206                                         setprompt(2);
11207                                 continue;
11208                         }
11209                         pungetc();
11210                         goto breakloop;
11211                 case '\n':
11212                         plinno++;
11213                         needprompt = doprompt;
11214                         RETURN(TNL);
11215                 case PEOF:
11216                         RETURN(TEOF);
11217                 case '&':
11218                         if (pgetc() == '&')
11219                                 RETURN(TAND);
11220                         pungetc();
11221                         RETURN(TBACKGND);
11222                 case '|':
11223                         if (pgetc() == '|')
11224                                 RETURN(TOR);
11225                         pungetc();
11226                         RETURN(TPIPE);
11227                 case ';':
11228                         if (pgetc() == ';')
11229                                 RETURN(TENDCASE);
11230                         pungetc();
11231                         RETURN(TSEMI);
11232                 case '(':
11233                         RETURN(TLP);
11234                 case ')':
11235                         RETURN(TRP);
11236                 default:
11237                         goto breakloop;
11238                 }
11239         }
11240  breakloop:
11241         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11242 #undef RETURN
11243 }
11244 #endif /* NEW_xxreadtoken */
11245
11246 static int
11247 readtoken(void)
11248 {
11249         int t;
11250 #if DEBUG
11251         smallint alreadyseen = tokpushback;
11252 #endif
11253
11254 #if ENABLE_ASH_ALIAS
11255  top:
11256 #endif
11257
11258         t = xxreadtoken();
11259
11260         /*
11261          * eat newlines
11262          */
11263         if (checkkwd & CHKNL) {
11264                 while (t == TNL) {
11265                         parseheredoc();
11266                         t = xxreadtoken();
11267                 }
11268         }
11269
11270         if (t != TWORD || quoteflag) {
11271                 goto out;
11272         }
11273
11274         /*
11275          * check for keywords
11276          */
11277         if (checkkwd & CHKKWD) {
11278                 const char *const *pp;
11279
11280                 pp = findkwd(wordtext);
11281                 if (pp) {
11282                         lasttoken = t = pp - tokname_array;
11283                         TRACE(("keyword %s recognized\n", tokname(t)));
11284                         goto out;
11285                 }
11286         }
11287
11288         if (checkkwd & CHKALIAS) {
11289 #if ENABLE_ASH_ALIAS
11290                 struct alias *ap;
11291                 ap = lookupalias(wordtext, 1);
11292                 if (ap != NULL) {
11293                         if (*ap->val) {
11294                                 pushstring(ap->val, ap);
11295                         }
11296                         goto top;
11297                 }
11298 #endif
11299         }
11300  out:
11301         checkkwd = 0;
11302 #if DEBUG
11303         if (!alreadyseen)
11304                 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11305         else
11306                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11307 #endif
11308         return t;
11309 }
11310
11311 static char
11312 peektoken(void)
11313 {
11314         int t;
11315
11316         t = readtoken();
11317         tokpushback = 1;
11318         return tokname_array[t][0];
11319 }
11320
11321 /*
11322  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
11323  * valid parse tree indicating a blank line.)
11324  */
11325 static union node *
11326 parsecmd(int interact)
11327 {
11328         int t;
11329
11330         tokpushback = 0;
11331         doprompt = interact;
11332         if (doprompt)
11333                 setprompt(doprompt);
11334         needprompt = 0;
11335         t = readtoken();
11336         if (t == TEOF)
11337                 return NEOF;
11338         if (t == TNL)
11339                 return NULL;
11340         tokpushback = 1;
11341         return list(1);
11342 }
11343
11344 /*
11345  * Input any here documents.
11346  */
11347 static void
11348 parseheredoc(void)
11349 {
11350         struct heredoc *here;
11351         union node *n;
11352
11353         here = heredoclist;
11354         heredoclist = NULL;
11355
11356         while (here) {
11357                 if (needprompt) {
11358                         setprompt(2);
11359                 }
11360                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11361                                 here->eofmark, here->striptabs);
11362                 n = stzalloc(sizeof(struct narg));
11363                 n->narg.type = NARG;
11364                 /*n->narg.next = NULL; - stzalloc did it */
11365                 n->narg.text = wordtext;
11366                 n->narg.backquote = backquotelist;
11367                 here->here->nhere.doc = n;
11368                 here = here->next;
11369         }
11370 }
11371
11372
11373 /*
11374  * called by editline -- any expansions to the prompt should be added here.
11375  */
11376 #if ENABLE_ASH_EXPAND_PRMT
11377 static const char *
11378 expandstr(const char *ps)
11379 {
11380         union node n;
11381
11382         /* XXX Fix (char *) cast. */
11383         setinputstring((char *)ps);
11384         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11385         popfile();
11386
11387         n.narg.type = NARG;
11388         n.narg.next = NULL;
11389         n.narg.text = wordtext;
11390         n.narg.backquote = backquotelist;
11391
11392         expandarg(&n, NULL, 0);
11393         return stackblock();
11394 }
11395 #endif
11396
11397 /*
11398  * Execute a command or commands contained in a string.
11399  */
11400 static int
11401 evalstring(char *s, int mask)
11402 {
11403         union node *n;
11404         struct stackmark smark;
11405         int skip;
11406
11407         setinputstring(s);
11408         setstackmark(&smark);
11409
11410         skip = 0;
11411         while ((n = parsecmd(0)) != NEOF) {
11412                 evaltree(n, 0);
11413                 popstackmark(&smark);
11414                 skip = evalskip;
11415                 if (skip)
11416                         break;
11417         }
11418         popfile();
11419
11420         skip &= mask;
11421         evalskip = skip;
11422         return skip;
11423 }
11424
11425 /*
11426  * The eval command.
11427  */
11428 static int
11429 evalcmd(int argc UNUSED_PARAM, char **argv)
11430 {
11431         char *p;
11432         char *concat;
11433
11434         if (argv[1]) {
11435                 p = argv[1];
11436                 argv += 2;
11437                 if (argv[0]) {
11438                         STARTSTACKSTR(concat);
11439                         for (;;) {
11440                                 concat = stack_putstr(p, concat);
11441                                 p = *argv++;
11442                                 if (p == NULL)
11443                                         break;
11444                                 STPUTC(' ', concat);
11445                         }
11446                         STPUTC('\0', concat);
11447                         p = grabstackstr(concat);
11448                 }
11449                 evalstring(p, ~SKIPEVAL);
11450
11451         }
11452         return exitstatus;
11453 }
11454
11455 /*
11456  * Read and execute commands.  "Top" is nonzero for the top level command
11457  * loop; it turns on prompting if the shell is interactive.
11458  */
11459 static int
11460 cmdloop(int top)
11461 {
11462         union node *n;
11463         struct stackmark smark;
11464         int inter;
11465         int numeof = 0;
11466
11467         TRACE(("cmdloop(%d) called\n", top));
11468         for (;;) {
11469                 int skip;
11470
11471                 setstackmark(&smark);
11472 #if JOBS
11473                 if (doing_jobctl)
11474                         showjobs(stderr, SHOW_CHANGED);
11475 #endif
11476                 inter = 0;
11477                 if (iflag && top) {
11478                         inter++;
11479 #if ENABLE_ASH_MAIL
11480                         chkmail();
11481 #endif
11482                 }
11483                 n = parsecmd(inter);
11484                 /* showtree(n); DEBUG */
11485                 if (n == NEOF) {
11486                         if (!top || numeof >= 50)
11487                                 break;
11488                         if (!stoppedjobs()) {
11489                                 if (!Iflag)
11490                                         break;
11491                                 out2str("\nUse \"exit\" to leave shell.\n");
11492                         }
11493                         numeof++;
11494                 } else if (nflag == 0) {
11495                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11496                         job_warning >>= 1;
11497                         numeof = 0;
11498                         evaltree(n, 0);
11499                 }
11500                 popstackmark(&smark);
11501                 skip = evalskip;
11502
11503                 if (skip) {
11504                         evalskip = 0;
11505                         return skip & SKIPEVAL;
11506                 }
11507         }
11508         return 0;
11509 }
11510
11511 /*
11512  * Take commands from a file.  To be compatible we should do a path
11513  * search for the file, which is necessary to find sub-commands.
11514  */
11515 static char *
11516 find_dot_file(char *name)
11517 {
11518         char *fullname;
11519         const char *path = pathval();
11520         struct stat statb;
11521
11522         /* don't try this for absolute or relative paths */
11523         if (strchr(name, '/'))
11524                 return name;
11525
11526         while ((fullname = padvance(&path, name)) != NULL) {
11527                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11528                         /*
11529                          * Don't bother freeing here, since it will
11530                          * be freed by the caller.
11531                          */
11532                         return fullname;
11533                 }
11534                 stunalloc(fullname);
11535         }
11536
11537         /* not found in the PATH */
11538         ash_msg_and_raise_error("%s: not found", name);
11539         /* NOTREACHED */
11540 }
11541
11542 static int
11543 dotcmd(int argc, char **argv)
11544 {
11545         struct strlist *sp;
11546         volatile struct shparam saveparam;
11547         int status = 0;
11548
11549         for (sp = cmdenviron; sp; sp = sp->next)
11550                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11551
11552         if (argv[1]) {        /* That's what SVR2 does */
11553                 char *fullname = find_dot_file(argv[1]);
11554                 argv += 2;
11555                 argc -= 2;
11556                 if (argc) { /* argc > 0, argv[0] != NULL */
11557                         saveparam = shellparam;
11558                         shellparam.malloced = 0;
11559                         shellparam.nparam = argc;
11560                         shellparam.p = argv;
11561                 };
11562
11563                 setinputfile(fullname, INPUT_PUSH_FILE);
11564                 commandname = fullname;
11565                 cmdloop(0);
11566                 popfile();
11567
11568                 if (argc) {
11569                         freeparam(&shellparam);
11570                         shellparam = saveparam;
11571                 };
11572                 status = exitstatus;
11573         }
11574         return status;
11575 }
11576
11577 static int
11578 exitcmd(int argc UNUSED_PARAM, char **argv)
11579 {
11580         if (stoppedjobs())
11581                 return 0;
11582         if (argv[1])
11583                 exitstatus = number(argv[1]);
11584         raise_exception(EXEXIT);
11585         /* NOTREACHED */
11586 }
11587
11588 /*
11589  * Read a file containing shell functions.
11590  */
11591 static void
11592 readcmdfile(char *name)
11593 {
11594         setinputfile(name, INPUT_PUSH_FILE);
11595         cmdloop(0);
11596         popfile();
11597 }
11598
11599
11600 /* ============ find_command inplementation */
11601
11602 /*
11603  * Resolve a command name.  If you change this routine, you may have to
11604  * change the shellexec routine as well.
11605  */
11606 static void
11607 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11608 {
11609         struct tblentry *cmdp;
11610         int idx;
11611         int prev;
11612         char *fullname;
11613         struct stat statb;
11614         int e;
11615         int updatetbl;
11616         struct builtincmd *bcmd;
11617
11618         /* If name contains a slash, don't use PATH or hash table */
11619         if (strchr(name, '/') != NULL) {
11620                 entry->u.index = -1;
11621                 if (act & DO_ABS) {
11622                         while (stat(name, &statb) < 0) {
11623 #ifdef SYSV
11624                                 if (errno == EINTR)
11625                                         continue;
11626 #endif
11627                                 entry->cmdtype = CMDUNKNOWN;
11628                                 return;
11629                         }
11630                 }
11631                 entry->cmdtype = CMDNORMAL;
11632                 return;
11633         }
11634
11635 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11636
11637         updatetbl = (path == pathval());
11638         if (!updatetbl) {
11639                 act |= DO_ALTPATH;
11640                 if (strstr(path, "%builtin") != NULL)
11641                         act |= DO_ALTBLTIN;
11642         }
11643
11644         /* If name is in the table, check answer will be ok */
11645         cmdp = cmdlookup(name, 0);
11646         if (cmdp != NULL) {
11647                 int bit;
11648
11649                 switch (cmdp->cmdtype) {
11650                 default:
11651 #if DEBUG
11652                         abort();
11653 #endif
11654                 case CMDNORMAL:
11655                         bit = DO_ALTPATH;
11656                         break;
11657                 case CMDFUNCTION:
11658                         bit = DO_NOFUNC;
11659                         break;
11660                 case CMDBUILTIN:
11661                         bit = DO_ALTBLTIN;
11662                         break;
11663                 }
11664                 if (act & bit) {
11665                         updatetbl = 0;
11666                         cmdp = NULL;
11667                 } else if (cmdp->rehash == 0)
11668                         /* if not invalidated by cd, we're done */
11669                         goto success;
11670         }
11671
11672         /* If %builtin not in path, check for builtin next */
11673         bcmd = find_builtin(name);
11674         if (bcmd) {
11675                 if (IS_BUILTIN_REGULAR(bcmd))
11676                         goto builtin_success;
11677                 if (act & DO_ALTPATH) {
11678                         if (!(act & DO_ALTBLTIN))
11679                                 goto builtin_success;
11680                 } else if (builtinloc <= 0) {
11681                         goto builtin_success;
11682                 }
11683         }
11684
11685 #if ENABLE_FEATURE_SH_STANDALONE
11686         {
11687                 int applet_no = find_applet_by_name(name);
11688                 if (applet_no >= 0) {
11689                         entry->cmdtype = CMDNORMAL;
11690                         entry->u.index = -2 - applet_no;
11691                         return;
11692                 }
11693         }
11694 #endif
11695
11696         /* We have to search path. */
11697         prev = -1;              /* where to start */
11698         if (cmdp && cmdp->rehash) {     /* doing a rehash */
11699                 if (cmdp->cmdtype == CMDBUILTIN)
11700                         prev = builtinloc;
11701                 else
11702                         prev = cmdp->param.index;
11703         }
11704
11705         e = ENOENT;
11706         idx = -1;
11707  loop:
11708         while ((fullname = padvance(&path, name)) != NULL) {
11709                 stunalloc(fullname);
11710                 /* NB: code below will still use fullname
11711                  * despite it being "unallocated" */
11712                 idx++;
11713                 if (pathopt) {
11714                         if (prefix(pathopt, "builtin")) {
11715                                 if (bcmd)
11716                                         goto builtin_success;
11717                                 continue;
11718                         }
11719                         if ((act & DO_NOFUNC)
11720                          || !prefix(pathopt, "func")
11721                         ) {     /* ignore unimplemented options */
11722                                 continue;
11723                         }
11724                 }
11725                 /* if rehash, don't redo absolute path names */
11726                 if (fullname[0] == '/' && idx <= prev) {
11727                         if (idx < prev)
11728                                 continue;
11729                         TRACE(("searchexec \"%s\": no change\n", name));
11730                         goto success;
11731                 }
11732                 while (stat(fullname, &statb) < 0) {
11733 #ifdef SYSV
11734                         if (errno == EINTR)
11735                                 continue;
11736 #endif
11737                         if (errno != ENOENT && errno != ENOTDIR)
11738                                 e = errno;
11739                         goto loop;
11740                 }
11741                 e = EACCES;     /* if we fail, this will be the error */
11742                 if (!S_ISREG(statb.st_mode))
11743                         continue;
11744                 if (pathopt) {          /* this is a %func directory */
11745                         stalloc(strlen(fullname) + 1);
11746                         /* NB: stalloc will return space pointed by fullname
11747                          * (because we don't have any intervening allocations
11748                          * between stunalloc above and this stalloc) */
11749                         readcmdfile(fullname);
11750                         cmdp = cmdlookup(name, 0);
11751                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11752                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11753                         stunalloc(fullname);
11754                         goto success;
11755                 }
11756                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11757                 if (!updatetbl) {
11758                         entry->cmdtype = CMDNORMAL;
11759                         entry->u.index = idx;
11760                         return;
11761                 }
11762                 INT_OFF;
11763                 cmdp = cmdlookup(name, 1);
11764                 cmdp->cmdtype = CMDNORMAL;
11765                 cmdp->param.index = idx;
11766                 INT_ON;
11767                 goto success;
11768         }
11769
11770         /* We failed.  If there was an entry for this command, delete it */
11771         if (cmdp && updatetbl)
11772                 delete_cmd_entry();
11773         if (act & DO_ERR)
11774                 ash_msg("%s: %s", name, errmsg(e, "not found"));
11775         entry->cmdtype = CMDUNKNOWN;
11776         return;
11777
11778  builtin_success:
11779         if (!updatetbl) {
11780                 entry->cmdtype = CMDBUILTIN;
11781                 entry->u.cmd = bcmd;
11782                 return;
11783         }
11784         INT_OFF;
11785         cmdp = cmdlookup(name, 1);
11786         cmdp->cmdtype = CMDBUILTIN;
11787         cmdp->param.cmd = bcmd;
11788         INT_ON;
11789  success:
11790         cmdp->rehash = 0;
11791         entry->cmdtype = cmdp->cmdtype;
11792         entry->u = cmdp->param;
11793 }
11794
11795
11796 /* ============ trap.c */
11797
11798 /*
11799  * The trap builtin.
11800  */
11801 static int
11802 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11803 {
11804         char *action;
11805         char **ap;
11806         int signo;
11807
11808         nextopt(nullstr);
11809         ap = argptr;
11810         if (!*ap) {
11811                 for (signo = 0; signo < NSIG; signo++) {
11812                         if (trap[signo] != NULL) {
11813                                 const char *sn;
11814
11815                                 sn = get_signame(signo);
11816                                 out1fmt("trap -- %s %s\n",
11817                                         single_quote(trap[signo]), sn);
11818                         }
11819                 }
11820                 return 0;
11821         }
11822         if (!ap[1])
11823                 action = NULL;
11824         else
11825                 action = *ap++;
11826         while (*ap) {
11827                 signo = get_signum(*ap);
11828                 if (signo < 0)
11829                         ash_msg_and_raise_error("%s: bad trap", *ap);
11830                 INT_OFF;
11831                 if (action) {
11832                         if (LONE_DASH(action))
11833                                 action = NULL;
11834                         else
11835                                 action = ckstrdup(action);
11836                 }
11837                 free(trap[signo]);
11838                 trap[signo] = action;
11839                 if (signo != 0)
11840                         setsignal(signo);
11841                 INT_ON;
11842                 ap++;
11843         }
11844         return 0;
11845 }
11846
11847
11848 /* ============ Builtins */
11849
11850 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11851 /*
11852  * Lists available builtins
11853  */
11854 static int
11855 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11856 {
11857         unsigned col;
11858         unsigned i;
11859
11860         out1fmt("\nBuilt-in commands:\n-------------------\n");
11861         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
11862                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11863                                         builtintab[i].name + 1);
11864                 if (col > 60) {
11865                         out1fmt("\n");
11866                         col = 0;
11867                 }
11868         }
11869 #if ENABLE_FEATURE_SH_STANDALONE
11870         {
11871                 const char *a = applet_names;
11872                 while (*a) {
11873                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
11874                         if (col > 60) {
11875                                 out1fmt("\n");
11876                                 col = 0;
11877                         }
11878                         a += strlen(a) + 1;
11879                 }
11880         }
11881 #endif
11882         out1fmt("\n\n");
11883         return EXIT_SUCCESS;
11884 }
11885 #endif /* FEATURE_SH_EXTRA_QUIET */
11886
11887 /*
11888  * The export and readonly commands.
11889  */
11890 static int
11891 exportcmd(int argc UNUSED_PARAM, char **argv)
11892 {
11893         struct var *vp;
11894         char *name;
11895         const char *p;
11896         char **aptr;
11897         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11898
11899         if (nextopt("p") != 'p') {
11900                 aptr = argptr;
11901                 name = *aptr;
11902                 if (name) {
11903                         do {
11904                                 p = strchr(name, '=');
11905                                 if (p != NULL) {
11906                                         p++;
11907                                 } else {
11908                                         vp = *findvar(hashvar(name), name);
11909                                         if (vp) {
11910                                                 vp->flags |= flag;
11911                                                 continue;
11912                                         }
11913                                 }
11914                                 setvar(name, p, flag);
11915                         } while ((name = *++aptr) != NULL);
11916                         return 0;
11917                 }
11918         }
11919         showvars(argv[0], flag, 0);
11920         return 0;
11921 }
11922
11923 /*
11924  * Delete a function if it exists.
11925  */
11926 static void
11927 unsetfunc(const char *name)
11928 {
11929         struct tblentry *cmdp;
11930
11931         cmdp = cmdlookup(name, 0);
11932         if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11933                 delete_cmd_entry();
11934 }
11935
11936 /*
11937  * The unset builtin command.  We unset the function before we unset the
11938  * variable to allow a function to be unset when there is a readonly variable
11939  * with the same name.
11940  */
11941 static int
11942 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11943 {
11944         char **ap;
11945         int i;
11946         int flag = 0;
11947         int ret = 0;
11948
11949         while ((i = nextopt("vf")) != '\0') {
11950                 flag = i;
11951         }
11952
11953         for (ap = argptr; *ap; ap++) {
11954                 if (flag != 'f') {
11955                         i = unsetvar(*ap);
11956                         ret |= i;
11957                         if (!(i & 2))
11958                                 continue;
11959                 }
11960                 if (flag != 'v')
11961                         unsetfunc(*ap);
11962         }
11963         return ret & 1;
11964 }
11965
11966
11967 /*      setmode.c      */
11968
11969 #include <sys/times.h>
11970
11971 static const unsigned char timescmd_str[] ALIGN1 = {
11972         ' ',  offsetof(struct tms, tms_utime),
11973         '\n', offsetof(struct tms, tms_stime),
11974         ' ',  offsetof(struct tms, tms_cutime),
11975         '\n', offsetof(struct tms, tms_cstime),
11976         0
11977 };
11978
11979 static int
11980 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11981 {
11982         long clk_tck, s, t;
11983         const unsigned char *p;
11984         struct tms buf;
11985
11986         clk_tck = sysconf(_SC_CLK_TCK);
11987         times(&buf);
11988
11989         p = timescmd_str;
11990         do {
11991                 t = *(clock_t *)(((char *) &buf) + p[1]);
11992                 s = t / clk_tck;
11993                 out1fmt("%ldm%ld.%.3lds%c",
11994                         s/60, s%60,
11995                         ((t - s * clk_tck) * 1000) / clk_tck,
11996                         p[0]);
11997         } while (*(p += 2));
11998
11999         return 0;
12000 }
12001
12002 #if ENABLE_ASH_MATH_SUPPORT
12003 static arith_t
12004 dash_arith(const char *s)
12005 {
12006         arith_t result;
12007         int errcode = 0;
12008
12009         INT_OFF;
12010         result = arith(s, &errcode);
12011         if (errcode < 0) {
12012                 if (errcode == -3)
12013                         ash_msg_and_raise_error("exponent less than 0");
12014                 if (errcode == -2)
12015                         ash_msg_and_raise_error("divide by zero");
12016                 if (errcode == -5)
12017                         ash_msg_and_raise_error("expression recursion loop detected");
12018                 raise_error_syntax(s);
12019         }
12020         INT_ON;
12021
12022         return result;
12023 }
12024
12025 /*
12026  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12027  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12028  *
12029  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12030  */
12031 static int
12032 letcmd(int argc UNUSED_PARAM, char **argv)
12033 {
12034         arith_t i;
12035
12036         argv++;
12037         if (!*argv)
12038                 ash_msg_and_raise_error("expression expected");
12039         do {
12040                 i = dash_arith(*argv);
12041         } while (*++argv);
12042
12043         return !i;
12044 }
12045 #endif /* ASH_MATH_SUPPORT */
12046
12047
12048 /* ============ miscbltin.c
12049  *
12050  * Miscellaneous builtins.
12051  */
12052
12053 #undef rflag
12054
12055 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12056 typedef enum __rlimit_resource rlim_t;
12057 #endif
12058
12059 /*
12060  * The read builtin. Options:
12061  *      -r              Do not interpret '\' specially
12062  *      -s              Turn off echo (tty only)
12063  *      -n NCHARS       Read NCHARS max
12064  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
12065  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
12066  *      -u FD           Read from given FD instead of fd 0
12067  * This uses unbuffered input, which may be avoidable in some cases.
12068  * TODO: bash also has:
12069  *      -a ARRAY        Read into array[0],[1],etc
12070  *      -d DELIM        End on DELIM char, not newline
12071  *      -e              Use line editing (tty only)
12072  */
12073 static int
12074 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12075 {
12076         static const char *const arg_REPLY[] = { "REPLY", NULL };
12077
12078         char **ap;
12079         int backslash;
12080         char c;
12081         int rflag;
12082         char *prompt;
12083         const char *ifs;
12084         char *p;
12085         int startword;
12086         int status;
12087         int i;
12088         int fd = 0;
12089 #if ENABLE_ASH_READ_NCHARS
12090         int nchars = 0; /* if != 0, -n is in effect */
12091         int silent = 0;
12092         struct termios tty, old_tty;
12093 #endif
12094 #if ENABLE_ASH_READ_TIMEOUT
12095         unsigned end_ms = 0;
12096         unsigned timeout = 0;
12097 #endif
12098
12099         rflag = 0;
12100         prompt = NULL;
12101         while ((i = nextopt("p:u:r"
12102                 USE_ASH_READ_TIMEOUT("t:")
12103                 USE_ASH_READ_NCHARS("n:s")
12104         )) != '\0') {
12105                 switch (i) {
12106                 case 'p':
12107                         prompt = optionarg;
12108                         break;
12109 #if ENABLE_ASH_READ_NCHARS
12110                 case 'n':
12111                         nchars = bb_strtou(optionarg, NULL, 10);
12112                         if (nchars < 0 || errno)
12113                                 ash_msg_and_raise_error("invalid count");
12114                         /* nchars == 0: off (bash 3.2 does this too) */
12115                         break;
12116                 case 's':
12117                         silent = 1;
12118                         break;
12119 #endif
12120 #if ENABLE_ASH_READ_TIMEOUT
12121                 case 't':
12122                         timeout = bb_strtou(optionarg, NULL, 10);
12123                         if (errno || timeout > UINT_MAX / 2048)
12124                                 ash_msg_and_raise_error("invalid timeout");
12125                         timeout *= 1000;
12126 #if 0 /* even bash have no -t N.NNN support */
12127                         ts.tv_sec = bb_strtou(optionarg, &p, 10);
12128                         ts.tv_usec = 0;
12129                         /* EINVAL means number is ok, but not terminated by NUL */
12130                         if (*p == '.' && errno == EINVAL) {
12131                                 char *p2;
12132                                 if (*++p) {
12133                                         int scale;
12134                                         ts.tv_usec = bb_strtou(p, &p2, 10);
12135                                         if (errno)
12136                                                 ash_msg_and_raise_error("invalid timeout");
12137                                         scale = p2 - p;
12138                                         /* normalize to usec */
12139                                         if (scale > 6)
12140                                                 ash_msg_and_raise_error("invalid timeout");
12141                                         while (scale++ < 6)
12142                                                 ts.tv_usec *= 10;
12143                                 }
12144                         } else if (ts.tv_sec < 0 || errno) {
12145                                 ash_msg_and_raise_error("invalid timeout");
12146                         }
12147                         if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12148                                 ash_msg_and_raise_error("invalid timeout");
12149                         }
12150 #endif /* if 0 */
12151                         break;
12152 #endif
12153                 case 'r':
12154                         rflag = 1;
12155                         break;
12156                 case 'u':
12157                         fd = bb_strtou(optionarg, NULL, 10);
12158                         if (fd < 0 || errno)
12159                                 ash_msg_and_raise_error("invalid file descriptor");
12160                         break;
12161                 default:
12162                         break;
12163                 }
12164         }
12165         if (prompt && isatty(fd)) {
12166                 out2str(prompt);
12167         }
12168         ap = argptr;
12169         if (*ap == NULL)
12170                 ap = (char**)arg_REPLY;
12171         ifs = bltinlookup("IFS");
12172         if (ifs == NULL)
12173                 ifs = defifs;
12174 #if ENABLE_ASH_READ_NCHARS
12175         tcgetattr(fd, &tty);
12176         old_tty = tty;
12177         if (nchars || silent) {
12178                 if (nchars) {
12179                         tty.c_lflag &= ~ICANON;
12180                         tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12181                 }
12182                 if (silent) {
12183                         tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12184                 }
12185                 /* if tcgetattr failed, tcsetattr will fail too.
12186                  * Ignoring, it's harmless. */
12187                 tcsetattr(fd, TCSANOW, &tty);
12188         }
12189 #endif
12190
12191         status = 0;
12192         startword = 1;
12193         backslash = 0;
12194 #if ENABLE_ASH_READ_TIMEOUT
12195         if (timeout) /* NB: ensuring end_ms is nonzero */
12196                 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12197 #endif
12198         STARTSTACKSTR(p);
12199         do {
12200 #if ENABLE_ASH_READ_TIMEOUT
12201                 if (end_ms) {
12202                         struct pollfd pfd[1];
12203                         pfd[0].fd = fd;
12204                         pfd[0].events = POLLIN;
12205                         timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12206                         if ((int)timeout <= 0 /* already late? */
12207                          || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12208                         ) { /* timed out! */
12209 #if ENABLE_ASH_READ_NCHARS
12210                                 tcsetattr(fd, TCSANOW, &old_tty);
12211 #endif
12212                                 return 1;
12213                         }
12214                 }
12215 #endif
12216                 if (nonblock_safe_read(fd, &c, 1) != 1) {
12217                         status = 1;
12218                         break;
12219                 }
12220                 if (c == '\0')
12221                         continue;
12222                 if (backslash) {
12223                         backslash = 0;
12224                         if (c != '\n')
12225                                 goto put;
12226                         continue;
12227                 }
12228                 if (!rflag && c == '\\') {
12229                         backslash++;
12230                         continue;
12231                 }
12232                 if (c == '\n')
12233                         break;
12234                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12235                         continue;
12236                 }
12237                 startword = 0;
12238                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12239                         STACKSTRNUL(p);
12240                         setvar(*ap, stackblock(), 0);
12241                         ap++;
12242                         startword = 1;
12243                         STARTSTACKSTR(p);
12244                 } else {
12245  put:
12246                         STPUTC(c, p);
12247                 }
12248         }
12249 /* end of do {} while: */
12250 #if ENABLE_ASH_READ_NCHARS
12251         while (--nchars);
12252 #else
12253         while (1);
12254 #endif
12255
12256 #if ENABLE_ASH_READ_NCHARS
12257         tcsetattr(fd, TCSANOW, &old_tty);
12258 #endif
12259
12260         STACKSTRNUL(p);
12261         /* Remove trailing blanks */
12262         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12263                 *p = '\0';
12264         setvar(*ap, stackblock(), 0);
12265         while (*++ap != NULL)
12266                 setvar(*ap, nullstr, 0);
12267         return status;
12268 }
12269
12270 static int
12271 umaskcmd(int argc UNUSED_PARAM, char **argv)
12272 {
12273         static const char permuser[3] ALIGN1 = "ugo";
12274         static const char permmode[3] ALIGN1 = "rwx";
12275         static const short permmask[] ALIGN2 = {
12276                 S_IRUSR, S_IWUSR, S_IXUSR,
12277                 S_IRGRP, S_IWGRP, S_IXGRP,
12278                 S_IROTH, S_IWOTH, S_IXOTH
12279         };
12280
12281         char *ap;
12282         mode_t mask;
12283         int i;
12284         int symbolic_mode = 0;
12285
12286         while (nextopt("S") != '\0') {
12287                 symbolic_mode = 1;
12288         }
12289
12290         INT_OFF;
12291         mask = umask(0);
12292         umask(mask);
12293         INT_ON;
12294
12295         ap = *argptr;
12296         if (ap == NULL) {
12297                 if (symbolic_mode) {
12298                         char buf[18];
12299                         char *p = buf;
12300
12301                         for (i = 0; i < 3; i++) {
12302                                 int j;
12303
12304                                 *p++ = permuser[i];
12305                                 *p++ = '=';
12306                                 for (j = 0; j < 3; j++) {
12307                                         if ((mask & permmask[3 * i + j]) == 0) {
12308                                                 *p++ = permmode[j];
12309                                         }
12310                                 }
12311                                 *p++ = ',';
12312                         }
12313                         *--p = 0;
12314                         puts(buf);
12315                 } else {
12316                         out1fmt("%.4o\n", mask);
12317                 }
12318         } else {
12319                 if (isdigit((unsigned char) *ap)) {
12320                         mask = 0;
12321                         do {
12322                                 if (*ap >= '8' || *ap < '0')
12323                                         ash_msg_and_raise_error(illnum, argv[1]);
12324                                 mask = (mask << 3) + (*ap - '0');
12325                         } while (*++ap != '\0');
12326                         umask(mask);
12327                 } else {
12328                         mask = ~mask & 0777;
12329                         if (!bb_parse_mode(ap, &mask)) {
12330                                 ash_msg_and_raise_error("illegal mode: %s", ap);
12331                         }
12332                         umask(~mask & 0777);
12333                 }
12334         }
12335         return 0;
12336 }
12337
12338 /*
12339  * ulimit builtin
12340  *
12341  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12342  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12343  * ash by J.T. Conklin.
12344  *
12345  * Public domain.
12346  */
12347
12348 struct limits {
12349         uint8_t cmd;          /* RLIMIT_xxx fit into it */
12350         uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12351         char    option;
12352 };
12353
12354 static const struct limits limits_tbl[] = {
12355 #ifdef RLIMIT_CPU
12356         { RLIMIT_CPU,        0, 't' },
12357 #endif
12358 #ifdef RLIMIT_FSIZE
12359         { RLIMIT_FSIZE,      9, 'f' },
12360 #endif
12361 #ifdef RLIMIT_DATA
12362         { RLIMIT_DATA,      10, 'd' },
12363 #endif
12364 #ifdef RLIMIT_STACK
12365         { RLIMIT_STACK,     10, 's' },
12366 #endif
12367 #ifdef RLIMIT_CORE
12368         { RLIMIT_CORE,       9, 'c' },
12369 #endif
12370 #ifdef RLIMIT_RSS
12371         { RLIMIT_RSS,       10, 'm' },
12372 #endif
12373 #ifdef RLIMIT_MEMLOCK
12374         { RLIMIT_MEMLOCK,   10, 'l' },
12375 #endif
12376 #ifdef RLIMIT_NPROC
12377         { RLIMIT_NPROC,      0, 'p' },
12378 #endif
12379 #ifdef RLIMIT_NOFILE
12380         { RLIMIT_NOFILE,     0, 'n' },
12381 #endif
12382 #ifdef RLIMIT_AS
12383         { RLIMIT_AS,        10, 'v' },
12384 #endif
12385 #ifdef RLIMIT_LOCKS
12386         { RLIMIT_LOCKS,      0, 'w' },
12387 #endif
12388 };
12389 static const char limits_name[] =
12390 #ifdef RLIMIT_CPU
12391         "time(seconds)" "\0"
12392 #endif
12393 #ifdef RLIMIT_FSIZE
12394         "file(blocks)" "\0"
12395 #endif
12396 #ifdef RLIMIT_DATA
12397         "data(kb)" "\0"
12398 #endif
12399 #ifdef RLIMIT_STACK
12400         "stack(kb)" "\0"
12401 #endif
12402 #ifdef RLIMIT_CORE
12403         "coredump(blocks)" "\0"
12404 #endif
12405 #ifdef RLIMIT_RSS
12406         "memory(kb)" "\0"
12407 #endif
12408 #ifdef RLIMIT_MEMLOCK
12409         "locked memory(kb)" "\0"
12410 #endif
12411 #ifdef RLIMIT_NPROC
12412         "process" "\0"
12413 #endif
12414 #ifdef RLIMIT_NOFILE
12415         "nofiles" "\0"
12416 #endif
12417 #ifdef RLIMIT_AS
12418         "vmemory(kb)" "\0"
12419 #endif
12420 #ifdef RLIMIT_LOCKS
12421         "locks" "\0"
12422 #endif
12423 ;
12424
12425 enum limtype { SOFT = 0x1, HARD = 0x2 };
12426
12427 static void
12428 printlim(enum limtype how, const struct rlimit *limit,
12429                         const struct limits *l)
12430 {
12431         rlim_t val;
12432
12433         val = limit->rlim_max;
12434         if (how & SOFT)
12435                 val = limit->rlim_cur;
12436
12437         if (val == RLIM_INFINITY)
12438                 out1fmt("unlimited\n");
12439         else {
12440                 val >>= l->factor_shift;
12441                 out1fmt("%lld\n", (long long) val);
12442         }
12443 }
12444
12445 static int
12446 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12447 {
12448         int c;
12449         rlim_t val = 0;
12450         enum limtype how = SOFT | HARD;
12451         const struct limits *l;
12452         int set, all = 0;
12453         int optc, what;
12454         struct rlimit limit;
12455
12456         what = 'f';
12457         while ((optc = nextopt("HSa"
12458 #ifdef RLIMIT_CPU
12459                                 "t"
12460 #endif
12461 #ifdef RLIMIT_FSIZE
12462                                 "f"
12463 #endif
12464 #ifdef RLIMIT_DATA
12465                                 "d"
12466 #endif
12467 #ifdef RLIMIT_STACK
12468                                 "s"
12469 #endif
12470 #ifdef RLIMIT_CORE
12471                                 "c"
12472 #endif
12473 #ifdef RLIMIT_RSS
12474                                 "m"
12475 #endif
12476 #ifdef RLIMIT_MEMLOCK
12477                                 "l"
12478 #endif
12479 #ifdef RLIMIT_NPROC
12480                                 "p"
12481 #endif
12482 #ifdef RLIMIT_NOFILE
12483                                 "n"
12484 #endif
12485 #ifdef RLIMIT_AS
12486                                 "v"
12487 #endif
12488 #ifdef RLIMIT_LOCKS
12489                                 "w"
12490 #endif
12491                                         )) != '\0')
12492                 switch (optc) {
12493                 case 'H':
12494                         how = HARD;
12495                         break;
12496                 case 'S':
12497                         how = SOFT;
12498                         break;
12499                 case 'a':
12500                         all = 1;
12501                         break;
12502                 default:
12503                         what = optc;
12504                 }
12505
12506         for (l = limits_tbl; l->option != what; l++)
12507                 continue;
12508
12509         set = *argptr ? 1 : 0;
12510         if (set) {
12511                 char *p = *argptr;
12512
12513                 if (all || argptr[1])
12514                         ash_msg_and_raise_error("too many arguments");
12515                 if (strncmp(p, "unlimited\n", 9) == 0)
12516                         val = RLIM_INFINITY;
12517                 else {
12518                         val = (rlim_t) 0;
12519
12520                         while ((c = *p++) >= '0' && c <= '9') {
12521                                 val = (val * 10) + (long)(c - '0');
12522                                 // val is actually 'unsigned long int' and can't get < 0
12523                                 if (val < (rlim_t) 0)
12524                                         break;
12525                         }
12526                         if (c)
12527                                 ash_msg_and_raise_error("bad number");
12528                         val <<= l->factor_shift;
12529                 }
12530         }
12531         if (all) {
12532                 const char *lname = limits_name;
12533                 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12534                         getrlimit(l->cmd, &limit);
12535                         out1fmt("%-20s ", lname);
12536                         lname += strlen(lname) + 1;
12537                         printlim(how, &limit, l);
12538                 }
12539                 return 0;
12540         }
12541
12542         getrlimit(l->cmd, &limit);
12543         if (set) {
12544                 if (how & HARD)
12545                         limit.rlim_max = val;
12546                 if (how & SOFT)
12547                         limit.rlim_cur = val;
12548                 if (setrlimit(l->cmd, &limit) < 0)
12549                         ash_msg_and_raise_error("error setting limit (%m)");
12550         } else {
12551                 printlim(how, &limit, l);
12552         }
12553         return 0;
12554 }
12555
12556
12557 /* ============ Math support */
12558
12559 #if ENABLE_ASH_MATH_SUPPORT
12560
12561 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12562
12563    Permission is hereby granted, free of charge, to any person obtaining
12564    a copy of this software and associated documentation files (the
12565    "Software"), to deal in the Software without restriction, including
12566    without limitation the rights to use, copy, modify, merge, publish,
12567    distribute, sublicense, and/or sell copies of the Software, and to
12568    permit persons to whom the Software is furnished to do so, subject to
12569    the following conditions:
12570
12571    The above copyright notice and this permission notice shall be
12572    included in all copies or substantial portions of the Software.
12573
12574    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12575    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12576    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12577    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12578    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12579    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12580    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12581 */
12582
12583 /* This is my infix parser/evaluator. It is optimized for size, intended
12584  * as a replacement for yacc-based parsers. However, it may well be faster
12585  * than a comparable parser written in yacc. The supported operators are
12586  * listed in #defines below. Parens, order of operations, and error handling
12587  * are supported. This code is thread safe. The exact expression format should
12588  * be that which POSIX specifies for shells. */
12589
12590 /* The code uses a simple two-stack algorithm. See
12591  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12592  * for a detailed explanation of the infix-to-postfix algorithm on which
12593  * this is based (this code differs in that it applies operators immediately
12594  * to the stack instead of adding them to a queue to end up with an
12595  * expression). */
12596
12597 /* To use the routine, call it with an expression string and error return
12598  * pointer */
12599
12600 /*
12601  * Aug 24, 2001              Manuel Novoa III
12602  *
12603  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12604  *
12605  * 1) In arith_apply():
12606  *    a) Cached values of *numptr and &(numptr[-1]).
12607  *    b) Removed redundant test for zero denominator.
12608  *
12609  * 2) In arith():
12610  *    a) Eliminated redundant code for processing operator tokens by moving
12611  *       to a table-based implementation.  Also folded handling of parens
12612  *       into the table.
12613  *    b) Combined all 3 loops which called arith_apply to reduce generated
12614  *       code size at the cost of speed.
12615  *
12616  * 3) The following expressions were treated as valid by the original code:
12617  *       1()  ,    0!  ,    1 ( *3 )   .
12618  *    These bugs have been fixed by internally enclosing the expression in
12619  *    parens and then checking that all binary ops and right parens are
12620  *    preceded by a valid expression (NUM_TOKEN).
12621  *
12622  * Note: It may be desirable to replace Aaron's test for whitespace with
12623  * ctype's isspace() if it is used by another busybox applet or if additional
12624  * whitespace chars should be considered.  Look below the "#include"s for a
12625  * precompiler test.
12626  */
12627
12628 /*
12629  * Aug 26, 2001              Manuel Novoa III
12630  *
12631  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
12632  *
12633  * Merge in Aaron's comments previously posted to the busybox list,
12634  * modified slightly to take account of my changes to the code.
12635  *
12636  */
12637
12638 /*
12639  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12640  *
12641  * - allow access to variable,
12642  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12643  * - realize assign syntax (VAR=expr, +=, *= etc)
12644  * - realize exponentiation (** operator)
12645  * - realize comma separated - expr, expr
12646  * - realise ++expr --expr expr++ expr--
12647  * - realise expr ? expr : expr (but, second expr calculate always)
12648  * - allow hexadecimal and octal numbers
12649  * - was restored loses XOR operator
12650  * - remove one goto label, added three ;-)
12651  * - protect $((num num)) as true zero expr (Manuel`s error)
12652  * - always use special isspace(), see comment from bash ;-)
12653  */
12654
12655 #define arith_isspace(arithval) \
12656         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12657
12658 typedef unsigned char operator;
12659
12660 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12661  * precedence, and 3 high bits are an ID unique across operators of that
12662  * precedence. The ID portion is so that multiple operators can have the
12663  * same precedence, ensuring that the leftmost one is evaluated first.
12664  * Consider * and /. */
12665
12666 #define tok_decl(prec,id) (((id)<<5)|(prec))
12667 #define PREC(op) ((op) & 0x1F)
12668
12669 #define TOK_LPAREN tok_decl(0,0)
12670
12671 #define TOK_COMMA tok_decl(1,0)
12672
12673 #define TOK_ASSIGN tok_decl(2,0)
12674 #define TOK_AND_ASSIGN tok_decl(2,1)
12675 #define TOK_OR_ASSIGN tok_decl(2,2)
12676 #define TOK_XOR_ASSIGN tok_decl(2,3)
12677 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12678 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12679 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12680 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12681
12682 #define TOK_MUL_ASSIGN tok_decl(3,0)
12683 #define TOK_DIV_ASSIGN tok_decl(3,1)
12684 #define TOK_REM_ASSIGN tok_decl(3,2)
12685
12686 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12687 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12688
12689 /* conditional is right associativity too */
12690 #define TOK_CONDITIONAL tok_decl(4,0)
12691 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12692
12693 #define TOK_OR tok_decl(5,0)
12694
12695 #define TOK_AND tok_decl(6,0)
12696
12697 #define TOK_BOR tok_decl(7,0)
12698
12699 #define TOK_BXOR tok_decl(8,0)
12700
12701 #define TOK_BAND tok_decl(9,0)
12702
12703 #define TOK_EQ tok_decl(10,0)
12704 #define TOK_NE tok_decl(10,1)
12705
12706 #define TOK_LT tok_decl(11,0)
12707 #define TOK_GT tok_decl(11,1)
12708 #define TOK_GE tok_decl(11,2)
12709 #define TOK_LE tok_decl(11,3)
12710
12711 #define TOK_LSHIFT tok_decl(12,0)
12712 #define TOK_RSHIFT tok_decl(12,1)
12713
12714 #define TOK_ADD tok_decl(13,0)
12715 #define TOK_SUB tok_decl(13,1)
12716
12717 #define TOK_MUL tok_decl(14,0)
12718 #define TOK_DIV tok_decl(14,1)
12719 #define TOK_REM tok_decl(14,2)
12720
12721 /* exponent is right associativity */
12722 #define TOK_EXPONENT tok_decl(15,1)
12723
12724 /* For now unary operators. */
12725 #define UNARYPREC 16
12726 #define TOK_BNOT tok_decl(UNARYPREC,0)
12727 #define TOK_NOT tok_decl(UNARYPREC,1)
12728
12729 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12730 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12731
12732 #define PREC_PRE (UNARYPREC+2)
12733
12734 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12735 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12736
12737 #define PREC_POST (UNARYPREC+3)
12738
12739 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12740 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12741
12742 #define SPEC_PREC (UNARYPREC+4)
12743
12744 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12745 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12746
12747 #define NUMPTR (*numstackptr)
12748
12749 static int
12750 tok_have_assign(operator op)
12751 {
12752         operator prec = PREC(op);
12753
12754         convert_prec_is_assing(prec);
12755         return (prec == PREC(TOK_ASSIGN) ||
12756                         prec == PREC_PRE || prec == PREC_POST);
12757 }
12758
12759 static int
12760 is_right_associativity(operator prec)
12761 {
12762         return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12763                 || prec == PREC(TOK_CONDITIONAL));
12764 }
12765
12766 typedef struct {
12767         arith_t val;
12768         arith_t contidional_second_val;
12769         char contidional_second_val_initialized;
12770         char *var;      /* if NULL then is regular number,
12771                            else is variable name */
12772 } v_n_t;
12773
12774 typedef struct chk_var_recursive_looped_t {
12775         const char *var;
12776         struct chk_var_recursive_looped_t *next;
12777 } chk_var_recursive_looped_t;
12778
12779 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12780
12781 static int
12782 arith_lookup_val(v_n_t *t)
12783 {
12784         if (t->var) {
12785                 const char * p = lookupvar(t->var);
12786
12787                 if (p) {
12788                         int errcode;
12789
12790                         /* recursive try as expression */
12791                         chk_var_recursive_looped_t *cur;
12792                         chk_var_recursive_looped_t cur_save;
12793
12794                         for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12795                                 if (strcmp(cur->var, t->var) == 0) {
12796                                         /* expression recursion loop detected */
12797                                         return -5;
12798                                 }
12799                         }
12800                         /* save current lookuped var name */
12801                         cur = prev_chk_var_recursive;
12802                         cur_save.var = t->var;
12803                         cur_save.next = cur;
12804                         prev_chk_var_recursive = &cur_save;
12805
12806                         t->val = arith (p, &errcode);
12807                         /* restore previous ptr after recursiving */
12808                         prev_chk_var_recursive = cur;
12809                         return errcode;
12810                 }
12811                 /* allow undefined var as 0 */
12812                 t->val = 0;
12813         }
12814         return 0;
12815 }
12816
12817 /* "applying" a token means performing it on the top elements on the integer
12818  * stack. For a unary operator it will only change the top element, but a
12819  * binary operator will pop two arguments and push a result */
12820 static int
12821 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12822 {
12823         v_n_t *numptr_m1;
12824         arith_t numptr_val, rez;
12825         int ret_arith_lookup_val;
12826
12827         /* There is no operator that can work without arguments */
12828         if (NUMPTR == numstack) goto err;
12829         numptr_m1 = NUMPTR - 1;
12830
12831         /* check operand is var with noninteger value */
12832         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12833         if (ret_arith_lookup_val)
12834                 return ret_arith_lookup_val;
12835
12836         rez = numptr_m1->val;
12837         if (op == TOK_UMINUS)
12838                 rez *= -1;
12839         else if (op == TOK_NOT)
12840                 rez = !rez;
12841         else if (op == TOK_BNOT)
12842                 rez = ~rez;
12843         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12844                 rez++;
12845         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12846                 rez--;
12847         else if (op != TOK_UPLUS) {
12848                 /* Binary operators */
12849
12850                 /* check and binary operators need two arguments */
12851                 if (numptr_m1 == numstack) goto err;
12852
12853                 /* ... and they pop one */
12854                 --NUMPTR;
12855                 numptr_val = rez;
12856                 if (op == TOK_CONDITIONAL) {
12857                         if (! numptr_m1->contidional_second_val_initialized) {
12858                                 /* protect $((expr1 ? expr2)) without ": expr" */
12859                                 goto err;
12860                         }
12861                         rez = numptr_m1->contidional_second_val;
12862                 } else if (numptr_m1->contidional_second_val_initialized) {
12863                         /* protect $((expr1 : expr2)) without "expr ? " */
12864                         goto err;
12865                 }
12866                 numptr_m1 = NUMPTR - 1;
12867                 if (op != TOK_ASSIGN) {
12868                         /* check operand is var with noninteger value for not '=' */
12869                         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12870                         if (ret_arith_lookup_val)
12871                                 return ret_arith_lookup_val;
12872                 }
12873                 if (op == TOK_CONDITIONAL) {
12874                         numptr_m1->contidional_second_val = rez;
12875                 }
12876                 rez = numptr_m1->val;
12877                 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12878                         rez |= numptr_val;
12879                 else if (op == TOK_OR)
12880                         rez = numptr_val || rez;
12881                 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12882                         rez &= numptr_val;
12883                 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12884                         rez ^= numptr_val;
12885                 else if (op == TOK_AND)
12886                         rez = rez && numptr_val;
12887                 else if (op == TOK_EQ)
12888                         rez = (rez == numptr_val);
12889                 else if (op == TOK_NE)
12890                         rez = (rez != numptr_val);
12891                 else if (op == TOK_GE)
12892                         rez = (rez >= numptr_val);
12893                 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12894                         rez >>= numptr_val;
12895                 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12896                         rez <<= numptr_val;
12897                 else if (op == TOK_GT)
12898                         rez = (rez > numptr_val);
12899                 else if (op == TOK_LT)
12900                         rez = (rez < numptr_val);
12901                 else if (op == TOK_LE)
12902                         rez = (rez <= numptr_val);
12903                 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12904                         rez *= numptr_val;
12905                 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12906                         rez += numptr_val;
12907                 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12908                         rez -= numptr_val;
12909                 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12910                         rez = numptr_val;
12911                 else if (op == TOK_CONDITIONAL_SEP) {
12912                         if (numptr_m1 == numstack) {
12913                                 /* protect $((expr : expr)) without "expr ? " */
12914                                 goto err;
12915                         }
12916                         numptr_m1->contidional_second_val_initialized = op;
12917                         numptr_m1->contidional_second_val = numptr_val;
12918                 } else if (op == TOK_CONDITIONAL) {
12919                         rez = rez ?
12920                                 numptr_val : numptr_m1->contidional_second_val;
12921                 } else if (op == TOK_EXPONENT) {
12922                         if (numptr_val < 0)
12923                                 return -3;      /* exponent less than 0 */
12924                         else {
12925                                 arith_t c = 1;
12926
12927                                 if (numptr_val)
12928                                         while (numptr_val--)
12929                                                 c *= rez;
12930                                 rez = c;
12931                         }
12932                 } else if (numptr_val==0)          /* zero divisor check */
12933                         return -2;
12934                 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12935                         rez /= numptr_val;
12936                 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12937                         rez %= numptr_val;
12938         }
12939         if (tok_have_assign(op)) {
12940                 char buf[sizeof(arith_t_type)*3 + 2];
12941
12942                 if (numptr_m1->var == NULL) {
12943                         /* Hmm, 1=2 ? */
12944                         goto err;
12945                 }
12946                 /* save to shell variable */
12947 #if ENABLE_ASH_MATH_SUPPORT_64
12948                 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12949 #else
12950                 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12951 #endif
12952                 setvar(numptr_m1->var, buf, 0);
12953                 /* after saving, make previous value for v++ or v-- */
12954                 if (op == TOK_POST_INC)
12955                         rez--;
12956                 else if (op == TOK_POST_DEC)
12957                         rez++;
12958         }
12959         numptr_m1->val = rez;
12960         /* protect geting var value, is number now */
12961         numptr_m1->var = NULL;
12962         return 0;
12963  err:
12964         return -1;
12965 }
12966
12967 /* longest must be first */
12968 static const char op_tokens[] ALIGN1 = {
12969         '<','<','=',0, TOK_LSHIFT_ASSIGN,
12970         '>','>','=',0, TOK_RSHIFT_ASSIGN,
12971         '<','<',    0, TOK_LSHIFT,
12972         '>','>',    0, TOK_RSHIFT,
12973         '|','|',    0, TOK_OR,
12974         '&','&',    0, TOK_AND,
12975         '!','=',    0, TOK_NE,
12976         '<','=',    0, TOK_LE,
12977         '>','=',    0, TOK_GE,
12978         '=','=',    0, TOK_EQ,
12979         '|','=',    0, TOK_OR_ASSIGN,
12980         '&','=',    0, TOK_AND_ASSIGN,
12981         '*','=',    0, TOK_MUL_ASSIGN,
12982         '/','=',    0, TOK_DIV_ASSIGN,
12983         '%','=',    0, TOK_REM_ASSIGN,
12984         '+','=',    0, TOK_PLUS_ASSIGN,
12985         '-','=',    0, TOK_MINUS_ASSIGN,
12986         '-','-',    0, TOK_POST_DEC,
12987         '^','=',    0, TOK_XOR_ASSIGN,
12988         '+','+',    0, TOK_POST_INC,
12989         '*','*',    0, TOK_EXPONENT,
12990         '!',        0, TOK_NOT,
12991         '<',        0, TOK_LT,
12992         '>',        0, TOK_GT,
12993         '=',        0, TOK_ASSIGN,
12994         '|',        0, TOK_BOR,
12995         '&',        0, TOK_BAND,
12996         '*',        0, TOK_MUL,
12997         '/',        0, TOK_DIV,
12998         '%',        0, TOK_REM,
12999         '+',        0, TOK_ADD,
13000         '-',        0, TOK_SUB,
13001         '^',        0, TOK_BXOR,
13002         /* uniq */
13003         '~',        0, TOK_BNOT,
13004         ',',        0, TOK_COMMA,
13005         '?',        0, TOK_CONDITIONAL,
13006         ':',        0, TOK_CONDITIONAL_SEP,
13007         ')',        0, TOK_RPAREN,
13008         '(',        0, TOK_LPAREN,
13009         0
13010 };
13011 /* ptr to ")" */
13012 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13013
13014 static arith_t
13015 arith(const char *expr, int *perrcode)
13016 {
13017         char arithval; /* Current character under analysis */
13018         operator lasttok, op;
13019         operator prec;
13020         operator *stack, *stackptr;
13021         const char *p = endexpression;
13022         int errcode;
13023         v_n_t *numstack, *numstackptr;
13024         unsigned datasizes = strlen(expr) + 2;
13025
13026         /* Stack of integers */
13027         /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13028          * in any given correct or incorrect expression is left as an exercise to
13029          * the reader. */
13030         numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13031         /* Stack of operator tokens */
13032         stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13033
13034         *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
13035         *perrcode = errcode = 0;
13036
13037         while (1) {
13038                 arithval = *expr;
13039                 if (arithval == 0) {
13040                         if (p == endexpression) {
13041                                 /* Null expression. */
13042                                 return 0;
13043                         }
13044
13045                         /* This is only reached after all tokens have been extracted from the
13046                          * input stream. If there are still tokens on the operator stack, they
13047                          * are to be applied in order. At the end, there should be a final
13048                          * result on the integer stack */
13049
13050                         if (expr != endexpression + 1) {
13051                                 /* If we haven't done so already, */
13052                                 /* append a closing right paren */
13053                                 expr = endexpression;
13054                                 /* and let the loop process it. */
13055                                 continue;
13056                         }
13057                         /* At this point, we're done with the expression. */
13058                         if (numstackptr != numstack+1) {
13059                                 /* ... but if there isn't, it's bad */
13060  err:
13061                                 *perrcode = -1;
13062                                 return *perrcode;
13063                         }
13064                         if (numstack->var) {
13065                                 /* expression is $((var)) only, lookup now */
13066                                 errcode = arith_lookup_val(numstack);
13067                         }
13068  ret:
13069                         *perrcode = errcode;
13070                         return numstack->val;
13071                 }
13072
13073                 /* Continue processing the expression. */
13074                 if (arith_isspace(arithval)) {
13075                         /* Skip whitespace */
13076                         goto prologue;
13077                 }
13078                 p = endofname(expr);
13079                 if (p != expr) {
13080                         size_t var_name_size = (p-expr) + 1;  /* trailing zero */
13081
13082                         numstackptr->var = alloca(var_name_size);
13083                         safe_strncpy(numstackptr->var, expr, var_name_size);
13084                         expr = p;
13085  num:
13086                         numstackptr->contidional_second_val_initialized = 0;
13087                         numstackptr++;
13088                         lasttok = TOK_NUM;
13089                         continue;
13090                 }
13091                 if (isdigit(arithval)) {
13092                         numstackptr->var = NULL;
13093 #if ENABLE_ASH_MATH_SUPPORT_64
13094                         numstackptr->val = strtoll(expr, (char **) &expr, 0);
13095 #else
13096                         numstackptr->val = strtol(expr, (char **) &expr, 0);
13097 #endif
13098                         goto num;
13099                 }
13100                 for (p = op_tokens; ; p++) {
13101                         const char *o;
13102
13103                         if (*p == 0) {
13104                                 /* strange operator not found */
13105                                 goto err;
13106                         }
13107                         for (o = expr; *p && *o == *p; p++)
13108                                 o++;
13109                         if (! *p) {
13110                                 /* found */
13111                                 expr = o - 1;
13112                                 break;
13113                         }
13114                         /* skip tail uncompared token */
13115                         while (*p)
13116                                 p++;
13117                         /* skip zero delim */
13118                         p++;
13119                 }
13120                 op = p[1];
13121
13122                 /* post grammar: a++ reduce to num */
13123                 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13124                         lasttok = TOK_NUM;
13125
13126                 /* Plus and minus are binary (not unary) _only_ if the last
13127                  * token was as number, or a right paren (which pretends to be
13128                  * a number, since it evaluates to one). Think about it.
13129                  * It makes sense. */
13130                 if (lasttok != TOK_NUM) {
13131                         switch (op) {
13132                         case TOK_ADD:
13133                                 op = TOK_UPLUS;
13134                                 break;
13135                         case TOK_SUB:
13136                                 op = TOK_UMINUS;
13137                                 break;
13138                         case TOK_POST_INC:
13139                                 op = TOK_PRE_INC;
13140                                 break;
13141                         case TOK_POST_DEC:
13142                                 op = TOK_PRE_DEC;
13143                                 break;
13144                         }
13145                 }
13146                 /* We don't want a unary operator to cause recursive descent on the
13147                  * stack, because there can be many in a row and it could cause an
13148                  * operator to be evaluated before its argument is pushed onto the
13149                  * integer stack. */
13150                 /* But for binary operators, "apply" everything on the operator
13151                  * stack until we find an operator with a lesser priority than the
13152                  * one we have just extracted. */
13153                 /* Left paren is given the lowest priority so it will never be
13154                  * "applied" in this way.
13155                  * if associativity is right and priority eq, applied also skip
13156                  */
13157                 prec = PREC(op);
13158                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13159                         /* not left paren or unary */
13160                         if (lasttok != TOK_NUM) {
13161                                 /* binary op must be preceded by a num */
13162                                 goto err;
13163                         }
13164                         while (stackptr != stack) {
13165                                 if (op == TOK_RPAREN) {
13166                                         /* The algorithm employed here is simple: while we don't
13167                                          * hit an open paren nor the bottom of the stack, pop
13168                                          * tokens and apply them */
13169                                         if (stackptr[-1] == TOK_LPAREN) {
13170                                                 --stackptr;
13171                                                 /* Any operator directly after a */
13172                                                 lasttok = TOK_NUM;
13173                                                 /* close paren should consider itself binary */
13174                                                 goto prologue;
13175                                         }
13176                                 } else {
13177                                         operator prev_prec = PREC(stackptr[-1]);
13178
13179                                         convert_prec_is_assing(prec);
13180                                         convert_prec_is_assing(prev_prec);
13181                                         if (prev_prec < prec)
13182                                                 break;
13183                                         /* check right assoc */
13184                                         if (prev_prec == prec && is_right_associativity(prec))
13185                                                 break;
13186                                 }
13187                                 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13188                                 if (errcode) goto ret;
13189                         }
13190                         if (op == TOK_RPAREN) {
13191                                 goto err;
13192                         }
13193                 }
13194
13195                 /* Push this operator to the stack and remember it. */
13196                 *stackptr++ = lasttok = op;
13197  prologue:
13198                 ++expr;
13199         } /* while */
13200 }
13201 #endif /* ASH_MATH_SUPPORT */
13202
13203
13204 /* ============ main() and helpers */
13205
13206 /*
13207  * Called to exit the shell.
13208  */
13209 static void exitshell(void) NORETURN;
13210 static void
13211 exitshell(void)
13212 {
13213         struct jmploc loc;
13214         char *p;
13215         int status;
13216
13217         status = exitstatus;
13218         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13219         if (setjmp(loc.loc)) {
13220                 if (exception == EXEXIT)
13221 /* dash bug: it just does _exit(exitstatus) here
13222  * but we have to do setjobctl(0) first!
13223  * (bug is still not fixed in dash-0.5.3 - if you run dash
13224  * under Midnight Commander, on exit from dash MC is backgrounded) */
13225                         status = exitstatus;
13226                 goto out;
13227         }
13228         exception_handler = &loc;
13229         p = trap[0];
13230         if (p) {
13231                 trap[0] = NULL;
13232                 evalstring(p, 0);
13233         }
13234         flush_stdout_stderr();
13235  out:
13236         setjobctl(0);
13237         _exit(status);
13238         /* NOTREACHED */
13239 }
13240
13241 static void
13242 init(void)
13243 {
13244         /* from input.c: */
13245         basepf.nextc = basepf.buf = basebuf;
13246
13247         /* from trap.c: */
13248         signal(SIGCHLD, SIG_DFL);
13249
13250         /* from var.c: */
13251         {
13252                 char **envp;
13253                 char ppid[sizeof(int)*3 + 1];
13254                 const char *p;
13255                 struct stat st1, st2;
13256
13257                 initvar();
13258                 for (envp = environ; envp && *envp; envp++) {
13259                         if (strchr(*envp, '=')) {
13260                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13261                         }
13262                 }
13263
13264                 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13265                 setvar("PPID", ppid, 0);
13266
13267                 p = lookupvar("PWD");
13268                 if (p)
13269                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13270                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13271                                 p = '\0';
13272                 setpwd(p, 0);
13273         }
13274 }
13275
13276 /*
13277  * Process the shell command line arguments.
13278  */
13279 static void
13280 procargs(char **argv)
13281 {
13282         int i;
13283         const char *xminusc;
13284         char **xargv;
13285
13286         xargv = argv;
13287         arg0 = xargv[0];
13288         /* if (xargv[0]) - mmm, this is always true! */
13289                 xargv++;
13290         for (i = 0; i < NOPTS; i++)
13291                 optlist[i] = 2;
13292         argptr = xargv;
13293         if (options(1)) {
13294                 /* it already printed err message */
13295                 raise_exception(EXERROR);
13296         }
13297         xargv = argptr;
13298         xminusc = minusc;
13299         if (*xargv == NULL) {
13300                 if (xminusc)
13301                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13302                 sflag = 1;
13303         }
13304         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13305                 iflag = 1;
13306         if (mflag == 2)
13307                 mflag = iflag;
13308         for (i = 0; i < NOPTS; i++)
13309                 if (optlist[i] == 2)
13310                         optlist[i] = 0;
13311 #if DEBUG == 2
13312         debug = 1;
13313 #endif
13314         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13315         if (xminusc) {
13316                 minusc = *xargv++;
13317                 if (*xargv)
13318                         goto setarg0;
13319         } else if (!sflag) {
13320                 setinputfile(*xargv, 0);
13321  setarg0:
13322                 arg0 = *xargv++;
13323                 commandname = arg0;
13324         }
13325
13326         shellparam.p = xargv;
13327 #if ENABLE_ASH_GETOPTS
13328         shellparam.optind = 1;
13329         shellparam.optoff = -1;
13330 #endif
13331         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13332         while (*xargv) {
13333                 shellparam.nparam++;
13334                 xargv++;
13335         }
13336         optschanged();
13337 }
13338
13339 /*
13340  * Read /etc/profile or .profile.
13341  */
13342 static void
13343 read_profile(const char *name)
13344 {
13345         int skip;
13346
13347         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13348                 return;
13349         skip = cmdloop(0);
13350         popfile();
13351         if (skip)
13352                 exitshell();
13353 }
13354
13355 /*
13356  * This routine is called when an error or an interrupt occurs in an
13357  * interactive shell and control is returned to the main command loop.
13358  */
13359 static void
13360 reset(void)
13361 {
13362         /* from eval.c: */
13363         evalskip = 0;
13364         loopnest = 0;
13365         /* from input.c: */
13366         parselleft = parsenleft = 0;      /* clear input buffer */
13367         popallfiles();
13368         /* from parser.c: */
13369         tokpushback = 0;
13370         checkkwd = 0;
13371         /* from redir.c: */
13372         clearredir(0);
13373 }
13374
13375 #if PROFILE
13376 static short profile_buf[16384];
13377 extern int etext();
13378 #endif
13379
13380 /*
13381  * Main routine.  We initialize things, parse the arguments, execute
13382  * profiles if we're a login shell, and then call cmdloop to execute
13383  * commands.  The setjmp call sets up the location to jump to when an
13384  * exception occurs.  When an exception occurs the variable "state"
13385  * is used to figure out how far we had gotten.
13386  */
13387 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13388 int ash_main(int argc UNUSED_PARAM, char **argv)
13389 {
13390         char *shinit;
13391         volatile int state;
13392         struct jmploc jmploc;
13393         struct stackmark smark;
13394
13395         /* Initialize global data */
13396         INIT_G_misc();
13397         INIT_G_memstack();
13398         INIT_G_var();
13399 #if ENABLE_ASH_ALIAS
13400         INIT_G_alias();
13401 #endif
13402         INIT_G_cmdtable();
13403
13404 #if PROFILE
13405         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13406 #endif
13407
13408 #if ENABLE_FEATURE_EDITING
13409         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13410 #endif
13411         state = 0;
13412         if (setjmp(jmploc.loc)) {
13413                 int e;
13414                 int s;
13415
13416                 reset();
13417
13418                 e = exception;
13419                 if (e == EXERROR)
13420                         exitstatus = 2;
13421                 s = state;
13422                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13423                         exitshell();
13424
13425                 if (e == EXINT) {
13426                         outcslow('\n', stderr);
13427                 }
13428                 popstackmark(&smark);
13429                 FORCE_INT_ON; /* enable interrupts */
13430                 if (s == 1)
13431                         goto state1;
13432                 if (s == 2)
13433                         goto state2;
13434                 if (s == 3)
13435                         goto state3;
13436                 goto state4;
13437         }
13438         exception_handler = &jmploc;
13439 #if DEBUG
13440         opentrace();
13441         trace_puts("Shell args: ");
13442         trace_puts_args(argv);
13443 #endif
13444         rootpid = getpid();
13445
13446 #if ENABLE_ASH_RANDOM_SUPPORT
13447         /* Can use monotonic_ns() for better randomness but for now it is
13448          * not used anywhere else in busybox... so avoid bloat */
13449         random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13450 #endif
13451         init();
13452         setstackmark(&smark);
13453         procargs(argv);
13454
13455 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13456         if (iflag) {
13457                 const char *hp = lookupvar("HISTFILE");
13458
13459                 if (hp == NULL) {
13460                         hp = lookupvar("HOME");
13461                         if (hp != NULL) {
13462                                 char *defhp = concat_path_file(hp, ".ash_history");
13463                                 setvar("HISTFILE", defhp, 0);
13464                                 free(defhp);
13465                         }
13466                 }
13467         }
13468 #endif
13469         if (argv[0] && argv[0][0] == '-')
13470                 isloginsh = 1;
13471         if (isloginsh) {
13472                 state = 1;
13473                 read_profile("/etc/profile");
13474  state1:
13475                 state = 2;
13476                 read_profile(".profile");
13477         }
13478  state2:
13479         state = 3;
13480         if (
13481 #ifndef linux
13482          getuid() == geteuid() && getgid() == getegid() &&
13483 #endif
13484          iflag
13485         ) {
13486                 shinit = lookupvar("ENV");
13487                 if (shinit != NULL && *shinit != '\0') {
13488                         read_profile(shinit);
13489                 }
13490         }
13491  state3:
13492         state = 4;
13493         if (minusc)
13494                 evalstring(minusc, 0);
13495
13496         if (sflag || minusc == NULL) {
13497 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13498                 if (iflag) {
13499                         const char *hp = lookupvar("HISTFILE");
13500
13501                         if (hp != NULL)
13502                                 line_input_state->hist_file = hp;
13503                 }
13504 #endif
13505  state4: /* XXX ??? - why isn't this before the "if" statement */
13506                 cmdloop(1);
13507         }
13508 #if PROFILE
13509         monitor(0);
13510 #endif
13511 #ifdef GPROF
13512         {
13513                 extern void _mcleanup(void);
13514                 _mcleanup();
13515         }
13516 #endif
13517         exitshell();
13518         /* NOTREACHED */
13519 }
13520
13521 #if DEBUG
13522 const char *applet_name = "debug stuff usage";
13523 int main(int argc, char **argv)
13524 {
13525         return ash_main(argc, argv);
13526 }
13527 #endif
13528
13529
13530 /*-
13531  * Copyright (c) 1989, 1991, 1993, 1994
13532  *      The Regents of the University of California.  All rights reserved.
13533  *
13534  * This code is derived from software contributed to Berkeley by
13535  * Kenneth Almquist.
13536  *
13537  * Redistribution and use in source and binary forms, with or without
13538  * modification, are permitted provided that the following conditions
13539  * are met:
13540  * 1. Redistributions of source code must retain the above copyright
13541  *    notice, this list of conditions and the following disclaimer.
13542  * 2. Redistributions in binary form must reproduce the above copyright
13543  *    notice, this list of conditions and the following disclaimer in the
13544  *    documentation and/or other materials provided with the distribution.
13545  * 3. Neither the name of the University nor the names of its contributors
13546  *    may be used to endorse or promote products derived from this software
13547  *    without specific prior written permission.
13548  *
13549  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13550  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13551  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13552  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13553  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13554  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13555  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13556  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13557  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13558  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13559  * SUCH DAMAGE.
13560  */