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