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