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