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